diff options
Diffstat (limited to 'packages')
1213 files changed, 21937 insertions, 11305 deletions
diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml index e67b3be43ea1..44aa1b1b8747 100644 --- a/packages/BackupRestoreConfirmation/AndroidManifest.xml +++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml @@ -26,7 +26,8 @@ android:allowBackup="false" android:permission="android.permission.CONFIRM_FULL_BACKUP" > - <activity android:name=".BackupRestoreConfirmation" + <activity android:name=".BackupRestoreConfirmation" + android:theme="@style/OptOutEdgeToEdgeEnforcement" android:title="" android:windowSoftInputMode="stateAlwaysHidden" android:excludeFromRecents="true" diff --git a/packages/BackupRestoreConfirmation/res/values/styles.xml b/packages/BackupRestoreConfirmation/res/values/styles.xml new file mode 100644 index 000000000000..ce54568ed6d6 --- /dev/null +++ b/packages/BackupRestoreConfirmation/res/values/styles.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- + TODO(b/309578419): Make activities handle insets properly and then remove this. + --> + <style name="OptOutEdgeToEdgeEnforcement"> + <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> + </style> +</resources> diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml index 183965e6723a..d2df0e4f5d0d 100644 --- a/packages/CompanionDeviceManager/res/values-ar/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml @@ -27,10 +27,10 @@ <string name="summary_glasses" msgid="2872254734959842579">"سيتم السماح لهذا التطبيق بالوصول إلى هذه الأذونات على \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string> <string name="title_app_streaming" msgid="2270331024626446950">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من هاتفك"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"هل تريد منح <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> إذنًا لبث التطبيقات المُثبَّتة على هاتفك؟"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"سيتمكّن \"%1$s\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على الهاتف، بما في ذلك الملفات الصوتية والصور وكلمات المرور والرسائل.<br/><br/>سيتمكّن \"%1$s\" من بث التطبيقات إلى أنّ توقف إمكانية استخدام هذا الإذن."</string> + <string name="summary_app_streaming" msgid="295548145144086753">"سيتمكّن %1$s من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على الهاتف، بما في ذلك الملفات الصوتية والصور وكلمات المرور والرسائل.<br/><br/>سيتمكّن %1$s من بث التطبيقات إلى أن توقف إمكانية استخدام هذا الإذن."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"يطلب تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" لبثّ محتوى التطبيقات بين أجهزتك."</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" لعرض التطبيقات وبثها بين أجهزتك"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"تطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> لعرض التطبيقات وبثها بين أجهزتك"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من هاتفك"</string> @@ -39,7 +39,7 @@ <string name="helper_summary_computer" msgid="8774832742608187072">"يطلب تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" للوصول إلى الصور والوسائط والإشعارات في هاتفك."</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"هل تريد السماح للتطبيق <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> باتّخاذ هذا الإجراء؟"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"هل تريد منح <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> إذنًا لبث التطبيقات والوصول إلى ميزات النظام على هاتفك؟"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"سيتمكّن \"%1$s\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على هاتفك، بما في ذلك الملفات الصوتية والصور ومعلومات الدفع وكلمات المرور والرسائل.<br/><br/>سيتمكّن \"%1$s\" من بث التطبيقات والوصول إلى ميزات النظام إلى أنّ توقف إمكانية استخدام هذا الإذن."</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"سيتمكّن %1$s من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على هاتفك، بما في ذلك الملفات الصوتية والصور ومعلومات الدفع وكلمات المرور والرسائل.<br/><br/>سيتمكّن %1$s من بث التطبيقات والوصول إلى ميزات النظام إلى أن توقف إمكانية استخدام هذا الإذن."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" لبثّ التطبيقات وميزات النظام الأخرى إلى أجهزتك المجاورة."</string> <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string> <string name="summary_generic" msgid="1761976003668044801">"سيتمكّن هذا التطبيق من مزامنة المعلومات، مثل اسم المتصل، بين هاتفك والجهاز المحدّد."</string> diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml index 4fb9ceed1c6c..2316baadf480 100644 --- a/packages/CompanionDeviceManager/res/values-bg/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"%1$s ще има достъп до всичко, което се показва или възпроизвежда на телефона, включително аудиосъдържание, снимки, пароли и съобщения.<br/><br/>%1$s ще може да предава поточно приложения, докато не премахнете това разрешение."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> да показва и да предава поточно приложения между устройствата ви"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ иска разрешение от името на <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> да показва и да предава поточно приложения между устройствата ви"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от телефона ви"</string> diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml index 231d395e2a8e..247d017f4b16 100644 --- a/packages/CompanionDeviceManager/res/values-bs/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml @@ -26,7 +26,7 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string> <string name="summary_glasses" msgid="2872254734959842579">"Aplikaciji će biti dozvoljen pristup ovim odobrenjima na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama s telefona"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Dozvoliti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da prenosi aplikacije telefona?"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Dozvoliti uređaju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da prenosi aplikacije telefona?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"%1$s će imati pristup svemu što je vidljivo ili se reproducira na telefonu, uključujući zvuk, fotografije, lozinke i poruke.<br/><br/>%1$s će moći prenositi aplikacije dok ne uklonite pristup ovom odobrenju."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string> @@ -59,7 +59,7 @@ <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string> <string name="permission_call_logs" msgid="5546761417694586041">"Zapisnici poziva"</string> <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string> - <string name="permission_media_routing_control" msgid="5498639511586715253">"Promijeni izlaz med. sadržaja"</string> + <string name="permission_media_routing_control" msgid="5498639511586715253">"Promjena medijskog izlaza"</string> <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string> <string name="permission_notifications" msgid="4099418516590632909">"Obavještenja"</string> <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string> diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml index 94510e3d4ca7..3acd1798f990 100644 --- a/packages/CompanionDeviceManager/res/values-cs/strings.xml +++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml @@ -27,7 +27,7 @@ <string name="summary_glasses" msgid="2872254734959842579">"Tato aplikace bude mít ve vašem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> povolený přístup k těmto oprávněním"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho telefonu"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Povolit zařízení <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovat aplikace telefonu?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"Aplikace %1$s bude mít přístup ke všemu, co zobrazíte nebo přehrajete na telefonu, včetně zvuku, fotek, hesel a zpráv.<br/><br/>%1$s bude moci streamovat aplikace, dokud přístup k tomuto oprávnění neodeberete."</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s bude mít přístup ke všemu, co na telefonu zobrazíte nebo přehrajete, včetně zvuku, fotek, hesel a zpráv.<br/><br/>%1$s bude moci streamovat aplikace, dokud přístup k tomuto oprávnění neodeberete."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> oprávnění ke streamování aplikací mezi zařízeními"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> oprávnění k zobrazení a streamování obsahu mezi zařízeními"</string> @@ -39,7 +39,7 @@ <string name="helper_summary_computer" msgid="8774832742608187072">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> oprávnění k přístupu k fotkám, médiím a oznámením v telefonu"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Povolit zařízení <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> podniknout tuto akci?"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Povolit zařízení <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> streamovat aplikace a systémové funkce telefonu?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"Aplikace %1$s bude mít přístup ke všemu, co zobrazíte nebo přehrajete na telefonu, včetně zvuku, fotek, platebních údajů, hesel a zpráv.<br/><br/>%1$s bude moci streamovat aplikace a systémové funkce, dokud přístup k tomuto oprávnění neodeberete."</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s bude mít přístup ke všemu, co na telefonu zobrazíte nebo přehrajete, včetně zvuku, fotek, platebních údajů, hesel a zpráv.<br/><br/>%1$s bude moci streamovat aplikace a systémové funkce, dokud přístup k tomuto oprávnění neodeberete."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> žádá jménem vašeho zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o oprávnění streamovat aplikace a další systémové funkce do zařízení v okolí"</string> <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string> <string name="summary_generic" msgid="1761976003668044801">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a vybraným zařízením"</string> diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml index 6b38bff17b4c..9d0846c554c0 100644 --- a/packages/CompanionDeviceManager/res/values-da/strings.xml +++ b/packages/CompanionDeviceManager/res/values-da/strings.xml @@ -28,7 +28,7 @@ <string name="title_app_streaming" msgid="2270331024626446950">"Giv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adgang til disse oplysninger fra din telefon"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Vil du give <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at streame din telefons apps?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"%1$s har adgang til alt, der er synligt eller afspilles på telefonen, herunder lyd, billeder, adgangskoder og beskeder.<br/><br/>%1$s kan streame apps, indtil du fjerner adgangen til denne tilladelse."</string> - <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester til flere enheder"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> til at streame apps mellem dine enheder"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> til at vise og streame apps mellem dine enheder"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml index 65e923c67857..3f730fc82b30 100644 --- a/packages/CompanionDeviceManager/res/values-de/strings.xml +++ b/packages/CompanionDeviceManager/res/values-de/strings.xml @@ -26,11 +26,11 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"Gerät"</string> <string name="summary_glasses" msgid="2872254734959842579">"Diese App darf dann auf diese Berechtigungen auf deinem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zugreifen:"</string> <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> erlauben, die Apps auf deinem Smartphone zu streamen?"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Zulassen, dass <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> die Apps auf deinem Smartphone streamt?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"%1$s hat dann Zugriff auf alle Inhalte, die auf deinem Smartphone sichtbar sind oder abgespielt werden, einschließlich Audio, Fotos, Passwörter und Nachrichten.<br/><br/>%1$s kann so lange Apps streamen, bis du diese Berechtigung entfernst."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung zum Anzeigen und Streamen von Apps zwischen deinen Geräten"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung, gegenseitig das Anzeigen und Streamen von Apps zu erlauben"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-Dienste"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen deines <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung zum Zugriff auf die Fotos, Medien und Benachrichtigungen deines Smartphones"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Darf das Gerät <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> diese Aktion ausführen?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> erlauben, die Apps und Systemfunktionen auf deinem Smartphone zu streamen?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s hat dann Zugriff auf alle Inhalte, die auf deinem Smartphone sichtbar sind oder abgespielt werden, einschließlich Audio, Fotos, Zahlungsinformationen, Passwörter und Nachrichten.<br/><br/>%1$s kann so lange Apps und Systemfunktionen streamen, bis du diese Berechtigung entfernst."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Zulassen, dass <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> die Apps und Systemfunktionen auf deinem Smartphone streamt?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s hat dann Zugriff auf alle Inhalte, die auf deinem Smartphone sichtbar sind oder abgespielt werden, einschließlich Audio, Fotos, Zahlungsinformationen, Passwörter und Nachrichten.<br/><br/>%1$s kann so lange Apps und Systemfunktionen streamen, bis du diese Berechtigung entfernst."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein Gerät (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) um die Berechtigung, Apps und andere Systemfunktionen auf Geräte in der Nähe zu streamen"</string> <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string> <string name="summary_generic" msgid="1761976003668044801">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren"</string> diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml index c0d1888791e4..15d97af5ce0d 100644 --- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml +++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml @@ -59,7 +59,7 @@ <string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string> <string name="permission_call_logs" msgid="5546761417694586041">"Registros de llamadas"</string> <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string> - <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambia la salida multimedia"</string> + <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambiar la salida multimedia"</string> <string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string> <string name="permission_notifications" msgid="4099418516590632909">"Notificaciones"</string> <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string> diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml index b7a9ff632fba..e02cb04a6489 100644 --- a/packages/CompanionDeviceManager/res/values-et/strings.xml +++ b/packages/CompanionDeviceManager/res/values-et/strings.xml @@ -26,21 +26,21 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"seade"</string> <string name="summary_glasses" msgid="2872254734959842579">"Sellele rakendusele antakse need load teie seadmes <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Kas lubate rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> oma telefoni rakendusi voogesitada?"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Kas lubate seadmel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> oma telefoni rakendusi voogesitada?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"%1$s saab juurdepääsu kõigele, mis on telefonis nähtaval või esitatav, sh helile, fotodele, paroolidele ja sõnumitele.<br/><br/>%1$s saab rakendusi voogesitada kuni eemaldate juurdepääsu sellele loale."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string> - <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi kuvada ja voogesitada"</string> + <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi kuvada ja voogesitada"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_title_computer" msgid="4671071173916176037">"Google Play teenused"</string> - <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba pääseda juurde telefoni fotodele, meediale ja märguannetele"</string> + <string name="helper_summary_computer" msgid="8774832742608187072">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba pääseda juurde telefoni fotodele, meediale ja märguannetele"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Kas lubada seadmel <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> teha seda toimingut?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Kas lubate rakendusel <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> oma telefoni rakenduste ja süsteemifunktsioonidel voogesitada?"</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Kas lubate seadmel <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> oma telefoni rakendusi ja süsteemifunktsioone voogesitada?"</string> <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s saab juurdepääsu kõigele, mis on teie telefonis nähtav või esitatav, sh heli, fotod, makseteave, paroolid ja sõnumid.<br/><br/>%1$s saab voogesitada rakendusi ja süsteemifunktsioone, kuni eemaldate juurdepääsu sellele loale."</string> - <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba voogesitada rakendusi ja muid süsteemi funktsioone läheduses olevatesse seadmetesse"</string> + <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba voogesitada rakendusi ja muid süsteemi funktsioone läheduses olevatesse seadmetesse"</string> <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string> <string name="summary_generic" msgid="1761976003668044801">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja valitud seadme vahel"</string> <string name="consent_yes" msgid="8344487259618762872">"Luba"</string> @@ -59,7 +59,7 @@ <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string> <string name="permission_call_logs" msgid="5546761417694586041">"Kõnelogid"</string> <string name="permission_nearby_devices" msgid="7530973297737123481">"Läheduses olevad seadmed"</string> - <string name="permission_media_routing_control" msgid="5498639511586715253">"Muutke meediaväljundit"</string> + <string name="permission_media_routing_control" msgid="5498639511586715253">"Meediaväljundi muutmine"</string> <string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string> <string name="permission_notifications" msgid="4099418516590632909">"Märguanded"</string> <string name="permission_app_streaming" msgid="6009695219091526422">"Rakendused"</string> diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml index d0dee9ba9021..ca8497077f6a 100644 --- a/packages/CompanionDeviceManager/res/values-eu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml @@ -26,8 +26,8 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"gailua"</string> <string name="summary_glasses" msgid="2872254734959842579">"Baimen hauek erabili ahalko ditu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>n aplikazioak:"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Eman informazioa telefonotik hartzeko baimena <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari zure telefonoko aplikazioak zuzenean igortzeko baimena eman nahi diozu?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s aplikazioak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, pasahitzak eta mezuak barne.<br/><br/>%1$s aplikazioak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gailuari zure telefonoko aplikazioak zuzenean igortzeko baimena eman nahi diozu?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s gailuak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, pasahitzak eta mezuak barne.<br/><br/>%1$s aplikazioak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailuarteko zerbitzuak"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Gailu batetik bestera aplikazioak igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> gailuaren izenean"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikazioak gailuen artean bistaratzeko eta zuzenean igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> gailuaren izenean"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"Telefonoko argazkiak, multimedia-edukia eta jakinarazpenak erabiltzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> gailuaren izenean"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Ekintza hau gauzatzeko baimena eman nahi diozu <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> aplikazioari?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> aplikazioari zure telefonoko aplikazioak eta sistemaren eginbideak zuzenean igortzeko baimena eman nahi diozu?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s aplikazioak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, ordainketa-informazioa, pasahitzak eta mezuak barne.<br/><br/>%1$s aplikazioak eta sistemaren eginbideak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> gailuari zure telefonoko aplikazioak eta sistemaren eginbideak zuzenean igortzeko baimena eman nahi diozu?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s gailuak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, ordainketa-informazioa, pasahitzak eta mezuak barne.<br/><br/>%1$s aplikazioak eta sistemaren eginbideak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikazioak eta sistemaren beste eginbide batzuk inguruko gailuetara igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean"</string> <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string> <string name="summary_generic" msgid="1761976003668044801">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)"</string> diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml index 9b556698c0a8..2363886c3484 100644 --- a/packages/CompanionDeviceManager/res/values-hi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml @@ -27,10 +27,10 @@ <string name="summary_glasses" msgid="2872254734959842579">"यह ऐप्लिकेशन, आपके <xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर इन अनुमतियों को ऐक्सेस कर पाएगा"</string> <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को आपके फ़ोन के ऐप्लिकेशन स्ट्रीम करने की अनुमति देनी है?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चलाया गया हो. जैसे, ऑडियो, फ़ोटो, पासवर्ड, और मैसेज.<br/><br/>%1$s तब तक ऐप्लिकेशन स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string> - <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चल रहा हो. जैसे, ऑडियो, फ़ोटो, पासवर्ड, और मैसेज.<br/><br/>%1$s तब तक ऐप्लिकेशन स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन स्ट्रीम करने की अनुमति मांग रहा है"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन दिखाने और स्ट्रीम करने की अनुमति मांग रहा है"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, एक डिवाइस के ऐप्लिकेशन, दूसरे डिवाइस पर दिखाने और स्ट्रीम करने की अनुमति मांग रहा है"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string> @@ -39,7 +39,7 @@ <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, आपने फ़ोन में मौजूद फ़ोटो, मीडिया, और सूचनाओं को ऐक्सेस करने की अनुमति मांग रहा है"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"क्या <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> को यह कार्रवाई करने की अनुमति देनी है?"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> को आपके फ़ोन के ऐप्लिकेशन और सिस्टम की सुविधाएं स्ट्रीम करने की अनुमति देनी है?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चलाया गया हो. जैसे, ऑडियो, फ़ोटो, पेमेंट से जुड़ी जानकारी, पासवर्ड, और मैसेज.<br/><br/>%1$s तब तक ऐप्लिकेशन और सिस्टम की सुविधाओं को स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चल रहा हो. जैसे, ऑडियो, फ़ोटो, पेमेंट की जानकारी, पासवर्ड, और मैसेज.<br/><br/>%1$s तब तक ऐप्लिकेशन और सिस्टम की सुविधाओं को स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से, ऐप्लिकेशन और दूसरे सिस्टम की सुविधाओं को आस-पास मौजूद डिवाइसों पर स्ट्रीम करने की अनुमति मांग रहा है"</string> <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string> <string name="summary_generic" msgid="1761976003668044801">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक करेगा. जैसे, कॉल करने वाले व्यक्ति का नाम"</string> diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml index 1c9c218e34a4..4985ae3cde34 100644 --- a/packages/CompanionDeviceManager/res/values-hu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml @@ -59,7 +59,7 @@ <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string> <string name="permission_call_logs" msgid="5546761417694586041">"Hívásnaplók"</string> <string name="permission_nearby_devices" msgid="7530973297737123481">"Közeli eszközök"</string> - <string name="permission_media_routing_control" msgid="5498639511586715253">"Médiakiment módosítása"</string> + <string name="permission_media_routing_control" msgid="5498639511586715253">"Médiakimenet módosítása"</string> <string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string> <string name="permission_notifications" msgid="4099418516590632909">"Értesítések"</string> <string name="permission_app_streaming" msgid="6009695219091526422">"Alkalmazások"</string> diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml index c4de3cd08ade..a655a3ec3705 100644 --- a/packages/CompanionDeviceManager/res/values-hy/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml @@ -26,8 +26,8 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"սարք"</string> <string name="summary_glasses" msgid="2872254734959842579">"Այս հավելվածը կստանա հետևյալ թույլտվությունները ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ում"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Թույլատրե՞լ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին հեռարձակել ձեր հեռախոսի հավելվածները"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s հավելվածին հասանելի կլինի հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, գաղտնաբառերը և հաղորդագրությունները։<br/><br/>%1$s հավելվածը կկարողանա հավելվածներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Թույլատրե՞լ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ին հեռարձակել ձեր հեռախոսի հավելվածները"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s-ին հասանելի կլինի հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, գաղտնաբառերը և հաղորդագրությունները։<br/><br/>%1$s-ը կկարողանա հավելվածներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ծառայություններ"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր հեռախոսի լուսանկարները, մեդիաֆայլերն ու ծանուցումները տեսնելու համար"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Թույլատրե՞լ <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> հավելվածին կատարել այս գործողությունը"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Թույլատրե՞լ <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> սարքին հեռարձակել ձեր հեռախոսի հավելվածները և համակարգի գործառույթները"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s սարքին հասանելի կլինի ձեր հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, վճարային տեղեկությունները, գաղտնաբառերը և հաղորդագրությունները։<br/><br/>%1$s սարքը կկարողանա հավելվածներ և համակարգի գործառույթներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Թույլատրե՞լ <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong>-ին հեռարձակել ձեր հեռախոսի հավելվածները և համակարգի գործառույթները"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s-ին հասանելի կլինի ձեր հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, վճարային տեղեկությունները, գաղտնաբառերը և հաղորդագրությունները։<br/><br/>%1$s-ը կկարողանա հավելվածներ և համակարգի գործառույթներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ մոտակա սարքերին հավելվածներ և համակարգի այլ գործառույթներ հեռարձակելու համար"</string> <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string> <string name="summary_generic" msgid="1761976003668044801">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և ընտրված սարքի տվյալները, օր․՝ զանգողի անունը"</string> diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml index b1c4f5b01f50..1481ca136762 100644 --- a/packages/CompanionDeviceManager/res/values-in/strings.xml +++ b/packages/CompanionDeviceManager/res/values-in/strings.xml @@ -26,11 +26,11 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"perangkat"</string> <string name="summary_glasses" msgid="2872254734959842579">"Aplikasi ini akan diizinkan mengakses izin ini di <xliff:g id="DEVICE_NAME">%1$s</xliff:g> Anda"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses informasi ini dari ponsel Anda"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> melakukan streaming aplikasi di ponsel Anda?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s akan memiliki akses ke konten apa pun yang ditampilkan atau dimainkan di ponsel, termasuk audio, foto, sandi, dan pesan.<br/><br/>%1$s akan dapat melakukan streaming aplikasi hingga Anda menghapus izin ini."</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> menstreaming aplikasi di ponsel Anda?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s akan memiliki akses ke apa pun yang ditampilkan atau diputar di ponsel, termasuk audio, foto, sandi, dan pesan.<br/><br/>%1$s akan dapat menstreaming aplikasi hingga Anda menghapus izin ini."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggantikan <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> meminta izin untuk menampilkan dan melakukan streaming aplikasi di antara perangkat Anda"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> untuk menampilkan dan menstreaming aplikasi di antara perangkat Anda"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses informasi ini dari ponsel Anda"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Layanan Google Play"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> untuk mengakses foto, media, dan notifikasi ponsel Anda"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Izinkan <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> melakukan tindakan ini?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Izinkan <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> melakukan streaming aplikasi dan mengakses fitur sistem di ponsel Anda?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s akan memiliki akses ke konten apa pun yang ditampilkan atau dimainkan di ponsel Anda, termasuk audio, foto, info pembayaran, sandi, dan pesan.<br/><br/>%1$s akan dapat melakukan streaming aplikasi dan mengakses fitur sistem hingga Anda menghapus izin ini."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Izinkan <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> menstreaming aplikasi dan fitur sistem di ponsel Anda?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s akan memiliki akses ke apa pun yang ditampilkan atau diputar di ponsel Anda, termasuk audio, foto, info pembayaran, sandi, dan pesan.<br/><br/>%1$s akan dapat menstreaming aplikasi dan fitur sistem hingga Anda menghapus izin ini."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menstreaming aplikasi dan fitur sistem lainnya ke perangkat di sekitar"</string> <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string> <string name="summary_generic" msgid="1761976003668044801">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih"</string> diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml index f1eb53477960..ce8feb5e0f72 100644 --- a/packages/CompanionDeviceManager/res/values-iw/strings.xml +++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"ל-%1$s תהיה גישה לכל מה שרואים או מפעילים בטלפון, כולל אודיו, תמונות, סיסמאות והודעות.<br/><br/>ל-%1$s תהיה אפשרות לשדר אפליקציות עד שהגישה להרשאה הזו תוסר."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור המכשיר <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> כדי לשדר אפליקציות בין המכשירים שלך"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה למכשיר <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> כדי להציג ולשדר אפליקציות בין המכשירים שלך"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"האפליקציה \'<xliff:g id="APP_NAME">%1$s</xliff:g>\' מבקשת הרשאה למכשיר <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> כדי להציג ולשדר אפליקציות בין המכשירים שלך"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מהטלפון שלך"</string> diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml index 7aace8292792..7dbcef0675b5 100644 --- a/packages/CompanionDeviceManager/res/values-kn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"ಆಡಿಯೋ, ಫೋಟೋಗಳು, ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಸಂದೇಶಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ಕಂಟೆಂಟ್ಗೆ %1$s ಆ್ಯಕ್ಸೆಸ್ ಹೊಂದಿರುತ್ತದೆ.<br/><br/>ನೀವು ಈ ಅನುಮತಿಗೆ ಇರುವ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ತೆಗೆದುಹಾಕುವವರೆಗೆ %1$s ಗೆ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಮತ್ತು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಮತ್ತು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿವೆ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string> diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml index 86679ac147f7..925f21b0028c 100644 --- a/packages/CompanionDeviceManager/res/values-ko/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"%1$s에서 오디오, 사진, 비밀번호, 메시지 등 휴대전화에 표시되거나 휴대전화에서 재생되는 모든 항목에 액세스할 수 있습니다.<br/><br/>이 권한에 대한 액세스를 삭제할 때까지 %1$s에서 앱을 스트리밍할 수 있습니다."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 기기 간 앱을 표시하고 스트리밍할 권한을 요청하고 있습니다."</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 연결된 기기의 앱을 표시하고 스트리밍할 권한을 요청하고 있습니다."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>이 휴대전화에서 이 정보에 액세스하도록 허용"</string> diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml index 932b5c5339d5..1b72477f5e33 100644 --- a/packages/CompanionDeviceManager/res/values-ky/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml @@ -26,8 +26,8 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"түзмөк"</string> <string name="summary_glasses" msgid="2872254734959842579">"Бул колдонмого <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздө төмөнкүлөрдү аткарууга уруксат берилет"</string> <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы колдонмолорду алып ойнотууга уруксат бересизби?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s телефондо көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, сырсөздөр жана билдирүүлөргө кире алат. Бул уруксатты алып салмайынча, <br/><br/>%1$s колдонмолорду алып ойното алат."</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы колдонмолорду өткөрүүгө уруксат бересизби?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s телефондо көрүнгөн же ойнотулган аудиофайлдар, сүрөттөр, сырсөздөр жана билдирүүлөр сыяктуу нерселерди көрө алат. Бул уруксатты алып салмайынча, <br/><br/>%1$s колдонмолорду өткөрө берет."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду алып ойнотууга уруксат сурап жатат"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрдүн ортосунда колдонмолорду көрсөтүү жана алып ойнотуу үчүн уруксат сурап жатат"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play кызматтары"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан телефондогу сүрөттөрдү, медиа файлдарды жана билдирмелерди колдонууга уруксат сурап жатат"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> түзмөгүнө бул аракетти аткарууга уруксат бересизби?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы колдонмолорду жана тутумдун функцияларын алып ойнотууга уруксат бересизби?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s телефонуңузда көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, төлөм маалыматы, сырсөздөр жана билдирүүлөргө кире алат. Бул уруксатты алып салмайынча, <br/><br/>%1$s колдонмолорду жана тутум функцияларын алып ойното алат."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы колдонмолорду жана системалык функцияларды өткөргөнгө уруксат бересизби?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s телефонуңузда көрүнгөн же ойнотулган аудиофайлдар, сүрөттөр, төлөм маалыматы, сырсөздөр жана билдирүүлөр сыяктуу нерселерди көрө алат. Бул уруксатты алып салмайынча, <br/><br/>%1$s колдонмолорду жана системдик функцияларды өткөрө алат."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан жакын жердеги түзмөктөрдө колдонмолорду жана системанын башка функцияларын алып ойнотууга уруксат сурап жатат"</string> <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string> <string name="summary_generic" msgid="1761976003668044801">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана тандалган түзмөк менен шайкештирет"</string> diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml index fe6e4cca4e07..0c4bfcbfd6ba 100644 --- a/packages/CompanionDeviceManager/res/values-mn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml @@ -27,7 +27,7 @@ <string name="summary_glasses" msgid="2872254734959842579">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-н эдгээр зөвшөөрөлд хандах эрхтэй байх болно"</string> <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Таны утасны аппуудыг дамжуулахыг <strong><xliff:g id="APP_NAME">%1$s</xliff:g>-д</strong> зөвшөөрөх үү?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s аудио, зураг, нууц үг болон мессежүүдийг оруулаад утсан дээр харагдсан эсвэх тоглуулсан аливаа зүйлд хандах эрхтэй болно.<br/><br/>%1$s таныг энэ зөвшөөрлийг хасах хүртэл аппуудыг дамжуулах боломжтой байх болно."</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s аудио, зураг, нууц үг болон мессежүүдийг зэрэг утсан дээр харагдсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй болно.<br/><br/>%1$s таныг энэ зөвшөөрлийг хасах хүртэл аппуудыг дамжуулах боломжтой байх болно."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Таны төхөөрөмжүүд хооронд апп дамжуулахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>-н өмнөөс таны төхөөрөмжүүдийн хооронд аппууд үзүүлж, дамжуулах зөвшөөрлийг хүсэж байна"</string> @@ -39,7 +39,7 @@ <string name="helper_summary_computer" msgid="8774832742608187072">"Таны утасны зураг, медиа болон мэдэгдэлд хандахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong>-д энэ үйлдлийг хийхийг зөвшөөрөх үү?"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Таны утасны апп болон системийн онцлогуудыг дамжуулахыг <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g>-д</strong> зөвшөөрөх үү?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s аудио, зураг, төлбөрийн мэдээлэл, нууц үг болон мессежүүдийг оруулаад утсан дээр харагдсан эсвэх тоглуулсан аливаа зүйлд хандах эрхтэй болно.<br/><br/>%1$s таныг энэ зөвшөөрлийг хасах хүртэл апп болон системийн онцлогуудыг дамжуулах боломжтой байх болно."</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s аудио, зураг, төлбөрийн мэдээлэл, нууц үг болон мессеж зэрэг утсан дээр харагдсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй болно.<br/><br/>%1$s таныг энэ зөвшөөрлийг хасах хүртэл апп болон системийн онцлогуудыг дамжуулах боломжтой байх болно."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс аппууд болон системийн бусад онцлогийг ойролцоох төхөөрөмжүүд рүү дамжуулах зөвшөөрөл хүсэж байна"</string> <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string> <string name="summary_generic" msgid="1761976003668044801">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно"</string> diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml index d817df2678f3..4605c18eec0e 100644 --- a/packages/CompanionDeviceManager/res/values-nb/strings.xml +++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml @@ -24,7 +24,7 @@ <string name="summary_watch" msgid="7962014927042971830">"Denne appen får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og har disse tillatelsene på <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vil du la <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> administrere <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"enheten"</string> - <string name="summary_glasses" msgid="2872254734959842579">"Denne appen får disse tillatelsene på <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="summary_glasses" msgid="2872254734959842579">"Denne appen får disse tillatelsene på enheten din (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra telefonen din"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Vil du tillate at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> strømmer appene på telefonen?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"%1$s får tilgang til alt som er synlig eller spilles av på telefonen, inkludert lyd, bilder, passord og meldinger.<br/><br/>%1$s kan strømme apper til du fjerner denne tillatelsen."</string> diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml index 8394a82a963d..448362f619b0 100644 --- a/packages/CompanionDeviceManager/res/values-pa/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml @@ -27,7 +27,7 @@ <string name="summary_glasses" msgid="2872254734959842579">"ਇਸ ਐਪ ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> \'ਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ"</string> <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"ਕੀ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।<br/><br/>%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗੀ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।<br/><br/>%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗਾ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਦਿਖਾਉਣ ਅਤੇ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> @@ -39,7 +39,7 @@ <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"ਕੀ <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> ਨੂੰ ਇਹ ਕਾਰਵਾਈ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"ਕੀ <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।<br/><br/>%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕੇਗੀ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।<br/><br/>%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕੇਗਾ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ \'ਤੇ ਐਪਾਂ ਅਤੇ ਹੋਰ ਸਿਸਟਮ ਸੰਬੰਧੀ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string> <string name="summary_generic" msgid="1761976003668044801">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ"</string> diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml index 945f8491597f..757967858bea 100644 --- a/packages/CompanionDeviceManager/res/values-pl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"%1$s będzie mieć dostęp do wszystkiego, co jest widoczne i odtwarzane na telefonie, w tym do dźwięku, zdjęć, haseł i wiadomości.<br/><br/>%1$s będzie w stanie strumieniować aplikacje, dopóki nie usuniesz dostępu do tego uprawnienia."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> o pozwolenie na wyświetlanie i strumieniowanie aplikacji między Twoimi urządzeniami"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> o pozwolenie na wyświetlanie i strumieniowanie aplikacji między Twoimi urządzeniami"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string> diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml index 289d6e07f2e8..eb7b533abfc1 100644 --- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, senhas e mensagens. O app <br/><br/>%1$s poderá fazer o streaming de apps até que você remova o acesso a essa permissão."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Autorizar que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse estas informações do smartphone"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> realize esta ação?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> faça streaming dos apps e recursos do sistema do smartphone?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. O app <br/><br/>%1$s poderá fazer o streaming de apps e recursos do sistema até que você remova o acesso a essa permissão."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> faça streaming de apps e recursos do sistema do smartphone?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. <br/><br/>O %1$s poderá acessar e transferir informações de apps e recursos do sistema até que você remova essa permissão."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de apps e de outros recursos do sistema para dispositivos por perto"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string> diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml index 9d94de7b66ce..c951334e68ff 100644 --- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml @@ -26,8 +26,8 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="2872254734959842579">"Esta app vai poder aceder a estas autorizações no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu telemóvel"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Permitir que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça stream das apps do telemóvel?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, palavras-passe e mensagens.<br/><br/>%1$s vai poder fazer stream de apps até remover o acesso a esta autorização."</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Permitir que o dispositivo <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça stream das apps do telemóvel?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"O dispositivo %1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, palavras-passe e mensagens.<br/><br/>O %1$s vai poder fazer stream de apps até remover o acesso a esta autorização."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para fazer stream de apps entre os seus dispositivos"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para apresentar e fazer stream de apps entre os seus dispositivos"</string> @@ -39,7 +39,7 @@ <string name="helper_summary_computer" msgid="8774832742608187072">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para aceder às fotos, ao conteúdo multimédia e às notificações do seu telemóvel"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> faça esta ação?"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> faça stream das apps e das funcionalidades do sistema do telemóvel?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, informações de pagamento, palavras-passe e mensagens.<br/><br/>%1$s vai poder fazer stream de apps e funcionalidades do sistema até remover o acesso a esta autorização."</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O dispositivo %1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, informações de pagamento, palavras-passe e mensagens.<br/><br/>O %1$s vai poder fazer stream de apps e funcionalidades do sistema até remover o acesso a esta autorização."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer stream de apps e outras funcionalidades do sistema para dispositivos próximos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo escolhido"</string> diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml index 289d6e07f2e8..eb7b533abfc1 100644 --- a/packages/CompanionDeviceManager/res/values-pt/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml @@ -30,7 +30,7 @@ <string name="summary_app_streaming" msgid="295548145144086753">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, senhas e mensagens. O app <br/><br/>%1$s poderá fazer o streaming de apps até que você remova o acesso a essa permissão."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Autorizar que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse estas informações do smartphone"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> realize esta ação?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> faça streaming dos apps e recursos do sistema do smartphone?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. O app <br/><br/>%1$s poderá fazer o streaming de apps e recursos do sistema até que você remova o acesso a essa permissão."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> faça streaming de apps e recursos do sistema do smartphone?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. <br/><br/>O %1$s poderá acessar e transferir informações de apps e recursos do sistema até que você remova essa permissão."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de apps e de outros recursos do sistema para dispositivos por perto"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string> diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml index ce65c702aa8c..15456aaac3ea 100644 --- a/packages/CompanionDeviceManager/res/values-ru/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml @@ -26,11 +26,11 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"устройстве"</string> <string name="summary_glasses" msgid="2872254734959842579">"Это приложение получит указанные разрешения на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="title_app_streaming" msgid="2270331024626446950">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслировать приложения с вашего телефона?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"Приложение \"%1$s\" получит доступ ко всему, что показывается или воспроизводится на телефоне, включая аудиофайлы, фотографии, пароли и сообщения.<br/><br/>Приложение \"%1$s\" сможет транслировать приложения, пока вы не отзовете это разрешение."</string> - <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Разрешить устройству <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслировать приложения с вашего телефона?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"У устройства \"%1$s\" будет доступ ко всему, что показывается или воспроизводится на телефоне, включая аудиофайлы, фотографии, пароли и сообщения.<br/><br/><br/>Устройство \"%1$s\" сможет транслировать приложения, пока вы не отзовете это разрешение."</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы для нескольких устройств"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>, чтобы транслировать приложения между устройствами."</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>, чтобы транслировать приложения между устройствами."</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" запрашивает разрешение на трансляцию приложений между устройствами."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Сервисы Google Play"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>, чтобы получить доступ к фотографиям, медиаконтенту и уведомлениям на телефоне."</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Разрешить приложению <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> выполнять это действие?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Разрешить приложению <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> транслировать приложения и системные функции с вашего телефона?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"Приложение \"%1$s\" получит доступ ко всему, что показывается или воспроизводится на вашем телефоне, включая аудиофайлы, фотографии, платежные данные, пароли и сообщения.<br/><br/>Приложение \"%1$s\" сможет транслировать приложения и системные функции, пока вы не отзовете это разрешение."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Разрешить устройству <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> транслировать приложения и системные функции с вашего телефона?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"У устройства \"%1$s\" будет доступ ко всему, что показывается или воспроизводится на вашем телефоне, включая аудиофайлы, фотографии, платежные данные, пароли и сообщения.<br/><br/>Устройство \"%1$s\" сможет транслировать приложения и системные функции, пока вы не отзовете это разрешение."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение транслировать приложения и системные функции на устройства поблизости."</string> <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string> <string name="summary_generic" msgid="1761976003668044801">"Приложение сможет синхронизировать информацию между телефоном и выбранным устройством, например данные из журнала звонков."</string> diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml index bbee596d56f4..c0d27f1e32e1 100644 --- a/packages/CompanionDeviceManager/res/values-sk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml @@ -26,11 +26,11 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"zariadenie"</string> <string name="summary_glasses" msgid="2872254734959842579">"Táto aplikácia bude mať prístup k týmto povoleniam v zariadení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Chcete povoliť aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovať aplikácie vo svojom telefóne?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s bude mať prístup k všetkému obsahu viditeľnému alebo prehrávanému v telefóne vrátane zvuku, fotiek, hesiel a správ.<br/><br/>%1$s bude môcť streamovať aplikácie, kým prístup k tomuto povoleniu neodstránite."</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Chcete povoliť zariadeniu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovať aplikácie telefónu?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s bude mať prístup k všetkému, čo v telefóne zobrazíte alebo prehrajete, vrátane zvuku, fotiek, hesiel a správ.<br/><br/>%1$s bude môcť streamovať aplikácie, kým toto povolenie neodstránite."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie streamovať aplikácie medzi vašimi zariadeniami."</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie zobrazovať a streamovať aplikácie medzi zariadeniami"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje v mene zariadenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie zobrazovať a streamovať aplikácie medzi zariadeniami"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie na prístup k fotkám, médiám a upozorneniam vášho telefónu"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Chcete povoliť zariadeniu <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> vykonať túto akciu?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Chcete povoliť aplikácii <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> streamovať aplikácie a systémové funkcie vo svojom telefóne?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s bude mať prístup k všetkému obsahu viditeľnému alebo prehrávanému v telefóne vrátane zvuku, fotiek, platobných údajov, hesiel a správ.<br/><br/>%1$s bude môcť streamovať aplikácie, kým prístup k tomuto povoleniu neodstránite."</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Chcete povoliť zariadeniu <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> streamovať aplikácie a systémové funkcie telefónu?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s bude mať prístup k všetkému, čo v telefóne zobrazíte alebo prehrajete, vrátane zvuku, fotiek, platobných údajov, hesiel a správ.<br/><br/>%1$s bude môcť streamovať aplikácie a systémové funkcie, kým toto povolenie neodstránite."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie streamovať aplikácie a ďalšie systémové funkcie do zariadení v okolí"</string> <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string> <string name="summary_generic" msgid="1761976003668044801">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a vybraným zariadením"</string> diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml index 346fbaee9625..a895c25bf075 100644 --- a/packages/CompanionDeviceManager/res/values-sl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml @@ -28,7 +28,7 @@ <string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vašem telefonu"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Ali aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovolite, da pretočno predvaja aplikacije telefona?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"Aplikacija %1$s bo imela dostop do vsega, kar je prikazano ali se predvaja v telefonu, vključno z zvokom, fotografijami, gesli in sporočili.<br/><br/>Aplikacija %1$s bo lahko pretočno predvajala aplikacije, dokler ne odstranite dostopa do tega dovoljenja."</string> - <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve v več napravah"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>« zahteva dovoljenje za prikaz in pretočno predvajanje aplikacij v vaših napravah."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml index 76f623a1d2f5..63e8cb6a4c32 100644 --- a/packages/CompanionDeviceManager/res/values-sq/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml @@ -27,20 +27,20 @@ <string name="summary_glasses" msgid="2872254734959842579">"Këtij aplikacioni do t\'i lejohet qasja te këto leje në <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="title_app_streaming" msgid="2270331024626446950">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Të lejohet që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të transmetojë aplikacionet e telefonit tënd?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose luhet në telefon, duke përfshirë audion, fotografitë, fjalëkalimet dhe mesazhet.<br/><br/>%1$s do të mund të transmetojë aplikacionet derisa ta heqësh qasjen për këtë leje."</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose që luhet në telefon, duke përfshirë audion, fotografitë, fjalëkalimet dhe mesazhet.<br/><br/>%1$s do të mund t\'i transmetojë aplikacionet derisa ta heqësh qasjen për këtë leje."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string> - <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të shfaqur dhe transmetuar aplikacionet mes pajisjeve të tua"</string> + <string name="helper_summary_app_streaming" msgid="2396773196949578425">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të shfaqur dhe transmetuar aplikacionet mes pajisjeve të tua"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_title_computer" msgid="4671071173916176037">"Shërbimet e Google Play"</string> - <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të marrë qasje te fotografitë, media dhe njoftimet e telefonit tënd"</string> + <string name="helper_summary_computer" msgid="8774832742608187072">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të marrë qasje te fotografitë, media dhe njoftimet e telefonit tënd"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Të lejohet që <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> të ndërmarrë këtë veprim?"</string> <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Të lejohet që <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> të transmetojë aplikacionet dhe veçoritë e sistemit të telefonit tënd?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose luhet në telefon, duke përfshirë audion, fotografitë, informacionet për pagesën, fjalëkalimet dhe mesazhet.<br/><br/>%1$s do të mund të transmetojë aplikacionet dhe veçoritë e sistemit derisa ta heqësh qasjen për këtë leje."</string> - <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) tënde për të transmetuar aplikacione dhe veçori të tjera të sistemit te pajisjet në afërsi"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose që luhet në telefon, duke përfshirë audion, fotografitë, informacionet për pagesën, fjalëkalimet dhe mesazhet.<br/><br/>%1$s do të mund t\'i transmetojë aplikacionet dhe veçoritë e sistemit derisa ta heqësh qasjen për këtë leje."</string> + <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) tënde për të transmetuar aplikacione dhe veçori të tjera të sistemit te pajisjet në afërsi"</string> <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string> <string name="summary_generic" msgid="1761976003668044801">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emrin e dikujt që po telefonon, mes telefonit tënd dhe pajisjes së zgjedhur."</string> <string name="consent_yes" msgid="8344487259618762872">"Lejo"</string> diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml index ede266e23464..2643b2d4c19b 100644 --- a/packages/CompanionDeviceManager/res/values-te/strings.xml +++ b/packages/CompanionDeviceManager/res/values-te/strings.xml @@ -28,7 +28,7 @@ <string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> యాప్ను అనుమతించండి"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"మీ ఫోన్ యాప్లను స్ట్రీమ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించాలా?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"ఆడియో, ఫోటోలు, పాస్వర్డ్లు, మెసేజ్లతో సహా ఫోన్లో కనిపించే లేదా ప్లే అయ్యే దేనికైనా %1$sకు యాక్సెస్ ఉంటుంది.<br/><br/>మీరు ఈ అనుమతికి యాక్సెస్ను తీసివేసే వరకు %1$s యాప్లను స్ట్రీమ్ చేయగలదు."</string> - <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"క్రాస్-డివైజ్ సర్వీసులు"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"మీ పరికరాల మధ్య యాప్లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"మీ పరికరాలలో యాప్లను డిస్ప్లే చేయడానికి, స్ట్రీమ్ చేయడానికి <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> తరఫున <xliff:g id="APP_NAME">%1$s</xliff:g> అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml index 3efc29925a21..5852657a01b5 100644 --- a/packages/CompanionDeviceManager/res/values-tr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml @@ -26,7 +26,7 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"Cihaz"</string> <string name="summary_glasses" msgid="2872254734959842579">"Bu uygulamanın <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızda şu izinlere erişmesine izin verilecek:"</string> <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adlı uygulamanın telefonunuzdaki uygulamaları aktarmasına izin verilsin mi?"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adlı cihazın telefonunuzdaki uygulamaları aktarmasına izin verilsin mi?"</string> <string name="summary_app_streaming" msgid="295548145144086753">"%1$s; ses, fotoğraflar, şifreler ve mesajlar da dahil olmak üzere telefonda görünen veya oynatılan her şeye erişebilecek.<br/><br/>%1$s siz bu iznin erişimini kaldırana kadar uygulamaları aktarabilecek."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string> @@ -38,7 +38,7 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Hizmetleri"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g>, telefonunuzdaki fotoğraf, medya ve bildirimlere erişmek için <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> cihazının bu işlemi yapmasına izin verilsin mi?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> adlı uygulamanın telefonunuzdaki uygulamaları ve sistem özelliklerini aktarmasına izin verilsin mi?"</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> adlı cihazın telefonunuzdaki uygulamaları ve sistem özelliklerini aktarmasına izin verilsin mi?"</string> <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s; ses, fotoğraflar, ödeme bilgileri, şifreler ve mesajlar da dahil olmak üzere telefonunuzda görünen veya oynatılan her şeye erişebilecek.<br/><br/>%1$s siz bu iznin erişimini kaldırana kadar uygulamaları ve diğer sistem özelliklerini aktarabilecek."</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması <xliff:g id="DEVICE_NAME">%2$s</xliff:g> cihazınız adına uygulamaları ve diğer sistem özelliklerini yakındaki cihazlara aktarmak için izin istiyor"</string> <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string> diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml index 109a011bccd6..d92a2e088f25 100644 --- a/packages/CompanionDeviceManager/res/values-ur/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml @@ -27,7 +27,7 @@ <string name="summary_glasses" msgid="2872254734959842579">"اس ایپ کو آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> پر ان اجازتوں تک رسائی کی اجازت ہوگی"</string> <string name="title_app_streaming" msgid="2270331024626446950">"اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اجازت دیں"</string> <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"اجازت دیں<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اپنے فون کی ایپس کو سلسلہ بندی کرنے کے لیے؟"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"%1$s کو فون پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، پاس ورڈز اور پیغامات۔<br/><br/>%1$s اس وقت تک ایپس کو اسٹریم کر سکے گید جب تک آپ اس اجازت تک رسائی کو ہٹا دیتے ہیں۔"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s کو فون پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، پاس ورڈز اور پیغامات۔<br/><br/>اس وقت تک %1$s ایپس کو اسٹریم کر سکے گا جب تک آپ اس اجازت تک رسائی کو ہٹا نہیں دیتے۔"</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس ڈیوائس سروسز"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string> <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> آپ کے <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کو ڈسپلے اور اسٹریم کرنے کے لیے اجازت کی درخواست کر رہی ہے"</string> @@ -38,7 +38,7 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play سروسز"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> کی جانب سے آپ کے فون کی تصاویر، میڈیا اور اطلاعات تک رسائی کی اجازت کی درخواست کر رہی ہے"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> کو یہ کارروائی انجام دینے کی اجازت دیں؟"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"اجازت دیں <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> اپنے فون کی ایپس اور سسٹم کی خصوصیات کو سلسلہ بندی کرنے کے لیے؟"</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"آپ کے فون کی ایپس اور سسٹم کی خصوصیات کو سلسلہ بندی کرنے کی <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> کو اجازت دیں؟"</string> <!-- String.format failed for translation --> <!-- no translation found for summary_nearby_device_streaming (4039565463149145573) --> <skip /> diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml index 750ff0d5ce4e..6daf4ff20b54 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml @@ -26,11 +26,11 @@ <string name="profile_name_glasses" msgid="3506504967216601277">"设备"</string> <string name="summary_glasses" msgid="2872254734959842579">"该应用将可以获得您<xliff:g id="DEVICE_NAME">%1$s</xliff:g>上的以下权限"</string> <string name="title_app_streaming" msgid="2270331024626446950">"允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”<strong></strong>访问您手机中的这项信息"</string> - <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 流式传输手机的应用?"</string> - <string name="summary_app_streaming" msgid="295548145144086753">"“%1$s”将能够访问手机上可见或播放的任何内容,包括音频、照片、密码和消息。<br/><br/>“%1$s”将能够流式传输应用,除非您撤消此访问权限。"</string> + <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"要允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 流式传输手机的应用吗?"</string> + <string name="summary_app_streaming" msgid="295548145144086753">"%1$s 将能够访问手机上可见或播放的任何内容,包括音频、照片、密码和消息。<br/><br/>%1$s 将能够流式传输应用,除非您撤消此访问权限。"</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string> <string name="helper_summary_app_streaming" msgid="2396773196949578425">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>请求在您的设备之间流式传输应用内容"</string> - <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>请求在设备之间显示和流式传输应用"</string> + <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 请求在设备之间显示和流式传输应用"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 访问您手机中的这项信息"</string> @@ -38,8 +38,8 @@ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服务"</string> <string name="helper_summary_computer" msgid="8774832742608187072">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>请求访问您手机上的照片、媒体内容和通知"</string> <string name="title_nearby_device_streaming" msgid="7269956847378799794">"允许<strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong>进行此操作?"</string> - <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"允许 <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> 流式传输手机的应用和系统功能?"</string> - <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"“%1$s”将能够访问手机上可见或播放的任何内容,包括音频、照片、付款信息、密码和消息。<br/><br/>“%1$s”将能够流式传输应用和系统功能,除非您撤消此访问权限。"</string> + <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"要允许 <strong><xliff:g id="DEVICE_NAME">%1$s</xliff:g></strong> 流式传输手机的应用和系统功能吗?"</string> + <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s 将能够访问手机上可见或播放的任何内容,包括音频、照片、付款信息、密码和消息。<br/><br/>%1$s 将能够流式传输应用和系统功能,除非您撤消此访问权限。"</string> <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_NAME">%2$s</xliff:g>请求将应用和其他系统功能流式传输到附近的设备"</string> <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string> <string name="summary_generic" msgid="1761976003668044801">"此应用将能在您的手机和所选设备之间同步信息,例如来电者的姓名"</string> diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml index 0af108052137..e8e24f492005 100644 --- a/packages/CompanionDeviceManager/res/values/styles.xml +++ b/packages/CompanionDeviceManager/res/values/styles.xml @@ -40,6 +40,7 @@ <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:gravity">center</item> + <item name="android:textDirection">locale</item> <item name="android:layout_marginLeft">14dp</item> <item name="android:layout_marginRight">14dp</item> <item name="android:textSize">20sp</item> @@ -53,6 +54,7 @@ <item name="android:layout_marginTop">18dp</item> <item name="android:layout_marginLeft">18dp</item> <item name="android:layout_marginRight">18dp</item> + <item name="android:textDirection">locale</item> <item name="android:textSize">14sp</item> <item name="android:textColor">?android:attr/textColorSecondary</item> </style> diff --git a/packages/CrashRecovery/aconfig/flags.aconfig b/packages/CrashRecovery/aconfig/flags.aconfig index 8627eac7beed..15fdc521f75a 100644 --- a/packages/CrashRecovery/aconfig/flags.aconfig +++ b/packages/CrashRecovery/aconfig/flags.aconfig @@ -2,7 +2,7 @@ package: "android.crashrecovery.flags" flag { name: "recoverability_detection" - namespace: "package_watchdog" + namespace: "package_manager_service" description: "Feature flag for recoverability detection" bug: "310236690" is_fixed_read_only: true diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java index 8891b50352d1..75a8bdfe5416 100644 --- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java +++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java @@ -39,15 +39,15 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; -import android.util.BackgroundThread; -import android.util.LongArrayQueue; import android.util.Slog; import android.util.Xml; +import android.utils.BackgroundThread; +import android.utils.LongArrayQueue; +import android.utils.XmlUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java index 271d552fc574..f86eb61c365f 100644 --- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java +++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java @@ -31,7 +31,6 @@ import android.content.pm.VersionedPackage; import android.crashrecovery.flags.Flags; import android.os.Build; import android.os.Environment; -import android.os.FileUtils; import android.os.PowerManager; import android.os.RecoverySystem; import android.os.SystemClock; @@ -44,10 +43,11 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Slog; +import android.utils.ArrayUtils; +import android.utils.FileUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.server.PackageWatchdog.FailureReasons; import com.android.server.PackageWatchdog.PackageHealthObserver; import com.android.server.PackageWatchdog.PackageHealthObserverImpact; diff --git a/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java b/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java new file mode 100644 index 000000000000..fa4d6afc03d3 --- /dev/null +++ b/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.utils; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import java.io.File; +import java.util.List; +import java.util.Objects; + +/** + * Copied over from frameworks/base/core/java/com/android/internal/util/ArrayUtils.java + * + * @hide + */ +public class ArrayUtils { + private ArrayUtils() { /* cannot be instantiated */ } + public static final File[] EMPTY_FILE = new File[0]; + + + /** + * Return first index of {@code value} in {@code array}, or {@code -1} if + * not found. + */ + public static <T> int indexOf(@Nullable T[] array, T value) { + if (array == null) return -1; + for (int i = 0; i < array.length; i++) { + if (Objects.equals(array[i], value)) return i; + } + return -1; + } + + /** @hide */ + public static @NonNull File[] defeatNullable(@Nullable File[] val) { + return (val != null) ? val : EMPTY_FILE; + } + + /** + * Checks if given array is null or has zero elements. + */ + public static boolean isEmpty(@Nullable int[] array) { + return array == null || array.length == 0; + } + + /** + * True if the byte array is null or has length 0. + */ + public static boolean isEmpty(@Nullable byte[] array) { + return array == null || array.length == 0; + } + + /** + * Converts from List of bytes to byte array + * @param list + * @return byte[] + */ + public static byte[] toPrimitive(List<byte[]> list) { + if (list.size() == 0) { + return new byte[0]; + } + int byteLen = list.get(0).length; + byte[] array = new byte[list.size() * byteLen]; + for (int i = 0; i < list.size(); i++) { + for (int j = 0; j < list.get(i).length; j++) { + array[i * byteLen + j] = list.get(i)[j]; + } + } + return array; + } + + /** + * Adds value to given array if not already present, providing set-like + * behavior. + */ + public static @NonNull int[] appendInt(@Nullable int[] cur, int val) { + return appendInt(cur, val, false); + } + + /** + * Adds value to given array. + */ + public static @NonNull int[] appendInt(@Nullable int[] cur, int val, + boolean allowDuplicates) { + if (cur == null) { + return new int[] { val }; + } + final int n = cur.length; + if (!allowDuplicates) { + for (int i = 0; i < n; i++) { + if (cur[i] == val) { + return cur; + } + } + } + int[] ret = new int[n + 1]; + System.arraycopy(cur, 0, ret, 0, n); + ret[n] = val; + return ret; + } +} diff --git a/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java b/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java index a6ae68f62f10..afcf6895fd0d 100644 --- a/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java +++ b/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.util; +package android.utils; import android.annotation.NonNull; import android.os.Handler; diff --git a/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java b/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java new file mode 100644 index 000000000000..e4923bfc4ecb --- /dev/null +++ b/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.utils; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Bits and pieces copied from hidden API of android.os.FileUtils. + * + * @hide + */ +public class FileUtils { + /** + * Read a text file into a String, optionally limiting the length. + * + * @param file to read (will not seek, so things like /proc files are OK) + * @param max length (positive for head, negative of tail, 0 for no limit) + * @param ellipsis to add of the file was truncated (can be null) + * @return the contents of the file, possibly truncated + * @throws IOException if something goes wrong reading the file + * @hide + */ + public static @Nullable String readTextFile(@Nullable File file, @Nullable int max, + @Nullable String ellipsis) throws IOException { + InputStream input = new FileInputStream(file); + // wrapping a BufferedInputStream around it because when reading /proc with unbuffered + // input stream, bytes read not equal to buffer size is not necessarily the correct + // indication for EOF; but it is true for BufferedInputStream due to its implementation. + BufferedInputStream bis = new BufferedInputStream(input); + try { + long size = file.length(); + if (max > 0 || (size > 0 && max == 0)) { // "head" mode: read the first N bytes + if (size > 0 && (max == 0 || size < max)) max = (int) size; + byte[] data = new byte[max + 1]; + int length = bis.read(data); + if (length <= 0) return ""; + if (length <= max) return new String(data, 0, length); + if (ellipsis == null) return new String(data, 0, max); + return new String(data, 0, max) + ellipsis; + } else if (max < 0) { // "tail" mode: keep the last N + int len; + boolean rolled = false; + byte[] last = null; + byte[] data = null; + do { + if (last != null) rolled = true; + byte[] tmp = last; + last = data; + data = tmp; + if (data == null) data = new byte[-max]; + len = bis.read(data); + } while (len == data.length); + + if (last == null && len <= 0) return ""; + if (last == null) return new String(data, 0, len); + if (len > 0) { + rolled = true; + System.arraycopy(last, len, last, 0, last.length - len); + System.arraycopy(data, 0, last, last.length - len, len); + } + if (ellipsis == null || !rolled) return new String(last); + return ellipsis + new String(last); + } else { // "cat" mode: size unknown, read it all in streaming fashion + ByteArrayOutputStream contents = new ByteArrayOutputStream(); + int len; + byte[] data = new byte[1024]; + do { + len = bis.read(data); + if (len > 0) contents.write(data, 0, len); + } while (len == data.length); + return contents.toString(); + } + } finally { + bis.close(); + input.close(); + } + } + + /** + * Perform an fsync on the given FileOutputStream. The stream at this + * point must be flushed but not yet closed. + * + * @hide + */ + public static boolean sync(FileOutputStream stream) { + try { + if (stream != null) { + stream.getFD().sync(); + } + return true; + } catch (IOException e) { + } + return false; + } + + /** + * List the files in the directory or return empty file. + * + * @hide + */ + public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) { + return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles()) + : ArrayUtils.EMPTY_FILE; + } +} diff --git a/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java b/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java index 948ebcca0263..fdb15e2333d5 100644 --- a/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java +++ b/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.util; +package android.utils; import android.annotation.NonNull; import android.os.Handler; diff --git a/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java b/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java new file mode 100644 index 000000000000..5cdc2536129a --- /dev/null +++ b/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.utils; + +import libcore.util.EmptyArray; + +import java.util.NoSuchElementException; + +/** + * Copied from frameworks/base/core/java/android/util/LongArrayQueue.java + * + * @hide + */ +public class LongArrayQueue { + + private long[] mValues; + private int mSize; + private int mHead; + private int mTail; + + private long[] newUnpaddedLongArray(int num) { + return new long[num]; + } + /** + * Initializes a queue with the given starting capacity. + * + * @param initialCapacity the capacity. + */ + public LongArrayQueue(int initialCapacity) { + if (initialCapacity == 0) { + mValues = EmptyArray.LONG; + } else { + mValues = newUnpaddedLongArray(initialCapacity); + } + mSize = 0; + mHead = mTail = 0; + } + + /** + * Initializes a queue with default starting capacity. + */ + public LongArrayQueue() { + this(16); + } + + /** @hide */ + public static int growSize(int currentSize) { + return currentSize <= 4 ? 8 : currentSize * 2; + } + + private void grow() { + if (mSize < mValues.length) { + throw new IllegalStateException("Queue not full yet!"); + } + final int newSize = growSize(mSize); + final long[] newArray = newUnpaddedLongArray(newSize); + final int r = mValues.length - mHead; // Number of elements on and to the right of head. + System.arraycopy(mValues, mHead, newArray, 0, r); + System.arraycopy(mValues, 0, newArray, r, mHead); + mValues = newArray; + mHead = 0; + mTail = mSize; + } + + /** + * Returns the number of elements in the queue. + */ + public int size() { + return mSize; + } + + /** + * Removes all elements from this queue. + */ + public void clear() { + mSize = 0; + mHead = mTail = 0; + } + + /** + * Adds a value to the tail of the queue. + * + * @param value the value to be added. + */ + public void addLast(long value) { + if (mSize == mValues.length) { + grow(); + } + mValues[mTail] = value; + mTail = (mTail + 1) % mValues.length; + mSize++; + } + + /** + * Removes an element from the head of the queue. + * + * @return the element at the head of the queue. + * @throws NoSuchElementException if the queue is empty. + */ + public long removeFirst() { + if (mSize == 0) { + throw new NoSuchElementException("Queue is empty!"); + } + final long ret = mValues[mHead]; + mHead = (mHead + 1) % mValues.length; + mSize--; + return ret; + } + + /** + * Returns the element at the given position from the head of the queue, where 0 represents the + * head of the queue. + * + * @param position the position from the head of the queue. + * @return the element found at the given position. + * @throws IndexOutOfBoundsException if {@code position} < {@code 0} or + * {@code position} >= {@link #size()} + */ + public long get(int position) { + if (position < 0 || position >= mSize) { + throw new IndexOutOfBoundsException("Index " + position + + " not valid for a queue of size " + mSize); + } + final int index = (mHead + position) % mValues.length; + return mValues[index]; + } + + /** + * Returns the element at the head of the queue, without removing it. + * + * @return the element at the head of the queue. + * @throws NoSuchElementException if the queue is empty + */ + public long peekFirst() { + if (mSize == 0) { + throw new NoSuchElementException("Queue is empty!"); + } + return mValues[mHead]; + } + + /** + * Returns the element at the tail of the queue. + * + * @return the element at the tail of the queue. + * @throws NoSuchElementException if the queue is empty. + */ + public long peekLast() { + if (mSize == 0) { + throw new NoSuchElementException("Queue is empty!"); + } + final int index = (mTail == 0) ? mValues.length - 1 : mTail - 1; + return mValues[index]; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + if (mSize <= 0) { + return "{}"; + } + + final StringBuilder buffer = new StringBuilder(mSize * 64); + buffer.append('{'); + buffer.append(get(0)); + for (int i = 1; i < mSize; i++) { + buffer.append(", "); + buffer.append(get(i)); + } + buffer.append('}'); + return buffer.toString(); + } +} diff --git a/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java b/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java new file mode 100644 index 000000000000..dbbef61f6777 --- /dev/null +++ b/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.utils; + +import android.annotation.NonNull; +import android.system.ErrnoException; +import android.system.Os; + +import com.android.modules.utils.TypedXmlPullParser; + +import libcore.util.XmlObjectFactory; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Copied over partly from frameworks/base/core/java/com/android/internal/util/XmlUtils.java + * + * @hide + */ +public class XmlUtils { + + private static final String STRING_ARRAY_SEPARATOR = ":"; + + /** @hide */ + public static final void beginDocument(XmlPullParser parser, String firstElementName) + throws XmlPullParserException, IOException { + int type; + while ((type = parser.next()) != parser.START_TAG + && type != parser.END_DOCUMENT) { + // Do nothing + } + + if (type != parser.START_TAG) { + throw new XmlPullParserException("No start tag found"); + } + + if (!parser.getName().equals(firstElementName)) { + throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + + ", expected " + firstElementName); + } + } + + /** @hide */ + public static boolean nextElementWithin(XmlPullParser parser, int outerDepth) + throws IOException, XmlPullParserException { + for (;;) { + int type = parser.next(); + if (type == XmlPullParser.END_DOCUMENT + || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) { + return false; + } + if (type == XmlPullParser.START_TAG + && parser.getDepth() == outerDepth + 1) { + return true; + } + } + } + + private static XmlPullParser newPullParser() { + try { + XmlPullParser parser = XmlObjectFactory.newXmlPullParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + return parser; + } catch (XmlPullParserException e) { + throw new AssertionError(); + } + } + + /** @hide */ + public static @NonNull TypedXmlPullParser resolvePullParser(@NonNull InputStream in) + throws IOException { + final byte[] magic = new byte[4]; + if (in instanceof FileInputStream) { + try { + Os.pread(((FileInputStream) in).getFD(), magic, 0, magic.length, 0); + } catch (ErrnoException e) { + throw e.rethrowAsIOException(); + } + } else { + if (!in.markSupported()) { + in = new BufferedInputStream(in); + } + in.mark(8); + in.read(magic); + in.reset(); + } + + final TypedXmlPullParser xml; + xml = (TypedXmlPullParser) newPullParser(); + try { + xml.setInput(in, "UTF_8"); + } catch (XmlPullParserException e) { + throw new IOException(e); + } + return xml; + } +} diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml index a24134b3ff3f..b17293dbe4e2 100644 --- a/packages/CredentialManager/res/values-af/strings.xml +++ b/packages/CredentialManager/res/values-af/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Skep toegangsleutel om by <xliff:g id="APP_NAME">%1$s</xliff:g> aan te meld?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Stoor wagwoord om by <xliff:g id="APP_NAME">%1$s</xliff:g> aan te meld?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Stoor aanmeldinligting vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Gebruik jou skermslot om ’n toegangsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g> te skep?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Gebruik jou skermslot om ’n wagwoord vir <xliff:g id="APP_NAME">%1$s</xliff:g> te skep?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Gebruik jou skermslot om aanmeldinligting vir <xliff:g id="APP_NAME">%1$s</xliff:g> te stoor?"</string> <string name="passkey" msgid="632353688396759522">"toegangsleutel"</string> <string name="password" msgid="6738570945182936667">"wagwoord"</string> <string name="passkeys" msgid="5733880786866559847">"toegangsleutels"</string> diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml index 0554d81c0d6b..4ee07883d23e 100644 --- a/packages/CredentialManager/res/values-am/strings.xml +++ b/packages/CredentialManager/res/values-am/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"ወደ <xliff:g id="APP_NAME">%1$s</xliff:g> ለመግባት የይለፍ ቁልፍ ይፈጠር?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"ወደ <xliff:g id="APP_NAME">%1$s</xliff:g> ለመግባት የይለፍ ቃል ይቀመጥ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> የመግቢያ መረጃ ይቀመጥ?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የይለፍ ቁልፍ ለመፍጠር የማያ ገጽ መቆለፊያዎን መጠቀም ይፈልጋሉ?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የይለፍ ቃል ለመፍጠር የማያ ገጽ መቆለፊያዎን መጠቀም ይፈልጋሉ?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> መግቢያ መረጃን ለማስቀመጥ የማያ ገጽ መቆለፊያዎን መጠቀም ይፈልጋሉ?"</string> <string name="passkey" msgid="632353688396759522">"የይለፍ ቁልፍ"</string> <string name="password" msgid="6738570945182936667">"የይለፍ ቃል"</string> <string name="passkeys" msgid="5733880786866559847">"የይለፍ ቁልፎች"</string> diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml index 5e089fe5a301..7e141c244516 100644 --- a/packages/CredentialManager/res/values-ar/strings.xml +++ b/packages/CredentialManager/res/values-ar/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"هل تريد إنشاء مفتاح مرور لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"هل تريد حفظ كلمة المرور لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"هل تريد حفظ معلومات تسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"هل تريد استخدام قفل الشاشة لإنشاء مفتاح مرور لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"هل تريد استخدام قفل الشاشة لإنشاء كلمة مرور لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"هل تريد استخدام قفل الشاشة لحفظ معلومات تسجيل الدخول لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string> <string name="passkey" msgid="632353688396759522">"مفتاح المرور"</string> <string name="password" msgid="6738570945182936667">"كلمة المرور"</string> <string name="passkeys" msgid="5733880786866559847">"مفاتيح المرور"</string> diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml index 95a0e1b6a36d..cde91123d08b 100644 --- a/packages/CredentialManager/res/values-as/strings.xml +++ b/packages/CredentialManager/res/values-as/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g>ত ছাইন ইন কৰিবলৈ পাছকী সৃষ্টি কৰিবনে?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g>ত ছাইন ইন কৰিবলৈ পাছৱৰ্ড ছেভ কৰিবনে?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছাইন ইনৰ তথ্য ছেভ কৰিবনে?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে পাছকী সৃষ্টি কৰিবলৈ আপোনাৰ স্ক্ৰীন লক ব্যৱহাৰ কৰিবনে?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে পাছৱৰ্ড সৃষ্টি কৰিবলৈ আপোনাৰ স্ক্ৰীন লক ব্যৱহাৰ কৰিবনে?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছাইন ইনৰ তথ্য ছেভ কৰিবলৈ আপোনাৰ স্ক্ৰীন লক ব্যৱহাৰ কৰিবনে?"</string> <string name="passkey" msgid="632353688396759522">"পাছকী"</string> <string name="password" msgid="6738570945182936667">"পাছৱৰ্ড"</string> <string name="passkeys" msgid="5733880786866559847">"পাছকী"</string> diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml index 00a671847a38..1623ec4b292b 100644 --- a/packages/CredentialManager/res/values-az/strings.xml +++ b/packages/CredentialManager/res/values-az/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə daxil olmaq üçün giriş açarı yaradılsın?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə daxil olmaq üçün parol yadda saxlansın?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş məlumatları yadda saxlansın?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş açarı yaratmaq məqsədilə ekran kilidi istifadə edilsin?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün parol yaratmaq məqsədilə ekran kilidi istifadə edilsin?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş məlumatını yadda saxlamaq məqsədilə ekran kilidi istifadə edilsin?"</string> <string name="passkey" msgid="632353688396759522">"açar"</string> <string name="password" msgid="6738570945182936667">"parol"</string> <string name="passkeys" msgid="5733880786866559847">"açarlar"</string> diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml index 390c7742cde6..23c021e2528d 100644 --- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml +++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Želite da napravite pristupni ključ da biste se prijavili u <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Želite da sačuvate lozinku da biste se prijavili u <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Želite da sačuvate podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Želite da koristite otključavanje ekrana da biste napravili pristupni ključ za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Želite da koristite otključavanje ekrana da biste napravili lozinku za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Želite da koristite otključavanje ekrana da biste sačuvali podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"pristupni kôd"</string> <string name="password" msgid="6738570945182936667">"lozinka"</string> <string name="passkeys" msgid="5733880786866559847">"pristupni kodovi"</string> diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml index 6922e7052d91..d27f68bf56de 100644 --- a/packages/CredentialManager/res/values-be/strings.xml +++ b/packages/CredentialManager/res/values-be/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Стварыць ключ доступу для ўваходу ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Захаваць пароль для ўваходу ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Захаваць даныя для ўваходу ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"ключ доступу"</string> <string name="password" msgid="6738570945182936667">"пароль"</string> <string name="passkeys" msgid="5733880786866559847">"ключы доступу"</string> diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml index 3d33c8fd91f4..780699b450f7 100644 --- a/packages/CredentialManager/res/values-bg/strings.xml +++ b/packages/CredentialManager/res/values-bg/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Искате ли да създадете ключ за достъп, с който да влизате в(ъв) <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Искате ли да запазите паролата за влизане в(ъв) <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Искате ли да запазите данните за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"код за достъп"</string> <string name="password" msgid="6738570945182936667">"парола"</string> <string name="passkeys" msgid="5733880786866559847">"ключове за достъп"</string> diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml index fe42ed6f2ad1..9d429d4746a2 100644 --- a/packages/CredentialManager/res/values-bn/strings.xml +++ b/packages/CredentialManager/res/values-bn/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপে সাইন-ইন করার জন্য পাসকী তৈরি করবেন?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপে সাইন-ইন করার জন্য পাসওয়ার্ড সেভ করবেন?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপের জন্য সাইন-ইন সংক্রান্ত তথ্য সেভ করবেন?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"পাসকী"</string> <string name="password" msgid="6738570945182936667">"পাসওয়ার্ড"</string> <string name="passkeys" msgid="5733880786866559847">"পাসকী"</string> diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml index f6e6d811f2a6..00c211b48e01 100644 --- a/packages/CredentialManager/res/values-bs/strings.xml +++ b/packages/CredentialManager/res/values-bs/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Kreirati pristupni ključ da se prijavite u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Sačuvati lozinku da se prijavite u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Sačuvati podatke za prijavu u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Želite li upotrijebiti zaključavanje zaslona za izradu pristupnog ključa za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Želite li upotrijebiti zaključavanje zaslona za izradu zaporke za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Želite li upotrijebiti zaključavanje zaslona za spremanje podataka za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"pristupni ključ"</string> <string name="password" msgid="6738570945182936667">"lozinka"</string> <string name="passkeys" msgid="5733880786866559847">"pristupni ključevi"</string> diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml index 3809d9251f7c..cf08741ebc2f 100644 --- a/packages/CredentialManager/res/values-ca/strings.xml +++ b/packages/CredentialManager/res/values-ca/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Vols crear una clau d\'accés per iniciar la sessió a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Vols desar la contrasenya per iniciar la sessió a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vols desar la informació d\'inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"clau d\'accés"</string> <string name="password" msgid="6738570945182936667">"contrasenya"</string> <string name="passkeys" msgid="5733880786866559847">"claus d\'accés"</string> diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml index 6e6857c209d9..5e0d42e2d25f 100644 --- a/packages/CredentialManager/res/values-cs/strings.xml +++ b/packages/CredentialManager/res/values-cs/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Vytvořit přístupový klíč k přihlašování do aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Uložit heslo k přihlašování do aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Uložit přihlašovací údaje pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"přístupový klíč"</string> <string name="password" msgid="6738570945182936667">"heslo"</string> <string name="passkeys" msgid="5733880786866559847">"přístupové klíče"</string> diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml index ae7c3cfaf96e..e978b8e86890 100644 --- a/packages/CredentialManager/res/values-da/strings.xml +++ b/packages/CredentialManager/res/values-da/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Vil du oprette en adgangsnøgle for at logge ind på <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Vil du gemme adgangskoden for at logge ind på <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vil du gemme loginoplysningerne til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"adgangsnøgle"</string> <string name="password" msgid="6738570945182936667">"adgangskode"</string> <string name="passkeys" msgid="5733880786866559847">"adgangsnøgler"</string> diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml index 4fa669baa9d9..b338b1d92e48 100644 --- a/packages/CredentialManager/res/values-de/strings.xml +++ b/packages/CredentialManager/res/values-de/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Passkey zur Anmeldung in <xliff:g id="APP_NAME">%1$s</xliff:g> erstellen?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Passwort zur Anmeldung in <xliff:g id="APP_NAME">%1$s</xliff:g> speichern?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> speichern?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"Passkey"</string> <string name="password" msgid="6738570945182936667">"Passwort"</string> <string name="passkeys" msgid="5733880786866559847">"Passkeys"</string> diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml index b6b2728b8961..29ad56951449 100644 --- a/packages/CredentialManager/res/values-el/strings.xml +++ b/packages/CredentialManager/res/values-el/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Δημιουργία κλειδιού πρόσβασης για σύνδεση στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Αποθήκευση κωδικού πρόσβασης για σύνδεση στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Αποθήκευση πληροφοριών σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"κλειδί πρόσβασης"</string> <string name="password" msgid="6738570945182936667">"κωδικός πρόσβασης"</string> <string name="passkeys" msgid="5733880786866559847">"κλειδιά πρόσβασης"</string> diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml index f177cf981e8c..b8bef997a383 100644 --- a/packages/CredentialManager/res/values-en-rAU/strings.xml +++ b/packages/CredentialManager/res/values-en-rAU/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Create passkey to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Save password to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Save sign-in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"passkeys"</string> diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml index df4cd86e6d20..3fb3d55e655d 100644 --- a/packages/CredentialManager/res/values-en-rCA/strings.xml +++ b/packages/CredentialManager/res/values-en-rCA/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Create passkey to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Save password to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Save sign-in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Use your screen lock to create a passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Use your screen lock to create a password for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Use your screen lock to save sign in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"passkeys"</string> diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml index f177cf981e8c..b8bef997a383 100644 --- a/packages/CredentialManager/res/values-en-rGB/strings.xml +++ b/packages/CredentialManager/res/values-en-rGB/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Create passkey to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Save password to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Save sign-in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"passkeys"</string> diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml index f177cf981e8c..b8bef997a383 100644 --- a/packages/CredentialManager/res/values-en-rIN/strings.xml +++ b/packages/CredentialManager/res/values-en-rIN/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Create passkey to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Save password to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Save sign-in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"passkeys"</string> diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml index 77ae53afc700..b642c87bf28a 100644 --- a/packages/CredentialManager/res/values-en-rXC/strings.xml +++ b/packages/CredentialManager/res/values-en-rXC/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Create passkey to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Save password to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Save sign-in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Use your screen lock to create a passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Use your screen lock to create a password for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Use your screen lock to save sign in info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"passkeys"</string> diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml index 6ccfec3d8a15..3b4392d924e7 100644 --- a/packages/CredentialManager/res/values-es-rUS/strings.xml +++ b/packages/CredentialManager/res/values-es-rUS/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"¿Quieres crear una llave de acceso para acceder a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"¿Quieres guardar la contraseña para acceder a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"¿Quieres guardar la información de acceso para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"llave de acceso"</string> <string name="password" msgid="6738570945182936667">"contraseña"</string> <string name="passkeys" msgid="5733880786866559847">"llaves de acceso"</string> diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml index b2c1c6fe4915..427ed1d69c25 100644 --- a/packages/CredentialManager/res/values-es/strings.xml +++ b/packages/CredentialManager/res/values-es/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"¿Crear llave de acceso para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"¿Guardar contraseña para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"¿Guardar la información de inicio de sesión de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"llave de acceso"</string> <string name="password" msgid="6738570945182936667">"contraseña"</string> <string name="passkeys" msgid="5733880786866559847">"llaves de acceso"</string> diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml index 823a016e8d8f..44b907e4b08d 100644 --- a/packages/CredentialManager/res/values-et/strings.xml +++ b/packages/CredentialManager/res/values-et/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Kas luua rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks pääsuvõti?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Kas salvestada rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks parool?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Kas salvestada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks sisselogimisteave?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"pääsuvõti"</string> <string name="password" msgid="6738570945182936667">"parool"</string> <string name="passkeys" msgid="5733880786866559847">"pääsuvõtmed"</string> diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml index 8507b3f21997..afc91ea2cdb2 100644 --- a/packages/CredentialManager/res/values-eu/strings.xml +++ b/packages/CredentialManager/res/values-eu/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan saioa hasteko sarbide-gako bat sortu nahi duzu?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan saioa hasteko pasahitza gorde nahi duzu?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan saioa hasteko informazioa gorde nahi duzu?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"sarbide-gakoa"</string> <string name="password" msgid="6738570945182936667">"pasahitza"</string> <string name="passkeys" msgid="5733880786866559847">"sarbide-gakoak"</string> @@ -75,7 +81,7 @@ <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan saioa hasteko aukerak desblokeatu nahi dituzu?"</string> <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako sarbide-gakoa"</string> <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako pasahitza"</string> - <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako kredentzialak"</string> + <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako saioa hasteko moduak"</string> <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> zerbitzuan saioa hasteko kredentzialak"</string> <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako aukera bat hautatu nahi duzu?"</string> <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan erabili nahi duzu informazio hori?"</string> @@ -89,10 +95,10 @@ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Desblokeatzeko, sakatu hau"</string> <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ez dago saioa hasteko informaziorik"</string> <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ez dago saioa hasteko informaziorik <xliff:g id="SOURCE">%1$s</xliff:g> kontuan"</string> - <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kudeatu kredentzialak"</string> + <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kudeatu saioa hasteko moduak"</string> <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Beste gailu batean gordetakoak"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Erabili beste gailu bat"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"Utzi du bertan behera eskaera <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak"</string> - <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Saioa hasteko aukerak"</string> + <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Saioa hasteko moduak"</string> <string name="more_options_content_description" msgid="1323427365788198808">"Gehiago"</string> </resources> diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml index 656c789a72b8..095cb0614ca5 100644 --- a/packages/CredentialManager/res/values-fa/strings.xml +++ b/packages/CredentialManager/res/values-fa/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"برای ورود به سیستم <xliff:g id="APP_NAME">%1$s</xliff:g>، گذرکلید ایجاد شود؟"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"برای ورود به سیستم <xliff:g id="APP_NAME">%1$s</xliff:g>، گذرواژه ذخیره شود؟"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"اطلاعات ورود به سیستم <xliff:g id="APP_NAME">%1$s</xliff:g> ذخیره شود؟"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"گذرکلید"</string> <string name="password" msgid="6738570945182936667">"گذرواژه"</string> <string name="passkeys" msgid="5733880786866559847">"گذرکلیدها"</string> diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml index f2f1bfbb4d1e..7de1151f2117 100644 --- a/packages/CredentialManager/res/values-fi/strings.xml +++ b/packages/CredentialManager/res/values-fi/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Luodaanko avainkoodi sisäänkirjautumista (<xliff:g id="APP_NAME">%1$s</xliff:g>) varten?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Tallennetaanko salasana sisäänkirjautumista (<xliff:g id="APP_NAME">%1$s</xliff:g>) varten?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Tallennetaanko kirjautumistiedot (<xliff:g id="APP_NAME">%1$s</xliff:g>)?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"avainkoodi"</string> <string name="password" msgid="6738570945182936667">"salasana"</string> <string name="passkeys" msgid="5733880786866559847">"avainkoodit"</string> diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml index 891e98791449..519b14ace029 100644 --- a/packages/CredentialManager/res/values-fr-rCA/strings.xml +++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Créer une clé d\'accès pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Enregistrer un mot de passe pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Enregistrer les renseignements de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"clé d\'accès"</string> <string name="password" msgid="6738570945182936667">"mot de passe"</string> <string name="passkeys" msgid="5733880786866559847">"clés d\'accès"</string> diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml index f2ca1fc4028c..f63c7c2aee2b 100644 --- a/packages/CredentialManager/res/values-fr/strings.xml +++ b/packages/CredentialManager/res/values-fr/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Créer une clé d\'accès pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Enregistrer un mot de passe pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Enregistrer les informations de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"clé d\'accès"</string> <string name="password" msgid="6738570945182936667">"mot de passe"</string> <string name="passkeys" msgid="5733880786866559847">"clés d\'accès"</string> @@ -75,7 +81,7 @@ <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Déverrouiller les options de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choisir une clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choisir un mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choisir des informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choisissez les identifiants à utiliser pour la connexion à <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Choisir des infos de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choisir une option pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Utiliser ces informations dans <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml index 7117e1c00794..d756200c11d4 100644 --- a/packages/CredentialManager/res/values-gl/strings.xml +++ b/packages/CredentialManager/res/values-gl/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Queres crear unha clave de acceso para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Queres gardar o contrasinal para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Queres gardar a información de inicio de sesión de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"clave de acceso"</string> <string name="password" msgid="6738570945182936667">"contrasinal"</string> <string name="passkeys" msgid="5733880786866559847">"claves de acceso"</string> @@ -75,7 +81,7 @@ <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Queres desbloquear as opcións de inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Escolle unha clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Escolle un contrasinal gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Escolle un método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Escolle un inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Escolle un inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Queres escoller unha opción para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Queres usar esta información en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml index 98b4686716ec..ed081288bffb 100644 --- a/packages/CredentialManager/res/values-gu/strings.xml +++ b/packages/CredentialManager/res/values-gu/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g>માં સાઇન ઇન કરવા માટે પાસકી બનાવીએ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g>માં સાઇન ઇન કરવા માટે પાસવર્ડ સાચવીએ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સાઇન-ઇન કરવાની માહિતી સાચવીએ?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ પાસકી બનાવવા માટે, શું તમારા સ્ક્રીન લૉકનો ઉપયોગ કરીએ?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ પાસવર્ડ બનાવવા માટે, શું તમારા સ્ક્રીન લૉકનો ઉપયોગ કરીએ?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સાઇન ઇનની માહિતી સાચવવા માટે, શું તમારા સ્ક્રીન લૉકનો ઉપયોગ કરીએ?"</string> <string name="passkey" msgid="632353688396759522">"પાસકી"</string> <string name="password" msgid="6738570945182936667">"પાસવર્ડ"</string> <string name="passkeys" msgid="5733880786866559847">"પાસકી"</string> diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml index 9bc5feb6e9e9..16f04c5432b2 100644 --- a/packages/CredentialManager/res/values-hi/strings.xml +++ b/packages/CredentialManager/res/values-hi/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए पासकी बनानी है?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए पासवर्ड सेव करना है?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> के लिए साइन-इन की जानकारी सेव करनी है?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"क्या स्क्रीन लॉक का इस्तेमाल करके, <xliff:g id="APP_NAME">%1$s</xliff:g> के लिए पासकी बनानी है?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"क्या स्क्रीन लॉक का इस्तेमाल करके, <xliff:g id="APP_NAME">%1$s</xliff:g> के लिए पासवर्ड बनाना है?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"क्या स्क्रीन लॉक का इस्तेमाल करके, <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने की जानकारी सेव करनी है?"</string> <string name="passkey" msgid="632353688396759522">"पासकी"</string> <string name="password" msgid="6738570945182936667">"पासवर्ड"</string> <string name="passkeys" msgid="5733880786866559847">"पासकी"</string> @@ -75,24 +78,24 @@ <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के विकल्पों को अनलॉक करना है?"</string> <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव की गई पासकी चुनें"</string> <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया गया पासवर्ड चुनें"</string> - <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया गया साइन इन क्रेडेंशियल चुनें"</string> + <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया गया क्रेडेंशियल चुनें"</string> <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए साइन-इन क्रेडेंशियल चुनें"</string> <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए सेव किए गए विकल्पों में से किसी को चुनना है?"</string> <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए, क्या इस जानकारी का इस्तेमाल करना है?"</string> <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"किसी दूसरे तरीके से साइन इन करें"</string> <string name="snackbar_action" msgid="37373514216505085">"विकल्प देखें"</string> <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"जारी रखें"</string> - <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन इन करने के विकल्प"</string> + <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन-इन करने के लिए विकल्प"</string> <string name="button_label_view_more" msgid="3429098227286495651">"ज़्यादा देखें"</string> <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> के लिए"</string> <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक किए गए पासवर्ड मैनेजर"</string> <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करने के लिए टैप करें"</string> <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन करने से जुड़ी कोई जानकारी उपलब्ध नहीं है"</string> <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> में साइन-इन की जानकारी नहीं है"</string> - <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इन करने की सुविधा को मैनेज करें"</string> + <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन-इन किए गए खाते मैनेज करें"</string> <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"किसी दूसरे डिवाइस से"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"दूसरे डिवाइस का इस्तेमाल करें"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g> की ओर से अनुरोध रद्द किया गया"</string> - <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन-इन करने के विकल्प"</string> + <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन-इन करने के लिए विकल्प"</string> <string name="more_options_content_description" msgid="1323427365788198808">"ज़्यादा"</string> </resources> diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml index 968a7472d58e..2c10c2122ce3 100644 --- a/packages/CredentialManager/res/values-hr/strings.xml +++ b/packages/CredentialManager/res/values-hr/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Želite li izraditi pristupni ključ za prijavu u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Želite li spremiti zaporku za prijavu u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Želite li spremiti informacije o prijavi za <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Želite li upotrijebiti zaključavanje zaslona za izradu pristupnog ključa za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Želite li upotrijebiti zaključavanje zaslona za izradu zaporke za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Želite li upotrijebiti zaključavanje zaslona za spremanje podataka za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"pristupni ključ"</string> <string name="password" msgid="6738570945182936667">"zaporka"</string> <string name="passkeys" msgid="5733880786866559847">"pristupni ključevi"</string> diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml index e601da676a2f..fe749f6129a8 100644 --- a/packages/CredentialManager/res/values-hu/strings.xml +++ b/packages/CredentialManager/res/values-hu/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Létrehoz azonosítókulcsot a következőbe való bejelentkezéshez: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Menti a jelszót a következőbe való bejelentkezéshez: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Menti a bejelentkezési adatokat a következőhöz: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"azonosítókulcs"</string> <string name="password" msgid="6738570945182936667">"jelszó"</string> <string name="passkeys" msgid="5733880786866559847">"azonosítókulcsait"</string> @@ -75,7 +81,7 @@ <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Feloldja a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> bejelentkezési lehetőségeit?"</string> <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Mentett azonosítókulcs kiválasztása a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string> <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Mentett jelszó kiválasztása a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string> - <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Mentett bejelentkezési adatok kiválasztása a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string> + <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Mentett bejelentkezési adatok kiválasztása – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Válasszon bejelentkezési adatokat – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Kiválaszt egy lehetőséget a következőbe való bejelentkezéshez: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Használni szeretná ezt az információt a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásban?"</string> diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml index 79a2624e980f..452acb7a18b2 100644 --- a/packages/CredentialManager/res/values-hy/strings.xml +++ b/packages/CredentialManager/res/values-hy/strings.xml @@ -27,7 +27,7 @@ <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Անցաբառերի հետ ավելի ապահով է"</string> <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Անցաբառերի շնորհիվ դուք բարդ գաղտնաբառեր ստեղծելու կամ հիշելու անհրաժեշտություն չեք ունենա"</string> <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Անցաբառերը գաղտնագրված թվային բանալիներ են, որոնք ստեղծվում են մատնահետքի, դեմքով ապակողպման կամ էկրանի կողպման օգտագործմամբ"</string> - <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Դուք կարող եք մուտք գործել այլ սարքերում, քանի որ անցաբառերը պահվում են գաղտնաբառերի կառավարիչում"</string> + <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Դուք կարող եք մուտք գործել այլ սարքերում, քանի որ մուտքի բանալիները պահվում են գաղտնաբառերի կառավարիչում"</string> <string name="more_about_passkeys_title" msgid="7797903098728837795">"Ավելին՝ անցաբառերի մասին"</string> <string name="passwordless_technology_title" msgid="2497513482056606668">"Գաղտնաբառեր չպահանջող տեխնոլոգիա"</string> <string name="passwordless_technology_detail" msgid="6853928846532955882">"Անցաբառերը ձեզ թույլ են տալիս մուտք գործել առանց գաղտնաբառերի։ Ձեզ պարզապես հարկավոր է օգտագործել ձեր մատնահետքը, դիմաճանաչումը, PIN կոդը կամ նախշը՝ ձեր ինքնությունը հաստատելու և անցաբառ ստեղծելու համար։"</string> @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Ստեղծե՞լ անցաբառ՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Պահե՞լ գաղտնաբառը՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Պահե՞լ «<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածի մուտքի տվյալները"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"անցաբառ"</string> <string name="password" msgid="6738570945182936667">"գաղտնաբառ"</string> <string name="passkeys" msgid="5733880786866559847">"անցաբառեր"</string> @@ -53,7 +59,7 @@ <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Պահե՞լ գաղտնաբառն այլ սարքում"</string> <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Պահե՞լ մուտքի տվյալներն այլ սարքում"</string> <string name="use_provider_for_all_title" msgid="4201020195058980757">"Միշտ մուտք գործե՞լ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> հավելվածի միջոցով"</string> - <string name="use_provider_for_all_description" msgid="1998772715863958997">"Այս գաղտնաբառերի կառավարչում <xliff:g id="USERNAME">%1$s</xliff:g> օգտատերը կկարողանա պահել իր գաղտնաբառերն ու անցաբառերը, որպեսզի հետագայում ավելի արագ մուտք գործի հաշիվ"</string> + <string name="use_provider_for_all_description" msgid="1998772715863958997">"Այս գաղտնաբառերի կառավարչում <xliff:g id="USERNAME">%1$s</xliff:g> օգտատերը կկարողանա պահել իր գաղտնաբառերն ու մուտքի բանալիները, որպեսզի հետագայում ավելի արագ մուտք գործի հաշիվ"</string> <string name="set_as_default" msgid="4415328591568654603">"Նշել որպես կանխադրված"</string> <string name="settings" msgid="6536394145760913145">"Կարգավորումներ"</string> <string name="use_once" msgid="9027366575315399714">"Օգտագործել մեկ անգամ"</string> diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml index e7556b01d730..3eac6e97f986 100644 --- a/packages/CredentialManager/res/values-in/strings.xml +++ b/packages/CredentialManager/res/values-in/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Buat kunci sandi untuk login ke <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Simpan sandi untuk login ke <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Simpan info login untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Gunakan kunci layar Anda untuk membuat kunci sandi untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Gunakan kunci layar Anda untuk membuat sandi untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Gunakan kunci layar Anda untuk menyimpan info login untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"kunci sandi"</string> <string name="password" msgid="6738570945182936667">"sandi"</string> <string name="passkeys" msgid="5733880786866559847">"kunci sandi"</string> diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml index 970a2e647c8a..9fd552b11568 100644 --- a/packages/CredentialManager/res/values-is/strings.xml +++ b/packages/CredentialManager/res/values-is/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Búa til aðgangslykil til að skrá þig inn á <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Vista aðgangsorð til að skrá þig inn á <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Viltu vista innskráningarupplýsingar fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Nota skjálásinn til að búa til aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Nota skjálásinn til að búa til aðgangsorð fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Nota skjálásinn til að vista innskráningarupplýsingar fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"aðgangslykill"</string> <string name="password" msgid="6738570945182936667">"aðgangsorð"</string> <string name="passkeys" msgid="5733880786866559847">"aðgangslykla"</string> diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml index a04a840b5148..ce04dbc556b5 100644 --- a/packages/CredentialManager/res/values-it/strings.xml +++ b/packages/CredentialManager/res/values-it/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Creare passkey per accedere all\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Salvare password per accedere all\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vuoi salvare i dati di accesso di <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"passkey"</string> diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml index 87dee5fa8d5f..07b26b7d9c59 100644 --- a/packages/CredentialManager/res/values-iw/strings.xml +++ b/packages/CredentialManager/res/values-iw/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"ליצור מפתח גישה כדי להיכנס לחשבון ב-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"לשמור את הסיסמה כדי להיכנס לחשבון ב-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"לשמור את פרטי הכניסה של <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"מפתח גישה"</string> <string name="password" msgid="6738570945182936667">"סיסמה"</string> <string name="passkeys" msgid="5733880786866559847">"מפתחות גישה"</string> diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml index 71746dc63994..f12bb5e50937 100644 --- a/packages/CredentialManager/res/values-ja/strings.xml +++ b/packages/CredentialManager/res/values-ja/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> にログインするためにパスキーを作成しますか?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> にログインするためにパスワードを保存しますか?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> のログイン情報を保存しますか?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"パスキー"</string> <string name="password" msgid="6738570945182936667">"パスワード"</string> <string name="passkeys" msgid="5733880786866559847">"パスキー"</string> diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml index 51f1332eba1d..4c6154040a7d 100644 --- a/packages/CredentialManager/res/values-ka/strings.xml +++ b/packages/CredentialManager/res/values-ka/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"შესასვლელად წვდომის გასაღების შექმნა: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"შესასვლელი პაროლის შენახვა: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"აპში შესვლის ინფორმაციის შენახვა: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"წვდომის გასაღები"</string> <string name="password" msgid="6738570945182936667">"პაროლი"</string> <string name="passkeys" msgid="5733880786866559847">"წვდომის გასაღები"</string> diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml index 7393ca08c1bc..5b76ac89f47e 100644 --- a/packages/CredentialManager/res/values-kk/strings.xml +++ b/packages/CredentialManager/res/values-kk/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына кіру үшін кіру кілті жасалсын ба?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына кіру үшін құпия сөз сақталсын ба?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін кіру мәліметін сақтау керек пе?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"Кіру кілті"</string> <string name="password" msgid="6738570945182936667">"құпия сөз"</string> <string name="passkeys" msgid="5733880786866559847">"кіру кілттері"</string> @@ -75,7 +81,7 @@ <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін кіру опциялары ашылсын ба?"</string> <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілтін таңдаңыз"</string> <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған құпия сөзді таңдаңыз"</string> - <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректерін таңдаңыз"</string> + <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру деректерін таңдаңыз"</string> <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына кіру деректерін таңдаңыз"</string> <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін опция таңдайсыз ба?"</string> <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Бұл ақпарат <xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасында сақталсын ба?"</string> diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml index ac0d42704389..279474f96cb1 100644 --- a/packages/CredentialManager/res/values-km/strings.xml +++ b/packages/CredentialManager/res/values-km/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"បង្កើតកូដសម្ងាត់ ដើម្បីចូលគណនី <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"រក្សាទុកពាក្យសម្ងាត់ ដើម្បីចូលគណនី <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"រក្សាទុកព័ត៌មានចូលគណនីសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"ប្រើមុខងារចាក់សោអេក្រង់របស់អ្នក ដើម្បីបង្កើតកូដសម្ងាត់សម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"ប្រើមុខងារចាក់សោអេក្រង់របស់អ្នក ដើម្បីបង្កើតពាក្យសម្ងាត់សម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"ប្រើមុខងារចាក់សោអេក្រង់របស់អ្នក ដើម្បីរក្សាទុកព័ត៌មានចូលគណនីសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> <string name="passkey" msgid="632353688396759522">"កូដសម្ងាត់"</string> <string name="password" msgid="6738570945182936667">"ពាក្យសម្ងាត់"</string> <string name="passkeys" msgid="5733880786866559847">"កូដសម្ងាត់"</string> diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml index 031fa65114bf..01d0f59fe985 100644 --- a/packages/CredentialManager/res/values-kn/strings.xml +++ b/packages/CredentialManager/res/values-kn/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು ಪಾಸ್ಕೀ ಯನ್ನು ರಚಿಸಬೇಕೇ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಸೇವ್ ಮಾಡಬೇಕೇ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಸೇವ್ ಮಾಡಬೇಕೇ?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"ಪಾಸ್ಕೀ"</string> <string name="password" msgid="6738570945182936667">"ಪಾಸ್ವರ್ಡ್"</string> <string name="passkeys" msgid="5733880786866559847">"ಪಾಸ್ಕೀಗಳು"</string> diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml index e29ae68f7dc9..1f1fa2990d87 100644 --- a/packages/CredentialManager/res/values-ko/strings.xml +++ b/packages/CredentialManager/res/values-ko/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"패스키를 생성하여 <xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인하시겠습니까?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"비밀번호를 저장하여 <xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인하시겠습니까?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 로그인 정보를 저장하시겠습니까?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"패스키"</string> <string name="password" msgid="6738570945182936667">"비밀번호"</string> <string name="passkeys" msgid="5733880786866559847">"패스키"</string> diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml index 5e48ae5b2b2e..4e3fed1e1874 100644 --- a/packages/CredentialManager/res/values-ky/strings.xml +++ b/packages/CredentialManager/res/values-ky/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна кирүү үчүн киргизүүчү ачкычты түзөсүзбү?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна кирүү үчүн сырсөздү сактайсызбы?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн кирүү маалыматы сакталсынбы?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн киргизүүчү ачкыч катары экрандын кулпусун колдоносузбу?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн сырсөз катары экрандын кулпусун колдоносузбу?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн кирүү маалыматы катары экрандын кулпусун колдоносузбу?"</string> <string name="passkey" msgid="632353688396759522">"киргизүүчү ачкыч"</string> <string name="password" msgid="6738570945182936667">"сырсөз"</string> <string name="passkeys" msgid="5733880786866559847">"киргизүүчү ачкычтар"</string> diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml index c3733a3ef1c3..e0f8839f1465 100644 --- a/packages/CredentialManager/res/values-lo/strings.xml +++ b/packages/CredentialManager/res/values-lo/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"ສ້າງກະແຈຜ່ານເພື່ອເຂົ້າສູ່ລະບົບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"ບັນທຶກລະຫັດຜ່ານເພື່ອເຂົ້າສູ່ລະບົບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"ບັນທຶກຂໍ້ມູນການເຂົ້າສູ່ລະບົບສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"ໃຊ້ລັອກໜ້າຈໍຂອງທ່ານເພື່ອສ້າງກະແຈຜ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"ໃຊ້ລັອກໜ້າຈໍຂອງທ່ານເພື່ອສ້າງລະຫັດຜ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"ໃຊ້ລັອກໜ້າຈໍຂອງທ່ານເພື່ອບັນທຶກຂໍ້ມູນການເຂົ້າສູ່ລະບົບສຳລັບ<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> <string name="passkey" msgid="632353688396759522">"ກະແຈຜ່ານ"</string> <string name="password" msgid="6738570945182936667">"ລະຫັດຜ່ານ"</string> <string name="passkeys" msgid="5733880786866559847">"ກະແຈຜ່ານ"</string> diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml index 453a0e0236eb..3b0124cf2249 100644 --- a/packages/CredentialManager/res/values-lt/strings.xml +++ b/packages/CredentialManager/res/values-lt/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Sukurti prieigos raktą, skirtą prisijungti prie „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Sukurti slaptažodį, skirtą prisijungti prie „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Išsaugoti prisijungimo prie „<xliff:g id="APP_NAME">%1$s</xliff:g>“ informaciją?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"„passkey“"</string> <string name="password" msgid="6738570945182936667">"slaptažodis"</string> <string name="passkeys" msgid="5733880786866559847">"prieigos raktas"</string> diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml index 4da1051fe8fd..095fbeeea072 100644 --- a/packages/CredentialManager/res/values-lv/strings.xml +++ b/packages/CredentialManager/res/values-lv/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Vai izveidot piekļuves atslēgu, lai pierakstītos lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Vai saglabāt paroli, lai pierakstītos lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vai saglabāt pierakstīšanās informāciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"piekļuves atslēga"</string> <string name="password" msgid="6738570945182936667">"parole"</string> <string name="passkeys" msgid="5733880786866559847">"piekļuves atslēgas"</string> @@ -93,6 +99,6 @@ <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"No citas ierīces"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Izmantot citu ierīci"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g> atcēla pieprasījumu"</string> - <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Pierakstīšanās iespējas"</string> + <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Pierakstīšanās opcijas"</string> <string name="more_options_content_description" msgid="1323427365788198808">"Vairāk"</string> </resources> diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml index 95554a2330fb..0f22f6fc81fa 100644 --- a/packages/CredentialManager/res/values-mk/strings.xml +++ b/packages/CredentialManager/res/values-mk/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Да се создаде криптографски клуч за најавување на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Да се зачува лозинката за најавување на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Да се зачуваат податоците за најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"криптографски клуч"</string> <string name="password" msgid="6738570945182936667">"лозинка"</string> <string name="passkeys" msgid="5733880786866559847">"криптографски клучеви"</string> diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml index eccfb511b16c..f7d74fe2b05a 100644 --- a/packages/CredentialManager/res/values-ml/strings.xml +++ b/packages/CredentialManager/res/values-ml/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്യാൻ പാസ്കീ സൃഷ്ടിക്കണോ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്യാൻ പാസ്വേഡ് സംരക്ഷിക്കണോ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി സൈൻ ഇൻ വിവരങ്ങൾ സംരക്ഷിക്കണോ?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി പാസ്കീ സൃഷ്ടിക്കാൻ നിങ്ങളുടെ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കണോ?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി പാസ്വേഡ് സൃഷ്ടിക്കാൻ നിങ്ങളുടെ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കണോ?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി സൈൻ ഇൻ വിവരങ്ങൾ സംരക്ഷിക്കാൻ നിങ്ങളുടെ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കണോ?"</string> <string name="passkey" msgid="632353688396759522">"പാസ്കീ"</string> <string name="password" msgid="6738570945182936667">"പാസ്വേഡ്"</string> <string name="passkeys" msgid="5733880786866559847">"പാസ്കീകൾ"</string> diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml index 5b1cbe90c63a..5554670b4d2d 100644 --- a/packages/CredentialManager/res/values-mn/strings.xml +++ b/packages/CredentialManager/res/values-mn/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д нэвтрэхийн тулд нэвтрэх түлхүүр үүсгэх үү?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д нэвтрэхийн тулд нууц үгийг хадгалах уу?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н нэвтрэх мэдээллийг хадгалах уу?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"нууц үг"</string> <string name="passkeys" msgid="5733880786866559847">"нэвтрэх түлхүүрүүд"</string> diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml index a0a4a7de1146..ce415f5efd41 100644 --- a/packages/CredentialManager/res/values-mr/strings.xml +++ b/packages/CredentialManager/res/values-mr/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> मध्ये साइन इन करण्यासाठी पासकी तयार करायची आहे का?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> मध्ये साइन इन करण्यासाठी पासवर्ड सेव्ह करायचा आहे का?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी साइन-इनसंबंधित माहिती सेव्ह करायची का?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"पासकी"</string> <string name="password" msgid="6738570945182936667">"पासवर्ड"</string> <string name="passkeys" msgid="5733880786866559847">"पासकी"</string> @@ -82,7 +88,7 @@ <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"दुसऱ्या मार्गाने साइन इन करा"</string> <string name="snackbar_action" msgid="37373514216505085">"पर्याय पहा"</string> <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"पुढे सुरू ठेवा"</string> - <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन इन पर्याय"</string> + <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन-इन पर्याय"</string> <string name="button_label_view_more" msgid="3429098227286495651">"आणखी पहा"</string> <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> साठी"</string> <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक केलेले पासवर्ड व्यवस्थापक"</string> @@ -93,6 +99,6 @@ <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"दुसऱ्या डिव्हाइस वरून"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"वेगळे डिव्हाइस वापरा"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g> ने विनंती रद्द केली आहे"</string> - <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन इन करण्याचे पर्याय"</string> + <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन-इन पर्याय"</string> <string name="more_options_content_description" msgid="1323427365788198808">"आणखी"</string> </resources> diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml index c866013d9478..62a7deb2f553 100644 --- a/packages/CredentialManager/res/values-ms/strings.xml +++ b/packages/CredentialManager/res/values-ms/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Buat kunci laluan untuk log masuk ke <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Simpan kata laluan untuk log masuk ke <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Simpan maklumat log masuk untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Gunakan kunci skrin anda untuk membuat kunci laluan bagi <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Gunakan kunci skrin anda untuk membuat kata laluan bagi <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Gunakan kunci skrin anda untuk menyimpan maklumat log masuk bagi <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"kunci laluan"</string> <string name="password" msgid="6738570945182936667">"kata laluan"</string> <string name="passkeys" msgid="5733880786866559847">"kunci laluan"</string> diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml index a66e7b67c85e..5af7b72a48a6 100644 --- a/packages/CredentialManager/res/values-my/strings.xml +++ b/packages/CredentialManager/res/values-my/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> သို့ လက်မှတ်ထိုးဝင်ရန် လျှို့ဝှက်ကီး ပြုလုပ်မလား။"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> သို့ လက်မှတ်ထိုးဝင်ရန် စကားဝှက်ကို သိမ်းမလား။"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် လက်မှတ်ထိုးဝင်ရန် အချက်အလက်ကို သိမ်းမလား။"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"လျှို့ဝှက်ကီး"</string> <string name="password" msgid="6738570945182936667">"စကားဝှက်"</string> <string name="passkeys" msgid="5733880786866559847">"လျှို့ဝှက်ကီးများ"</string> diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml index 7f4fa6ba8dfb..b6a679a49be6 100644 --- a/packages/CredentialManager/res/values-nb/strings.xml +++ b/packages/CredentialManager/res/values-nb/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Vil du opprette en passnøkkel for å logge på <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Vil du lagre passordet for å logge på <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vil du lagre påloggingsinformasjon for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"passnøkkel"</string> <string name="password" msgid="6738570945182936667">"passord"</string> <string name="passkeys" msgid="5733880786866559847">"passnøkler"</string> diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml index 6e6947626ff0..161a16d6dbc5 100644 --- a/packages/CredentialManager/res/values-ne/strings.xml +++ b/packages/CredentialManager/res/values-ne/strings.xml @@ -22,8 +22,8 @@ <string name="string_continue" msgid="1346732695941131882">"जारी राख्नुहोस्"</string> <string name="string_more_options" msgid="2763852250269945472">"अर्को तरिकाले सेभ गर्नुहोस्"</string> <string name="string_learn_more" msgid="4541600451688392447">"थप जान्नुहोस्"</string> - <string name="content_description_show_password" msgid="3283502010388521607">"पासवर्ड देखाइयोस्"</string> - <string name="content_description_hide_password" msgid="6841375971631767996">"पासवर्ड लुकाइयोस्"</string> + <string name="content_description_show_password" msgid="3283502010388521607">"पासवर्ड देखाउनुहोस्"</string> + <string name="content_description_hide_password" msgid="6841375971631767996">"पासवर्ड लुकाउनुहोस्"</string> <string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकीका सहायताले सुरक्षित रहनुहोस्"</string> <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"तपाईंले पासकी बनाउनुभयो भने तपाईंले जटिल पासवर्ड बनाउनु वा तिनलाई याद गरिराख्नु पर्दैन"</string> <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी भनेको तपाईंले आफ्नो फिंगरप्रिन्ट, अनुहार वा स्क्रिन लक प्रयोग गरेर बनाएको इन्क्रिप्ट गरिएको डिजिटल की हो"</string> @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न पासकी बनाउने हो?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न पासवर्ड सेभ गर्ने हो?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन गर्न प्रयोग गरिने जानकारी सेभ गर्ने हो?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा पासकी बनाउन आफ्नो स्क्रिन लक प्रयोग गर्ने हो?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा पासवर्ड राख्न आफ्नो स्क्रिन लक प्रयोग गर्ने हो?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इनसम्बन्धी जानकारी सेभ गर्न आफ्नो स्क्रिन लक प्रयोग गर्ने हो?"</string> <string name="passkey" msgid="632353688396759522">"पासकी"</string> <string name="password" msgid="6738570945182936667">"पासवर्ड"</string> <string name="passkeys" msgid="5733880786866559847">"पासकीहरू"</string> diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml index 50eefc7e5e9b..06ebc08d9725 100644 --- a/packages/CredentialManager/res/values-nl/strings.xml +++ b/packages/CredentialManager/res/values-nl/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Toegangssleutel maken om in te loggen bij <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Wachtwoord opslaan om in te loggen bij <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Inloggegevens opslaan voor <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"Toegangssleutel"</string> <string name="password" msgid="6738570945182936667">"wachtwoord"</string> <string name="passkeys" msgid="5733880786866559847">"toegangssleutels"</string> @@ -82,7 +88,7 @@ <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Op een andere manier inloggen"</string> <string name="snackbar_action" msgid="37373514216505085">"Opties bekijken"</string> <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Doorgaan"</string> - <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opties voor inloggen"</string> + <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Inlogopties"</string> <string name="button_label_view_more" msgid="3429098227286495651">"Meer bekijken"</string> <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Voor <xliff:g id="USERNAME">%1$s</xliff:g>"</string> <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vergrendelde wachtwoordmanagers"</string> @@ -93,6 +99,6 @@ <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via een ander apparaat"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Een ander apparaat gebruiken"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"Verzoek geannuleerd door <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Opties voor inloggen"</string> + <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Inlogopties"</string> <string name="more_options_content_description" msgid="1323427365788198808">"Meer"</string> </resources> diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml index 56e585d015bd..9781c49d945c 100644 --- a/packages/CredentialManager/res/values-or/strings.xml +++ b/packages/CredentialManager/res/values-or/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g>ରେ ସାଇନ ଇନ କରିବାକୁ ପାସକୀ ତିଆରି କରିବେ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g>ରେ ସାଇନ ଇନ କରିବାକୁ ପାସୱାର୍ଡ ସେଭ କରିବେ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସାଇନ-ଇନର ସୂଚନା ସେଭ କରିବେ?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଏକ ପାସକୀ ତିଆରି କରିବାକୁ ଆପଣଙ୍କ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରିବେ?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଏକ ପାସୱାର୍ଡ ତିଆରି କରିବାକୁ ଆପଣଙ୍କ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରିବେ?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସାଇନ ଇନ ସୂଚନା ସେଭ କରିବାକୁ ଆପଣଙ୍କ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରିବେ?"</string> <string name="passkey" msgid="632353688396759522">"ପାସକୀ"</string> <string name="password" msgid="6738570945182936667">"ପାସୱାର୍ଡ"</string> <string name="passkeys" msgid="5733880786866559847">"ପାସକୀଗୁଡ଼ିକ"</string> diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml index d23d20956b11..4cf8e17172c0 100644 --- a/packages/CredentialManager/res/values-pa/strings.xml +++ b/packages/CredentialManager/res/values-pa/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਨ ਲਈ ਪਾਸਕੀ ਬਣਾਉਣੀ ਹੈ?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਰੱਖਿਅਤ ਕਰਨੀ ਹੈ?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"ਪਾਸਕੀ"</string> <string name="password" msgid="6738570945182936667">"ਪਾਸਵਰਡ"</string> <string name="passkeys" msgid="5733880786866559847">"ਪਾਸਕੀਆਂ"</string> diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml index 5fa26b49a9e6..eca8699d0a55 100644 --- a/packages/CredentialManager/res/values-pl/strings.xml +++ b/packages/CredentialManager/res/values-pl/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Utworzyć klucz dostępu do logowania w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Zapisać hasło do logowania w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Zapisać dane używane do logowania w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Użyć metody odblokowania ekranu do utworzenia klucza dostępu do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Użyć metody odblokowania ekranu do utworzenia hasła do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Użyć metody odblokowania ekranu do zapisania danych logowania do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"klucz"</string> <string name="password" msgid="6738570945182936667">"hasło"</string> <string name="passkeys" msgid="5733880786866559847">"klucze dostępu"</string> diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml index 994bc553102d..e49387143fef 100644 --- a/packages/CredentialManager/res/values-pt-rBR/strings.xml +++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Criar chave de acesso para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Salvar senha para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Salvar informações de login do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"chave de acesso"</string> <string name="password" msgid="6738570945182936667">"senha"</string> <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string> diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml index 26c6491ad591..8b6b2b2e6450 100644 --- a/packages/CredentialManager/res/values-pt-rPT/strings.xml +++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Criar a chave de acesso para iniciar sessão na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Guardar a palavra-passe para iniciar sessão na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Guardar as informações de início de sessão da app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Usar o bloqueio de ecrã para criar uma chave de acesso para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Usar o bloqueio de ecrã para criar uma palavra-passe para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Usar o bloqueio de ecrã para guardar as informações de início de sessão para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"chave de acesso"</string> <string name="password" msgid="6738570945182936667">"palavra-passe"</string> <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string> diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml index 994bc553102d..e49387143fef 100644 --- a/packages/CredentialManager/res/values-pt/strings.xml +++ b/packages/CredentialManager/res/values-pt/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Criar chave de acesso para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Salvar senha para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Salvar informações de login do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"chave de acesso"</string> <string name="password" msgid="6738570945182936667">"senha"</string> <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string> diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml index 342b6ab77e8b..87b551b62f22 100644 --- a/packages/CredentialManager/res/values-ro/strings.xml +++ b/packages/CredentialManager/res/values-ro/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Creezi o cheie de acces pentru a te conecta la <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Salvezi parola pentru a te conecta la <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Salvezi informațiile de conectare pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"cheia de acces"</string> <string name="password" msgid="6738570945182936667">"parolă"</string> <string name="passkeys" msgid="5733880786866559847">"cheile de acces"</string> @@ -89,7 +95,7 @@ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Atinge pentru a debloca"</string> <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Fără informații de conectare"</string> <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nu există informații de conectare în contul <xliff:g id="SOURCE">%1$s</xliff:g>"</string> - <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionează acreditările"</string> + <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionează conectările"</string> <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De pe alt dispozitiv"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Folosește alt dispozitiv"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"Solicitare anulată de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml index e4726957d650..c9c8dcccfbf0 100644 --- a/packages/CredentialManager/res/values-ru/strings.xml +++ b/packages/CredentialManager/res/values-ru/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Создать ключ доступа для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Сохранить пароль для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Сохранить данные для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Использовать способ разблокировки экрана, чтобы создать ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Использовать способ разблокировки экрана, чтобы создать пароль для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Использовать способ разблокировки экрана, чтобы сохранить данные для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="passkey" msgid="632353688396759522">"ключ доступа"</string> <string name="password" msgid="6738570945182936667">"пароль"</string> <string name="passkeys" msgid="5733880786866559847">"ключи доступа"</string> diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml index ce0b9cd048eb..ab78c062bba1 100644 --- a/packages/CredentialManager/res/values-si/strings.xml +++ b/packages/CredentialManager/res/values-si/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> වෙත පුරනය වීමට මුරයතුරක් තනන්න ද?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> වෙත පුරනය වීමට මුරපදය සුරකින්න ද?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා පුරනය වීමේ තතු සුරකින්න ද?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"මුරයතුර"</string> <string name="password" msgid="6738570945182936667">"මුරපදය"</string> <string name="passkeys" msgid="5733880786866559847">"මුරයතුරු"</string> diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml index 62a2e690edae..c2626eaebeca 100644 --- a/packages/CredentialManager/res/values-sk/strings.xml +++ b/packages/CredentialManager/res/values-sk/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Chcete vytvoriť prístupový kľúč na prihlasovanie do aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Chcete uložiť heslo na prihlasovanie do aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Chcete uložiť prihlasovacie údaje pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Chcete pomocou zámky obrazovky vytvoriť prístupový kľúč pre <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Chcete pomocou zámky obrazovky vytvoriť heslo pre <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Chcete pomocou zámky obrazovky uložiť prihlasovacie údaje pre <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"prístupový kľúč"</string> <string name="password" msgid="6738570945182936667">"heslo"</string> <string name="passkeys" msgid="5733880786866559847">"prístupové kľúče"</string> diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml index d2aaf685032a..79c8c72d2f94 100644 --- a/packages/CredentialManager/res/values-sl/strings.xml +++ b/packages/CredentialManager/res/values-sl/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Želite ustvariti ključ za dostop za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Želite shraniti geslo za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Želite shraniti podatke za prijavo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Želite uporabiti zaklepanje zaslona za ustvarjanje ključa za dostop za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Želite uporabiti zaklepanje zaslona za ustvarjanje gesla za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Želite uporabiti zaklepanje zaslona za shranjevanje podatkov za prijavo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"ključ za dostop"</string> <string name="password" msgid="6738570945182936667">"geslo"</string> <string name="passkeys" msgid="5733880786866559847">"ključi za dostop"</string> diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml index f31d16aabe1e..8038cea71aed 100644 --- a/packages/CredentialManager/res/values-sq/strings.xml +++ b/packages/CredentialManager/res/values-sq/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Të krijohet një çelës kalimi për t\'u identifikuar në <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Të ruhet fjalëkalimi për t\'u identifikuar në <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Të ruhen informacionet e identifikimit për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"çelësin e kalimit"</string> <string name="password" msgid="6738570945182936667">"fjalëkalimi"</string> <string name="passkeys" msgid="5733880786866559847">"çelësat e kalimit"</string> @@ -89,7 +95,7 @@ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trokit për të shkyçur"</string> <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nuk ka informacione për identifikimin"</string> <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nuk ka informacione regjistrimi në <xliff:g id="SOURCE">%1$s</xliff:g>"</string> - <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Identifikimet e menaxhimit"</string> + <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Menaxho identifikimet"</string> <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Nga një pajisje tjetër"</string> <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Përdor një pajisje tjetër"</string> <string name="request_cancelled_by" msgid="3735222326886267820">"Kërkesa u anulua nga <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml index e68a20cc4f3b..58110aacdc36 100644 --- a/packages/CredentialManager/res/values-sr/strings.xml +++ b/packages/CredentialManager/res/values-sr/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Желите да направите приступни кључ да бисте се пријавили у <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Желите да сачувате лозинку да бисте се пријавили у <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Желите да сачувате податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Желите да користите откључавање екрана да бисте направили приступни кључ за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Желите да користите откључавање екрана да бисте направили лозинку за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Желите да користите откључавање екрана да бисте сачували податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"приступни кôд"</string> <string name="password" msgid="6738570945182936667">"лозинка"</string> <string name="passkeys" msgid="5733880786866559847">"приступни кодови"</string> diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml index e18fea1049ea..6379df248b8d 100644 --- a/packages/CredentialManager/res/values-sv/strings.xml +++ b/packages/CredentialManager/res/values-sv/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Vill du skapa en nyckel för att logga in i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Vill du spara lösenordet för att logga in i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vill du spara inloggningsuppgifterna för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"nyckel"</string> <string name="password" msgid="6738570945182936667">"lösenord"</string> <string name="passkeys" msgid="5733880786866559847">"nycklar"</string> diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml index 65672d5696ef..888b01c7550c 100644 --- a/packages/CredentialManager/res/values-sw/strings.xml +++ b/packages/CredentialManager/res/values-sw/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Ungependa kubuni ufunguo wa siri wa kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Ungependa kuhifadhi nenosiri la kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Ungependa kuhifadhi maelezo ya kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Ungependa kutumia mbinu yako ya kufunga skrini kubuni ufunguo wa siri wa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Ungependa kutumia mbinu yako ya kufunga skrini kubuni nenosiri la <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Ungependa kutumia mbinu yako ya kufunga skrini kuhifadhi maelezo ya kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"ufunguo wa siri"</string> <string name="password" msgid="6738570945182936667">"nenosiri"</string> <string name="passkeys" msgid="5733880786866559847">"funguo za siri"</string> diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml index 49d17101abb2..008baaba0ec9 100644 --- a/packages/CredentialManager/res/values-ta/strings.xml +++ b/packages/CredentialManager/res/values-ta/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸில் உள்நுழைய கடவுச்சாவியை உருவாக்கவா?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸில் உள்நுழைய கடவுச்சொல்லைச் சேமிக்கவா?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான உள்நுழைவுத் தகவலைச் சேமிக்கவா?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"கடவுச்சாவி"</string> <string name="password" msgid="6738570945182936667">"கடவுச்சொல்"</string> <string name="passkeys" msgid="5733880786866559847">"கடவுச்சாவிகள்"</string> diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml index 742a42279169..e2e362bb37aa 100644 --- a/packages/CredentialManager/res/values-te/strings.xml +++ b/packages/CredentialManager/res/values-te/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g>కు సైన్ ఇన్ చేయడానికి పాస్-కీని క్రియేట్ చేయాలా?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g>కు సైన్ ఇన్ చేయడానికి పాస్వర్డ్ను సేవ్ చేయాలా?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సైన్ ఇన్ సమాచారాన్ని సేవ్ చేయాలా?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"మీ స్క్రీన్ లాక్ను ఉపయోగించి <xliff:g id="APP_NAME">%1$s</xliff:g>కు పాస్-కీని క్రియేట్ చేయాలా?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"మీ స్క్రీన్ లాక్ను ఉపయోగించి <xliff:g id="APP_NAME">%1$s</xliff:g>కు పాస్వర్డ్ను క్రియేట్ చేయాలా?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"మీ స్క్రీన్ లాక్ను ఉపయోగించి <xliff:g id="APP_NAME">%1$s</xliff:g>కు సంబంధించిన సైన్-ఇన్ సమాచారాన్ని సేవ్ చేయాలా?"</string> <string name="passkey" msgid="632353688396759522">"పాస్-కీ"</string> <string name="password" msgid="6738570945182936667">"పాస్వర్డ్"</string> <string name="passkeys" msgid="5733880786866559847">"పాస్-కీలు"</string> diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml index 3f9de268ecf4..876371a9c7f5 100644 --- a/packages/CredentialManager/res/values-th/strings.xml +++ b/packages/CredentialManager/res/values-th/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"สร้างพาสคีย์เพื่อลงชื่อเข้าใช้ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"บันทึกรหัสผ่านเพื่อลงชื่อเข้าใช้ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"บันทึกข้อมูลการลงชื่อเข้าใช้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"ต้องการใช้ฟีเจอร์ล็อกหน้าจอเพื่อสร้างพาสคีย์สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"ต้องการใช้ฟีเจอร์ล็อกหน้าจอเพื่อสร้างรหัสผ่านสำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"ต้องการใช้ฟีเจอร์ล็อกหน้าจอเพื่อบันทึกข้อมูลการลงชื่อเข้าใช้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string> <string name="passkey" msgid="632353688396759522">"พาสคีย์"</string> <string name="password" msgid="6738570945182936667">"รหัสผ่าน"</string> <string name="passkeys" msgid="5733880786866559847">"พาสคีย์"</string> diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml index 659c1ec031b0..163e93aaf4f9 100644 --- a/packages/CredentialManager/res/values-tl/strings.xml +++ b/packages/CredentialManager/res/values-tl/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Gumawa ng passkey para mag-sign in sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"I-save ang password para mag-sign in sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"I-save ang impormasyon sa pag-sign in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"Gamitin ang iyong lock ng screen para gumawa ng passkey para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"Gamitin ang iyong lock ng screen para gumawa ng password para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"Gamitin ang iyong lock ng screen para mag-save ng impormasyon sa pag-sign in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="passkey" msgid="632353688396759522">"passkey"</string> <string name="password" msgid="6738570945182936667">"password"</string> <string name="passkeys" msgid="5733880786866559847">"mga passkey"</string> diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml index 5139a6789f7a..96a1c0083fa5 100644 --- a/packages/CredentialManager/res/values-tr/strings.xml +++ b/packages/CredentialManager/res/values-tr/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında oturum açmak için geçiş anahtarı oluşturulsun mu?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında oturum açmak için şifre kaydedilsin mi?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma bilgileri kaydedilsin mi?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"Geçiş anahtarı"</string> <string name="password" msgid="6738570945182936667">"Şifre"</string> <string name="passkeys" msgid="5733880786866559847">"Geçiş anahtarlarınızın"</string> diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml index 62eac9afc737..b867903855a5 100644 --- a/packages/CredentialManager/res/values-uk/strings.xml +++ b/packages/CredentialManager/res/values-uk/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Створити ключ доступу для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Зберегти пароль для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Зберегти дані для входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"ключ доступу"</string> <string name="password" msgid="6738570945182936667">"пароль"</string> <string name="passkeys" msgid="5733880786866559847">"ключі доступу"</string> diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml index 9fad27318f80..67cf20ae7ae2 100644 --- a/packages/CredentialManager/res/values-ur/strings.xml +++ b/packages/CredentialManager/res/values-ur/strings.xml @@ -42,6 +42,9 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> میں سائن ان کرنے کیلئے پاس کی تخلیق کریں؟"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> میں سائن ان کرنے کیلئے پاس ورڈ محفوظ کریں؟"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے سائن ان کی معلومات محفوظ کریں؟"</string> + <string name="choose_create_single_tap_passkey_title" msgid="3872793514041774218">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے پاس کی بنانے کے لیے اپنا اسکرین لاک استعمال کریں؟"</string> + <string name="choose_create_single_tap_password_title" msgid="5231871886818921622">"<xliff:g id="APP_NAME">%1$s</xliff:g> کا پاس ورڈ بنانے کے لیے اپنا اسکرین لاک استعمال کریں؟"</string> + <string name="choose_create_single_tap_sign_in_title" msgid="256498714574099587">"<xliff:g id="APP_NAME">%1$s</xliff:g> کی سائن ان کی معلومات محفوظ کرنے کے لیے اپنا اسکرین لاک استعمال کریں؟"</string> <string name="passkey" msgid="632353688396759522">"پاس کی"</string> <string name="password" msgid="6738570945182936667">"پاس ورڈ"</string> <string name="passkeys" msgid="5733880786866559847">"پاس کیز"</string> diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml index a3d20250a249..796bd87e76e6 100644 --- a/packages/CredentialManager/res/values-uz/strings.xml +++ b/packages/CredentialManager/res/values-uz/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga kirish uchun kirish kaliti yaratilsinmi?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga kirish uchun parol saqlansinmi?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun kirish maʼlumoti saqlansinmi?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"kalit"</string> <string name="password" msgid="6738570945182936667">"parol"</string> <string name="passkeys" msgid="5733880786866559847">"kalitlar"</string> diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml index da04efd82896..59bd541061b4 100644 --- a/packages/CredentialManager/res/values-vi/strings.xml +++ b/packages/CredentialManager/res/values-vi/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Tạo khoá truy cập để đăng nhập vào <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Lưu mật khẩu để đăng nhập vào <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Lưu thông tin đăng nhập cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"khoá đăng nhập"</string> <string name="password" msgid="6738570945182936667">"mật khẩu"</string> <string name="passkeys" msgid="5733880786866559847">"khoá truy cập"</string> @@ -82,7 +88,7 @@ <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Đăng nhập bằng cách khác"</string> <string name="snackbar_action" msgid="37373514216505085">"Xem các lựa chọn"</string> <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Tiếp tục"</string> - <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Tuỳ chọn đăng nhập"</string> + <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Lựa chọn đăng nhập"</string> <string name="button_label_view_more" msgid="3429098227286495651">"Xem thêm"</string> <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Cho <xliff:g id="USERNAME">%1$s</xliff:g>"</string> <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Trình quản lý mật khẩu đã khoá"</string> diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml index 968e978801d4..e9ac45a73088 100644 --- a/packages/CredentialManager/res/values-zh-rCN/strings.xml +++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"要创建通行密钥以便登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”吗?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"要保存密码以便登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”吗?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"要保存“<xliff:g id="APP_NAME">%1$s</xliff:g>”的登录信息吗?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"通行密钥"</string> <string name="password" msgid="6738570945182936667">"密码"</string> <string name="passkeys" msgid="5733880786866559847">"通行密钥"</string> diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml index 7a375c9c7aea..77855b51c7c4 100644 --- a/packages/CredentialManager/res/values-zh-rHK/strings.xml +++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"要建立密鑰以登入 <xliff:g id="APP_NAME">%1$s</xliff:g> 嗎?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"要儲存密碼以登入 <xliff:g id="APP_NAME">%1$s</xliff:g> 嗎?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"要儲存 <xliff:g id="APP_NAME">%1$s</xliff:g> 的登入資料嗎?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"密鑰"</string> <string name="password" msgid="6738570945182936667">"密碼"</string> <string name="passkeys" msgid="5733880786866559847">"密鑰"</string> diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml index 029908872a71..520d9a8049e7 100644 --- a/packages/CredentialManager/res/values-zh-rTW/strings.xml +++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"要建立用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼金鑰嗎?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"要儲存用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼嗎?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"要儲存「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入資訊嗎?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"密碼金鑰"</string> <string name="password" msgid="6738570945182936667">"密碼"</string> <string name="passkeys" msgid="5733880786866559847">"密碼金鑰"</string> diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml index 4f888f42b686..8cb25cb2ce9c 100644 --- a/packages/CredentialManager/res/values-zu/strings.xml +++ b/packages/CredentialManager/res/values-zu/strings.xml @@ -42,6 +42,12 @@ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Sungula ukhiye wokudlula ukuze ungene ngemvume ku-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_password_title" msgid="4481366993598649224">"Londoloza iphasiwedi ukuze ungene ngemvume ku-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Londoloza ulwazi lokungena lwe-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <!-- no translation found for choose_create_single_tap_passkey_title (3872793514041774218) --> + <skip /> + <!-- no translation found for choose_create_single_tap_password_title (5231871886818921622) --> + <skip /> + <!-- no translation found for choose_create_single_tap_sign_in_title (256498714574099587) --> + <skip /> <string name="passkey" msgid="632353688396759522">"ukhiye wokudlula"</string> <string name="password" msgid="6738570945182936667">"iphasiwedi"</string> <string name="passkeys" msgid="5733880786866559847">"okhiye bokudlula"</string> diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt index ab70394057f3..694e27af5682 100644 --- a/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt +++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt @@ -21,7 +21,6 @@ import android.content.Context import android.content.Intent import android.credentials.selection.BaseDialogResult import android.credentials.selection.BaseDialogResult.RESULT_CODE_DIALOG_USER_CANCELED -import android.credentials.selection.Constants import android.credentials.selection.ProviderPendingIntentResponse import android.credentials.selection.UserSelectionDialogResult import android.os.Bundle @@ -117,21 +116,17 @@ class CredentialManagerClientImpl @Inject constructor( sendCancellationCode( cancelCode = cancelCode, requestToken = token, - resultReceiver = resultReceiver, - finalResponseReceiver = finalResponseReceiver + resultReceiver = resultReceiver ) } private fun sendCancellationCode( cancelCode: Int, requestToken: IBinder?, - resultReceiver: ResultReceiver?, - finalResponseReceiver: ResultReceiver? + resultReceiver: ResultReceiver? ) { if (requestToken != null && resultReceiver != null) { - val resultData = Bundle().apply { - putParcelable(Constants.EXTRA_FINAL_RESPONSE_RECEIVER, finalResponseReceiver) - } + val resultData = Bundle() BaseDialogResult.addToBundle(BaseDialogResult(requestToken), resultData) resultReceiver.send(cancelCode, resultData) } diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt index b408c1553d94..9c8ec3b56813 100644 --- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt +++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt @@ -142,7 +142,7 @@ private fun getCredentialOptionInfoList( isDefaultIconPreferredAsSingleProvider = credentialEntry.isDefaultIconPreferredAsSingleProvider, affiliatedDomain = credentialEntry.affiliatedDomain?.toString(), - biometricRequest = predetermineAndValidateBiometricFlow(it, + biometricRequest = retrieveEntryBiometricRequest(it, CREDENTIAL_ENTRY_PREFIX), ) ) @@ -172,7 +172,7 @@ private fun getCredentialOptionInfoList( isDefaultIconPreferredAsSingleProvider = credentialEntry.isDefaultIconPreferredAsSingleProvider, affiliatedDomain = credentialEntry.affiliatedDomain?.toString(), - biometricRequest = predetermineAndValidateBiometricFlow(it, + biometricRequest = retrieveEntryBiometricRequest(it, CREDENTIAL_ENTRY_PREFIX), ) ) @@ -201,7 +201,7 @@ private fun getCredentialOptionInfoList( isDefaultIconPreferredAsSingleProvider = credentialEntry.isDefaultIconPreferredAsSingleProvider, affiliatedDomain = credentialEntry.affiliatedDomain?.toString(), - biometricRequest = predetermineAndValidateBiometricFlow(it, + biometricRequest = retrieveEntryBiometricRequest(it, CREDENTIAL_ENTRY_PREFIX), ) ) @@ -216,7 +216,7 @@ private fun getCredentialOptionInfoList( } /** - * This validates if this is a biometric flow or not, and if it is, this returns the expected + * This validates if the entry calling this method contains biometric info, and if so, returns a * [BiometricRequestInfo]. Namely, the biometric flow must have at least the * ALLOWED_AUTHENTICATORS bit passed from Jetpack. * Note that the required values, such as the provider info's icon or display name, or the entries @@ -230,7 +230,7 @@ private fun getCredentialOptionInfoList( * // TODO(b/326243754) : Presently, due to dependencies, the opId bit is parsed but is never * // expected to be used. When it is added, it should be lightly validated. */ -fun predetermineAndValidateBiometricFlow( +fun retrieveEntryBiometricRequest( entry: Entry, hintPrefix: String, ): BiometricRequestInfo? { diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt index 786c441bb2e3..9242141cfd63 100644 --- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt +++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt @@ -54,9 +54,3 @@ val Intent.resultReceiver: ResultReceiver? Constants.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java ) - -val Intent.finalResponseReceiver: ResultReceiver? - get() = this.getParcelableExtra( - Constants.EXTRA_FINAL_RESPONSE_RECEIVER, - ResultReceiver::class.java - ) diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt index 1683cc43eef1..f1f1f7ca842e 100644 --- a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt +++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt @@ -20,7 +20,6 @@ import android.content.Context import android.content.Intent import com.android.credentialmanager.ktx.getCredentialProviderDataList import com.android.credentialmanager.ktx.requestInfo -import com.android.credentialmanager.ktx.finalResponseReceiver import com.android.credentialmanager.ktx.resultReceiver import com.android.credentialmanager.ktx.toProviderList import com.android.credentialmanager.model.Request @@ -29,7 +28,6 @@ fun Intent.toGet(context: Context): Request.Get { return Request.Get( token = requestInfo?.token, resultReceiver = resultReceiver, - finalResponseReceiver = finalResponseReceiver, providerInfos = getCredentialProviderDataList.toProviderList(context) ) } diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt index fd99275ebc8e..cb335fc229b2 100644 --- a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt +++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt @@ -25,8 +25,7 @@ import com.android.credentialmanager.model.get.ProviderInfo */ sealed class Request private constructor( open val token: IBinder?, - open val resultReceiver: ResultReceiver? = null, - open val finalResponseReceiver: ResultReceiver? = null, + open val resultReceiver: ResultReceiver? = null ) { /** @@ -51,9 +50,8 @@ sealed class Request private constructor( data class Get( override val token: IBinder?, override val resultReceiver: ResultReceiver?, - override val finalResponseReceiver: ResultReceiver?, val providerInfos: List<ProviderInfo>, - ) : Request(token, resultReceiver, finalResponseReceiver) + ) : Request(token, resultReceiver) /** * Request to start the create credentials flow. */ diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt index b17a98b30eee..3683235ff049 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt @@ -58,7 +58,6 @@ class CredentialManagerRepo( private val providerEnabledList: List<ProviderData> private val providerDisabledList: List<DisabledProviderData>? val resultReceiver: ResultReceiver? - val finalResponseReceiver: ResultReceiver? var initialUiState: UiState @@ -105,12 +104,6 @@ class CredentialManagerRepo( Constants.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java ) - - finalResponseReceiver = intent.getParcelableExtra( - Constants.EXTRA_FINAL_RESPONSE_RECEIVER, - ResultReceiver::class.java - ) - isReqForAllOptions = requestInfo?.isShowAllOptionsRequested ?: false val cancellationRequest = getCancelUiRequest(intent) @@ -206,7 +199,7 @@ class CredentialManagerRepo( } fun onCancel(cancelCode: Int) { - sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver, finalResponseReceiver) + sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver) } fun onOptionSelected( @@ -226,9 +219,6 @@ class CredentialManagerRepo( val resultDataBundle = Bundle() UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultDataBundle) - resultDataBundle.putParcelable(Constants.EXTRA_FINAL_RESPONSE_RECEIVER, - finalResponseReceiver) - resultReceiver?.send( BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION, resultDataBundle @@ -296,13 +286,10 @@ class CredentialManagerRepo( fun sendCancellationCode( cancelCode: Int, requestToken: IBinder?, - resultReceiver: ResultReceiver?, - finalResponseReceiver: ResultReceiver? + resultReceiver: ResultReceiver? ) { if (requestToken != null && resultReceiver != null) { val resultData = Bundle() - resultData.putParcelable(Constants.EXTRA_FINAL_RESPONSE_RECEIVER, - finalResponseReceiver) BaseDialogResult.addToBundle(BaseDialogResult(requestToken), resultData) resultReceiver.send(cancelCode, resultData) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt index ec0da0986e45..a2f55cd50519 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt @@ -208,18 +208,13 @@ class CredentialSelectorActivity : ComponentActivity() { android.credentials.selection.Constants.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java ) - val finalResponseResultReceiver = intent.getParcelableExtra( - android.credentials.selection.Constants.EXTRA_FINAL_RESPONSE_RECEIVER, - ResultReceiver::class.java - ) - val requestInfo = intent.extras?.getParcelable( RequestInfo.EXTRA_REQUEST_INFO, RequestInfo::class.java ) CredentialManagerRepo.sendCancellationCode( BaseDialogResult.RESULT_CODE_DATA_PARSING_FAILURE, - requestInfo?.token, resultReceiver, finalResponseResultReceiver + requestInfo?.token, resultReceiver ) this.finish() } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt index a03975375e8a..429bdbf5959b 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt @@ -30,6 +30,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel +import com.android.credentialmanager.common.BiometricError +import com.android.credentialmanager.common.BiometricFlowType +import com.android.credentialmanager.common.BiometricPromptState import com.android.credentialmanager.common.BiometricResult import com.android.credentialmanager.common.BiometricState import com.android.credentialmanager.model.EntryInfo @@ -40,7 +43,7 @@ import com.android.credentialmanager.common.ProviderActivityState import com.android.credentialmanager.createflow.ActiveEntry import com.android.credentialmanager.createflow.CreateCredentialUiState import com.android.credentialmanager.createflow.CreateScreenState -import com.android.credentialmanager.createflow.findBiometricFlowEntry +import com.android.credentialmanager.createflow.isBiometricFlow import com.android.credentialmanager.getflow.GetCredentialUiState import com.android.credentialmanager.getflow.GetScreenState import com.android.credentialmanager.logging.LifecycleEvent @@ -126,13 +129,22 @@ class CredentialSelectorViewModel( uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING) val entryIntent = entry.fillInIntent entryIntent?.putExtra(Constants.IS_AUTO_SELECTED_KEY, uiState.isAutoSelectFlow) - if (biometricState.biometricResult != null) { + if (biometricState.biometricResult != null || biometricState.biometricError != null) { if (uiState.isAutoSelectFlow) { Log.w(Constants.LOG_TAG, "Unexpected biometric result exists when " + "autoSelect is preferred.") } - entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_TYPE, - biometricState.biometricResult.biometricAuthenticationResult.authenticationType) + // TODO(b/333445754) : Decide whether to propagate info on prompt launch + if (biometricState.biometricResult != null) { + entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_RESULT, + biometricState.biometricResult.biometricAuthenticationResult + .authenticationType) + } else if (biometricState.biometricError != null){ + entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_CODE, + biometricState.biometricError.errorCode) + entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_MESSAGE, + biometricState.biometricError.errorMessage) + } } val intentSenderRequest = IntentSenderRequest.Builder(pendingIntent) .setFillInIntent(entryIntent).build() @@ -217,7 +229,8 @@ class CredentialSelectorViewModel( /**************************************************************************/ fun getFlowOnEntrySelected( entry: EntryInfo, - authResult: BiometricPrompt.AuthenticationResult? = null + authResult: BiometricPrompt.AuthenticationResult? = null, + authError: BiometricError? = null, ) { Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" + ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}") @@ -225,10 +238,11 @@ class CredentialSelectorViewModel( uiState.copy( selectedEntry = entry, providerActivityState = ProviderActivityState.READY_TO_LAUNCH, - biometricState = if (authResult == null) uiState.biometricState else uiState + biometricState = if (authResult == null && authError == null) + uiState.biometricState else if (authResult != null) uiState .biometricState.copy(biometricResult = BiometricResult( - biometricAuthenticationResult = authResult) - ) + biometricAuthenticationResult = authResult)) else uiState + .biometricState.copy(biometricError = authError) ) } else { credManRepo.onOptionSelected(entry.providerId, entry.entryKey, entry.entrySubkey) @@ -256,6 +270,15 @@ class CredentialSelectorViewModel( ) } + fun getFlowOnMoreOptionOnlySelected() { + Log.d(Constants.LOG_TAG, "More Option Only selected") + uiState = uiState.copy( + getCredentialUiState = uiState.getCredentialUiState?.copy( + currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY + ) + ) + } + fun getFlowOnMoreOptionOnSnackBarSelected(isNoAccount: Boolean) { Log.d(Constants.LOG_TAG, "More Option on snackBar selected") uiState = uiState.copy( @@ -303,13 +326,23 @@ class CredentialSelectorViewModel( } fun createFlowOnEntrySelectedFromMoreOptionScreen(activeEntry: ActiveEntry) { + val isBiometricFlow = isBiometricFlow(activeEntry = activeEntry, isAutoSelectFlow = false) + if (isBiometricFlow) { + // This atomically ensures that the only edge case that *restarts* the biometric flow + // doesn't risk a configuration change bug on the more options page during create. + // Namely, it's atomic in that it happens only on a tap, and it is not possible to + // reproduce a tap and a rotation at the same time. However, even if it were, it would + // just be an alternate way to jump back into the biometric selection flow after this + // reset, and thus, the state machine is maintained. + onBiometricPromptStateChange(BiometricPromptState.INACTIVE) + } uiState = uiState.copy( createCredentialUiState = uiState.createCredentialUiState?.copy( currentScreenState = // An autoselect flow never makes it to the more options screen - if (findBiometricFlowEntry(activeEntry = activeEntry, - isAutoSelectFlow = false) != null) CreateScreenState.BIOMETRIC_SELECTION - else if ( + if (isBiometricFlow) { + CreateScreenState.BIOMETRIC_SELECTION + } else if ( uiState.createCredentialUiState?.requestDisplayInfo?.userSetDefaultProviderIds ?.contains(activeEntry.activeProvider.id) ?: true || !(uiState.createCredentialUiState?.foundCandidateFromUserDefaultProvider @@ -338,7 +371,8 @@ class CredentialSelectorViewModel( fun createFlowOnEntrySelected( selectedEntry: EntryInfo, - authResult: AuthenticationResult? = null + authResult: AuthenticationResult? = null, + authError: BiometricError? = null, ) { val providerId = selectedEntry.providerId val entryKey = selectedEntry.entryKey @@ -350,9 +384,11 @@ class CredentialSelectorViewModel( uiState = uiState.copy( selectedEntry = selectedEntry, providerActivityState = ProviderActivityState.READY_TO_LAUNCH, - biometricState = if (authResult == null) uiState.biometricState else uiState + biometricState = if (authResult == null && authError == null) + uiState.biometricState else if (authResult != null) uiState .biometricState.copy(biometricResult = BiometricResult( - biometricAuthenticationResult = authResult)) + biometricAuthenticationResult = authResult)) else uiState + .biometricState.copy(biometricError = authError) ) } else { credManRepo.onOptionSelected( @@ -375,6 +411,46 @@ class CredentialSelectorViewModel( } } + /**************************************************************************/ + /***** Biometric Flow Callbacks *****/ + /**************************************************************************/ + + /** + * This allows falling back from the biometric prompt screen to the normal get flow by applying + * a reset to all necessary states involved in the fallback. + */ + fun fallbackFromBiometricToNormalFlow(biometricFlowType: BiometricFlowType) { + onBiometricPromptStateChange(BiometricPromptState.INACTIVE) + when (biometricFlowType) { + BiometricFlowType.GET -> getFlowOnBackToPrimarySelectionScreen() + BiometricFlowType.CREATE -> createFlowOnUseOnceSelected() + } + } + + /** + * This method can be used to change the [BiometricPromptState] according to the necessity. + * For example, if resetting, one might use [BiometricPromptState.INACTIVE], but if the flow + * has just launched, to avoid configuration errors, one can use + * [BiometricPromptState.PENDING]. + */ + fun onBiometricPromptStateChange(biometricPromptState: BiometricPromptState) { + uiState = uiState.copy( + biometricState = uiState.biometricState.copy( + biometricStatus = biometricPromptState + ) + ) + } + + /** + * This returns the present biometric state. + */ + fun getBiometricPromptState(): BiometricPromptState = + uiState.biometricState.biometricStatus + + /**************************************************************************/ + /***** Misc. Callbacks/Logs *****/ + /**************************************************************************/ + @Composable fun logUiEvent(uiEventEnum: UiEventEnum) { this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo?.packageName) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt index 358ebfa1ec90..c477f30a1d2f 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt @@ -53,8 +53,9 @@ import androidx.credentials.provider.RemoteEntry import org.json.JSONObject import android.credentials.flags.Flags import com.android.credentialmanager.createflow.isBiometricFlow +import com.android.credentialmanager.createflow.isFlowAutoSelectable import com.android.credentialmanager.getflow.TopBrandingContent -import com.android.credentialmanager.ktx.predetermineAndValidateBiometricFlow +import com.android.credentialmanager.ktx.retrieveEntryBiometricRequest import java.time.Instant fun getAppLabel( @@ -431,7 +432,12 @@ class CreateFlowUtils { remoteEntryProvider = remoteEntryProvider, ) val isBiometricFlow = if (activeEntry == null) false else isBiometricFlow(activeEntry, - sortedCreateOptionsPairs, requestDisplayInfo) + isFlowAutoSelectable( + requestDisplayInfo = requestDisplayInfo, + activeEntry = activeEntry, + sortedCreateOptionsPairs = sortedCreateOptionsPairs + ) + ) val initialScreenState = toCreateScreenState( createOptionSize = createOptionsPairs.size, remoteEntry = remoteEntry, @@ -514,7 +520,7 @@ class CreateFlowUtils { it.hasHint("androidx.credentials.provider.createEntry.SLICE_HINT_AUTO_" + "SELECT_ALLOWED") }?.text == "true", - biometricRequest = predetermineAndValidateBiometricFlow(it, + biometricRequest = retrieveEntryBiometricRequest(it, CREATE_ENTRY_PREFIX), ) ) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt index 1253ce3a6c80..4109079e20a5 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt @@ -32,6 +32,7 @@ import android.graphics.drawable.Icon import android.os.Bundle import android.os.CancellationSignal import android.os.OutcomeReceiver +import android.os.ResultReceiver import android.service.autofill.AutofillService import android.service.autofill.Dataset import android.service.autofill.Field @@ -109,17 +110,19 @@ class CredentialAutofillService : AutofillService() { } val sessionId = clientState.getInt(SESSION_ID_KEY) val requestId = clientState.getInt(REQUEST_ID_KEY) + val resultReceiver = clientState.getParcelable( + CredentialManager.EXTRA_AUTOFILL_RESULT_RECEIVER, ResultReceiver::class.java) Log.i(TAG, "Autofill sessionId: $sessionId, autofill requestId: $requestId") - if (sessionId == 0 || requestId == 0) { - Log.i(TAG, "Session Id or request Id not found") - callback.onFailure("Session Id or request Id not found") + if (sessionId == 0 || requestId == 0 || resultReceiver == null) { + Log.i(TAG, "Session Id or request Id or resultReceiver not found") + callback.onFailure("Session Id or request Id or resultReceiver not found") return } val responseClientState = Bundle() responseClientState.putBoolean(WEBVIEW_REQUESTED_CREDENTIAL_KEY, false) val getCredRequest: GetCredentialRequest? = getCredManRequest(structure, sessionId, - requestId, responseClientState) + requestId, resultReceiver, responseClientState) // TODO(b/324635774): Use callback for validating. If the request is coming // directly from the view, there should be a corresponding callback, otherwise // we should fail fast, @@ -531,6 +534,7 @@ class CredentialAutofillService : AutofillService() { structure: AssistStructure, sessionId: Int, requestId: Int, + resultReceiver: ResultReceiver, responseClientState: Bundle ): GetCredentialRequest? { val credentialOptions: MutableList<CredentialOption> = mutableListOf() @@ -540,6 +544,9 @@ class CredentialAutofillService : AutofillService() { val dataBundle = Bundle() dataBundle.putInt(SESSION_ID_KEY, sessionId) dataBundle.putInt(REQUEST_ID_KEY, requestId) + dataBundle.putParcelable(CredentialManager.EXTRA_AUTOFILL_RESULT_RECEIVER, + resultReceiver) + return GetCredentialRequest.Builder(dataBundle) .setCredentialOptions(credentialOptions) .build() diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/FlowType.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricFlowType.kt index f6140f51b7b5..263cfd574d73 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/common/FlowType.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricFlowType.kt @@ -16,7 +16,7 @@ package com.android.credentialmanager.common -enum class FlowType { +enum class BiometricFlowType { GET, CREATE }
\ No newline at end of file diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt index fa177351be30..aa721c9f6e13 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt @@ -20,6 +20,7 @@ import android.content.Context import android.graphics.Bitmap import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.BiometricPrompt +import android.hardware.biometrics.CryptoObject import android.os.CancellationSignal import android.util.Log import androidx.core.content.ContextCompat.getMainExecutor @@ -59,7 +60,7 @@ import java.lang.Exception * ). * * The above are examples; the credential type can change depending on scenario. - * // TODO(b/326243891) : Finalize once all the strings and create flow is iterated to completion + * // TODO(b/333445112) : Finalize once all the strings and create flow is iterated to completion */ data class BiometricDisplayInfo( val providerIcon: Bitmap, @@ -75,7 +76,9 @@ data class BiometricDisplayInfo( * additional states that may improve the flow. */ data class BiometricState( - val biometricResult: BiometricResult? = null + val biometricResult: BiometricResult? = null, + val biometricError: BiometricError? = null, + val biometricStatus: BiometricPromptState = BiometricPromptState.INACTIVE ) /** @@ -91,7 +94,7 @@ data class BiometricResult( */ data class BiometricError( val errorCode: Int, - val errString: CharSequence? = null + val errorMessage: CharSequence? = null ) /** @@ -104,88 +107,157 @@ data class BiometricHelp( ) /** - * This will handle the logic for integrating credential manager with the biometric prompt for the - * single account biometric experience. This simultaneously handles both the get and create flows, - * by retrieving all the data from credential manager, and properly parsing that data into the - * biometric prompt. + * This is the entry point to start the integrated biometric prompt for 'get' flows. It captures + * information specific to the get flow, along with required shared callbacks and more general + * info across both flows, such as the tapped [EntryInfo] or [sendDataToProvider]. */ -fun runBiometricFlow( +fun runBiometricFlowForGet( biometricEntry: EntryInfo, context: Context, openMoreOptionsPage: () -> Unit, - sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult) -> Unit, + sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult?, BiometricError?) -> Unit, onCancelFlowAndFinish: () -> Unit, onIllegalStateAndFinish: (String) -> Unit, + getBiometricPromptState: () -> BiometricPromptState, + onBiometricPromptStateChange: (BiometricPromptState) -> Unit, + onBiometricFailureFallback: (BiometricFlowType) -> Unit, getRequestDisplayInfo: RequestDisplayInfo? = null, getProviderInfoList: List<ProviderInfo>? = null, getProviderDisplayInfo: ProviderDisplayInfo? = null, - onBiometricFailureFallback: () -> Unit, +) { + if (getBiometricPromptState() != BiometricPromptState.INACTIVE) { + // Screen is already up, do not re-launch + return + } + onBiometricPromptStateChange(BiometricPromptState.PENDING) + val biometricDisplayInfo = validateAndRetrieveBiometricGetDisplayInfo( + getRequestDisplayInfo, + getProviderInfoList, + getProviderDisplayInfo, + context, biometricEntry + ) + + if (biometricDisplayInfo == null) { + onBiometricFailureFallback(BiometricFlowType.GET) + return + } + + val callback: BiometricPrompt.AuthenticationCallback = + setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry, + onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange) + + Log.d(TAG, "The BiometricPrompt API call begins.") + runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage, + onBiometricFailureFallback, BiometricFlowType.GET) +} + +/** + * This is the entry point to start the integrated biometric prompt for 'create' flows. It captures + * information specific to the create flow, along with required shared callbacks and more general + * info across both flows, such as the tapped [EntryInfo] or [sendDataToProvider]. + */ +fun runBiometricFlowForCreate( + biometricEntry: EntryInfo, + context: Context, + openMoreOptionsPage: () -> Unit, + sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult?, BiometricError?) -> Unit, + onCancelFlowAndFinish: () -> Unit, + onIllegalStateAndFinish: (String) -> Unit, + getBiometricPromptState: () -> BiometricPromptState, + onBiometricPromptStateChange: (BiometricPromptState) -> Unit, + onBiometricFailureFallback: (BiometricFlowType) -> Unit, createRequestDisplayInfo: com.android.credentialmanager.createflow .RequestDisplayInfo? = null, createProviderInfo: EnabledProviderInfo? = null, ) { - // TODO(b/330396089) : Add rotation configuration fix with state machine - var biometricDisplayInfo: BiometricDisplayInfo? = null - var flowType = FlowType.GET - if (getRequestDisplayInfo != null) { - biometricDisplayInfo = validateAndRetrieveBiometricGetDisplayInfo(getRequestDisplayInfo, - getProviderInfoList, - getProviderDisplayInfo, - context, biometricEntry) - } else if (createRequestDisplayInfo != null) { - flowType = FlowType.CREATE - biometricDisplayInfo = validateAndRetrieveBiometricCreateDisplayInfo( - createRequestDisplayInfo, - createProviderInfo, - context, biometricEntry) + if (getBiometricPromptState() != BiometricPromptState.INACTIVE) { + // Screen is already up, do not re-launch + return } + onBiometricPromptStateChange(BiometricPromptState.PENDING) + val biometricDisplayInfo = validateAndRetrieveBiometricCreateDisplayInfo( + createRequestDisplayInfo, + createProviderInfo, + context, biometricEntry + ) if (biometricDisplayInfo == null) { - onBiometricFailureFallback() + onBiometricFailureFallback(BiometricFlowType.CREATE) return } - val biometricPrompt = setupBiometricPrompt(context, biometricDisplayInfo, openMoreOptionsPage, - biometricDisplayInfo.biometricRequestInfo.allowedAuthenticators, flowType) - val callback: BiometricPrompt.AuthenticationCallback = setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry, - onCancelFlowAndFinish, onIllegalStateAndFinish) + onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange) + + Log.d(TAG, "The BiometricPrompt API call begins.") + runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage, + onBiometricFailureFallback, BiometricFlowType.CREATE) +} + +/** + * This will handle the logic for integrating credential manager with the biometric prompt for the + * single account biometric experience. This simultaneously handles both the get and create flows, + * by retrieving all the data from credential manager, and properly parsing that data into the + * biometric prompt. + */ +private fun runBiometricFlow( + context: Context, + biometricDisplayInfo: BiometricDisplayInfo, + callback: BiometricPrompt.AuthenticationCallback, + openMoreOptionsPage: () -> Unit, + onBiometricFailureFallback: (BiometricFlowType) -> Unit, + biometricFlowType: BiometricFlowType +) { + val biometricPrompt = setupBiometricPrompt(context, biometricDisplayInfo, openMoreOptionsPage, + biometricDisplayInfo.biometricRequestInfo, biometricFlowType) val cancellationSignal = CancellationSignal() cancellationSignal.setOnCancelListener { Log.d(TAG, "Your cancellation signal was called.") - // TODO(b/326243754) : Migrate towards passing along the developer cancellation signal + // TODO(b/333445112) : Migrate towards passing along the developer cancellation signal // or validate the necessity for this } val executor = getMainExecutor(context) try { - biometricPrompt.authenticate(cancellationSignal, executor, callback) + val cryptoOpId = getCryptoOpId(biometricDisplayInfo) + if (cryptoOpId != null) { + biometricPrompt.authenticate( + BiometricPrompt.CryptoObject(cryptoOpId.toLong()), + cancellationSignal, executor, callback) + } else { + biometricPrompt.authenticate(cancellationSignal, executor, callback) + } } catch (e: IllegalArgumentException) { Log.w(TAG, "Calling the biometric prompt API failed with: /n${e.localizedMessage}\n") - onBiometricFailureFallback() + onBiometricFailureFallback(biometricFlowType) } } +private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Int? { + return biometricDisplayInfo.biometricRequestInfo.opId +} + /** * Sets up the biometric prompt with the UI specific bits. - * // TODO(b/326243754) : Pass in opId once dependency is confirmed via CryptoObject + * // TODO(b/333445112) : Pass in opId once dependency is confirmed via CryptoObject */ private fun setupBiometricPrompt( context: Context, biometricDisplayInfo: BiometricDisplayInfo, openMoreOptionsPage: () -> Unit, - requestAllowedAuthenticators: Int, - flowType: FlowType, + biometricRequestInfo: BiometricRequestInfo, + biometricFlowType: BiometricFlowType, ): BiometricPrompt { - val finalAuthenticators = removeDeviceCredential(requestAllowedAuthenticators) + val finalAuthenticators = removeDeviceCredential(biometricRequestInfo.allowedAuthenticators) val biometricPrompt = BiometricPrompt.Builder(context) .setTitle(biometricDisplayInfo.displayTitleText) - // TODO(b/326243754) : Migrate to using new methods recently aligned upon - .setNegativeButton(context.getString(if (flowType == FlowType.GET) R.string + // TODO(b/333445112) : Migrate to using new methods and strings recently aligned upon + .setNegativeButton(context.getString(if (biometricFlowType == BiometricFlowType.GET) + R.string .dropdown_presentation_more_sign_in_options_text else R.string.string_more_options), getMainExecutor(context)) { _, _ -> openMoreOptionsPage() @@ -200,7 +272,7 @@ private fun setupBiometricPrompt( return biometricPrompt } -// TODO(b/326243754) : Remove after larger level alignments made on fallback negative button +// TODO(b/333445112) : Remove after larger level alignments made on fallback negative button // For the time being, we do not support the pin fallback until UX is decided. private fun removeDeviceCredential(requestAllowedAuthenticators: Int): Int { var finalAuthenticators = requestAllowedAuthenticators @@ -226,21 +298,23 @@ private fun removeDeviceCredential(requestAllowedAuthenticators: Int): Int { * Sets up the biometric authentication callback. */ private fun setupBiometricAuthenticationCallback( - sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult) -> Unit, + sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult?, BiometricError?) -> Unit, selectedEntry: EntryInfo, onCancelFlowAndFinish: () -> Unit, onIllegalStateAndFinish: (String) -> Unit, + onBiometricPromptStateChange: (BiometricPromptState) -> Unit ): BiometricPrompt.AuthenticationCallback { val callback: BiometricPrompt.AuthenticationCallback = object : BiometricPrompt.AuthenticationCallback() { - // TODO(b/326243754) : Validate remaining callbacks + // TODO(b/333445772) : Validate remaining callbacks override fun onAuthenticationSucceeded( authResult: BiometricPrompt.AuthenticationResult? ) { super.onAuthenticationSucceeded(authResult) try { if (authResult != null) { - sendDataToProvider(selectedEntry, authResult) + onBiometricPromptStateChange(BiometricPromptState.COMPLETE) + sendDataToProvider(selectedEntry, authResult, /*authError=*/null) } else { onIllegalStateAndFinish("The biometric flow succeeded but unexpectedly " + "returned a null value.") @@ -254,26 +328,26 @@ private fun setupBiometricAuthenticationCallback( override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence?) { super.onAuthenticationHelp(helpCode, helpString) Log.d(TAG, "Authentication help discovered: $helpCode and $helpString") - // TODO(b/326243754) : Decide on strategy with provider (a simple log probably - // suffices here) } override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) { super.onAuthenticationError(errorCode, errString) Log.d(TAG, "Authentication error-ed out: $errorCode and $errString") + onBiometricPromptStateChange(BiometricPromptState.COMPLETE) if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED) { // Note that because the biometric prompt is imbued directly // into the selector, parity applies to the selector's cancellation instead // of the provider's biometric prompt cancellation. onCancelFlowAndFinish() + } else { + sendDataToProvider(selectedEntry, /*authResult=*/null, /*authError=*/ + BiometricError(errorCode, errString)) } - // TODO(b/326243754) : Propagate to provider } override fun onAuthenticationFailed() { super.onAuthenticationFailed() Log.d(TAG, "Authentication failed.") - // TODO(b/326243754) : Propagate to provider } } return callback @@ -299,7 +373,7 @@ private fun validateAndRetrieveBiometricGetDisplayInfo( if (getRequestDisplayInfo != null && getProviderInfoList != null && getProviderDisplayInfo != null) { if (selectedEntry !is CredentialEntryInfo) { return null } - return getBiometricDisplayValues(getProviderInfoList, + return retrieveBiometricGetDisplayValues(getProviderInfoList, context, getRequestDisplayInfo, selectedEntry) } return null @@ -308,7 +382,8 @@ private fun validateAndRetrieveBiometricGetDisplayInfo( /** * Creates the [BiometricDisplayInfo] for create flows, and early handles conditional * checking between the two. The reason for this method matches the logic for the - * [validateBiometricGetFlow] with the only difference being that this is for the create flow. + * [validateAndRetrieveBiometricGetDisplayInfo] with the only difference being that this is for + * the create flow. */ private fun validateAndRetrieveBiometricCreateDisplayInfo( createRequestDisplayInfo: com.android.credentialmanager.createflow.RequestDisplayInfo?, @@ -318,8 +393,8 @@ private fun validateAndRetrieveBiometricCreateDisplayInfo( ): BiometricDisplayInfo? { if (createRequestDisplayInfo != null && createProviderInfo != null) { if (selectedEntry !is CreateOptionInfo) { return null } - return createBiometricDisplayValues(createRequestDisplayInfo, createProviderInfo, context, - selectedEntry) + return retrieveBiometricCreateDisplayValues(createRequestDisplayInfo, createProviderInfo, + context, selectedEntry) } return null } @@ -330,16 +405,16 @@ private fun validateAndRetrieveBiometricCreateDisplayInfo( * to the original selector. Note that these redundant checks are just failsafe; the original * flow should never reach here with invalid params. */ -private fun getBiometricDisplayValues( +private fun retrieveBiometricGetDisplayValues( getProviderInfoList: List<ProviderInfo>, context: Context, getRequestDisplayInfo: RequestDisplayInfo, selectedEntry: CredentialEntryInfo, ): BiometricDisplayInfo? { - var icon: Bitmap? = null - var providerName: String? = null - var displayTitleText: String? = null - var descriptionText: String? = null + val icon: Bitmap? + val providerName: String? + val displayTitleText: String? + val descriptionText: String? val primaryAccountsProviderInfo = retrievePrimaryAccountProviderInfo(selectedEntry.providerId, getProviderInfoList) icon = primaryAccountsProviderInfo?.icon?.toBitmap() @@ -373,7 +448,7 @@ private fun getBiometricDisplayValues( * if this is called, a result is guaranteed. Specifically, this is guaranteed to return a non-null * value unlike the get counterpart. */ -private fun createBiometricDisplayValues( +private fun retrieveBiometricCreateDisplayValues( createRequestDisplayInfo: com.android.credentialmanager.createflow.RequestDisplayInfo, createProviderInfo: EnabledProviderInfo, context: Context, @@ -401,7 +476,7 @@ private fun createBiometricDisplayValues( }, createRequestDisplayInfo.appName, ) - // TODO(b/327620327) : Add a subtitle and any other recently aligned ideas + // TODO(b/333445112) : Add a subtitle and any other recently aligned ideas return BiometricDisplayInfo(providerIcon = icon, providerName = providerName, displayTitleText = displayTitleText, descriptionForCredential = descriptionText, biometricRequestInfo = selectedEntry.biometricRequest as BiometricRequestInfo) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt new file mode 100644 index 000000000000..e1aa0418e7a0 --- /dev/null +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 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.credentialmanager.common + +enum class BiometricPromptState { + /** The biometric prompt hasn't been activated. */ + INACTIVE, + /** The biometric prompt is active but data hasn't been returned yet. */ + PENDING, + /** The biometric prompt has closed and returned data we then send to the provider activity. */ + COMPLETE +}
\ No newline at end of file diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt index 7e7a74fd3107..3c80113134b1 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt @@ -22,7 +22,9 @@ class Constants { const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS = "androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED" const val IS_AUTO_SELECTED_KEY = "IS_AUTO_SELECTED" - const val BIOMETRIC_AUTH_TYPE = "BIOMETRIC_AUTH_TYPE" - const val BIOMETRIC_AUTH_FAILURE = "BIOMETRIC_AUTH_FAILURE" + // TODO(b/333445772) : Qualify error codes fully for propagation + const val BIOMETRIC_AUTH_RESULT = "BIOMETRIC_AUTH_RESULT" + const val BIOMETRIC_AUTH_ERROR_CODE = "BIOMETRIC_AUTH_ERROR_CODE" + const val BIOMETRIC_AUTH_ERROR_MESSAGE = "BIOMETRIC_AUTH_ERROR_MESSAGE" } } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt index d13d86fccc97..149c14a24085 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt @@ -349,6 +349,38 @@ fun MoreOptionTopAppBar( } } +@Composable +fun MoreOptionTopAppBarWithCustomNavigation( + text: String, + onNavigationIconClicked: () -> Unit, + navigationIcon: ImageVector, + navigationIconContentDescription: String, + bottomPadding: Dp, +) { + Row( + modifier = Modifier.padding(top = 12.dp, bottom = bottomPadding), + verticalAlignment = Alignment.CenterVertically, + ) { + IconButton( + modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp).size(48.dp), + onClick = onNavigationIconClicked + ) { + Box( + modifier = Modifier.size(48.dp), + contentAlignment = Alignment.Center, + ) { + Icon( + imageVector = navigationIcon, + contentDescription = navigationIconContentDescription, + modifier = Modifier.size(24.dp).autoMirrored(), + tint = LocalAndroidColorScheme.current.onSurfaceVariant, + ) + } + } + LargeTitleText(text = text, modifier = Modifier.padding(horizontal = 4.dp)) + } +} + private fun Modifier.autoMirrored() = composed { when (LocalLayoutDirection.current) { LayoutDirection.Rtl -> graphicsLayer(scaleX = -1f) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt index 25fb477cbf38..a0915d22b613 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt @@ -46,11 +46,14 @@ import androidx.core.graphics.drawable.toBitmap import com.android.compose.theme.LocalAndroidColorScheme import com.android.credentialmanager.CredentialSelectorViewModel import com.android.credentialmanager.R +import com.android.credentialmanager.common.BiometricError +import com.android.credentialmanager.common.BiometricFlowType +import com.android.credentialmanager.common.BiometricPromptState import com.android.credentialmanager.model.EntryInfo import com.android.credentialmanager.model.CredentialType import com.android.credentialmanager.common.ProviderActivityState import com.android.credentialmanager.common.material.ModalBottomSheetDefaults -import com.android.credentialmanager.common.runBiometricFlow +import com.android.credentialmanager.common.runBiometricFlowForCreate import com.android.credentialmanager.common.ui.ActionButton import com.android.credentialmanager.common.ui.BodyMediumText import com.android.credentialmanager.common.ui.BodySmallText @@ -111,7 +114,11 @@ fun CreateCredentialScreen( onBiometricEntrySelected = viewModel::createFlowOnEntrySelected, fallbackToOriginalFlow = - viewModel::getFlowOnBackToPrimarySelectionScreen, + viewModel::fallbackFromBiometricToNormalFlow, + getBiometricPromptState = + viewModel::getBiometricPromptState, + onBiometricPromptStateChange = + viewModel::onBiometricPromptStateChange ) CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard( requestDisplayInfo = createCredentialUiState.requestDisplayInfo, @@ -575,21 +582,29 @@ internal fun BiometricSelectionPage( onMoreOptionSelected: () -> Unit, requestDisplayInfo: RequestDisplayInfo, enabledProviderInfo: EnabledProviderInfo, - onBiometricEntrySelected: (EntryInfo, BiometricPrompt.AuthenticationResult) -> Unit, + onBiometricEntrySelected: ( + EntryInfo, + BiometricPrompt.AuthenticationResult?, + BiometricError? + ) -> Unit, onCancelFlowAndFinish: () -> Unit, onIllegalScreenStateAndFinish: (String) -> Unit, - fallbackToOriginalFlow: () -> Unit, + fallbackToOriginalFlow: (BiometricFlowType) -> Unit, + getBiometricPromptState: () -> BiometricPromptState, + onBiometricPromptStateChange: (BiometricPromptState) -> Unit, ) { if (biometricEntry == null) { - fallbackToOriginalFlow() + fallbackToOriginalFlow(BiometricFlowType.CREATE) return } - runBiometricFlow( + runBiometricFlowForCreate( biometricEntry = biometricEntry, context = LocalContext.current, openMoreOptionsPage = onMoreOptionSelected, sendDataToProvider = onBiometricEntrySelected, onCancelFlowAndFinish = onCancelFlowAndFinish, + getBiometricPromptState = getBiometricPromptState, + onBiometricPromptStateChange = onBiometricPromptStateChange, createRequestDisplayInfo = requestDisplayInfo, createProviderInfo = enabledProviderInfo, onBiometricFailureFallback = fallbackToOriginalFlow, diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt index 1d262ba5261a..ddd4139b65b6 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt @@ -78,13 +78,8 @@ internal fun getCreateEntry( */ internal fun isBiometricFlow( activeEntry: ActiveEntry, - sortedCreateOptionsPairs: List<Pair<CreateOptionInfo, EnabledProviderInfo>>, - requestDisplayInfo: RequestDisplayInfo, -) = findBiometricFlowEntry(activeEntry, isFlowAutoSelectable( - requestDisplayInfo = requestDisplayInfo, - activeEntry = activeEntry, - sortedCreateOptionsPairs = sortedCreateOptionsPairs -)) != null + isAutoSelectFlow: Boolean, +) = findBiometricFlowEntry(activeEntry, isAutoSelectFlow) != null /** * This utility presents the correct resource string for the create flows title conditionally. diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt index 6d1a3dd98210..e68baf48475f 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt @@ -32,6 +32,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.outlined.QrCodeScanner import androidx.compose.material3.Divider import androidx.compose.material3.TextButton @@ -52,9 +53,12 @@ import androidx.compose.ui.unit.dp import androidx.core.graphics.drawable.toBitmap import com.android.credentialmanager.CredentialSelectorViewModel import com.android.credentialmanager.R +import com.android.credentialmanager.common.BiometricError +import com.android.credentialmanager.common.BiometricFlowType +import com.android.credentialmanager.common.BiometricPromptState import com.android.credentialmanager.common.ProviderActivityState import com.android.credentialmanager.common.material.ModalBottomSheetDefaults -import com.android.credentialmanager.common.runBiometricFlow +import com.android.credentialmanager.common.runBiometricFlowForGet import com.android.credentialmanager.common.ui.ActionButton import com.android.credentialmanager.common.ui.ActionEntry import com.android.credentialmanager.common.ui.ConfirmButton @@ -67,6 +71,7 @@ import com.android.credentialmanager.common.ui.HeadlineText import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant import com.android.credentialmanager.common.ui.ModalBottomSheet import com.android.credentialmanager.common.ui.MoreOptionTopAppBar +import com.android.credentialmanager.common.ui.MoreOptionTopAppBarWithCustomNavigation import com.android.credentialmanager.common.ui.SheetContainerCard import com.android.credentialmanager.common.ui.Snackbar import com.android.credentialmanager.common.ui.SnackbarActionText @@ -145,7 +150,7 @@ fun GetCredentialScreen( .currentScreenState == GetScreenState.BIOMETRIC_SELECTION) { BiometricSelectionPage( biometricEntry = getCredentialUiState.activeEntry, - onMoreOptionSelected = viewModel::getFlowOnMoreOptionSelected, + onMoreOptionSelected = viewModel::getFlowOnMoreOptionOnlySelected, onCancelFlowAndFinish = viewModel::onUserCancel, onIllegalStateAndFinish = viewModel::onIllegalUiState, requestDisplayInfo = getCredentialUiState.requestDisplayInfo, @@ -154,8 +159,34 @@ fun GetCredentialScreen( onBiometricEntrySelected = viewModel::getFlowOnEntrySelected, fallbackToOriginalFlow = - viewModel::getFlowOnBackToPrimarySelectionScreen, + viewModel::fallbackFromBiometricToNormalFlow, + getBiometricPromptState = + viewModel::getBiometricPromptState, + onBiometricPromptStateChange = + viewModel::onBiometricPromptStateChange ) + } else if (credmanBiometricApiEnabled() && + getCredentialUiState.currentScreenState + == GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY) { + AllSignInOptionCard( + providerInfoList = getCredentialUiState.providerInfoList, + providerDisplayInfo = getCredentialUiState.providerDisplayInfo, + onEntrySelected = viewModel::getFlowOnEntrySelected, + onBackButtonClicked = viewModel::onUserCancel, + onCancel = viewModel::onUserCancel, + onLog = { viewModel.logUiEvent(it) }, + customTopBar = { MoreOptionTopAppBarWithCustomNavigation( + text = stringResource( + R.string.get_dialog_title_sign_in_options), + onNavigationIconClicked = viewModel::onUserCancel, + navigationIcon = Icons.Filled.Close, + navigationIconContentDescription = + stringResource(R.string.accessibility_close_button), + bottomPadding = 0.dp + ) } + ) + viewModel.uiMetrics.log(GetCredentialEvent + .CREDMAN_GET_CRED_SCREEN_ALL_SIGN_IN_OPTIONS) } else { AllSignInOptionCard( providerInfoList = getCredentialUiState.providerInfoList, @@ -217,20 +248,28 @@ internal fun BiometricSelectionPage( requestDisplayInfo: RequestDisplayInfo, providerInfoList: List<ProviderInfo>, providerDisplayInfo: ProviderDisplayInfo, - onBiometricEntrySelected: (EntryInfo, BiometricPrompt.AuthenticationResult?) -> Unit, - fallbackToOriginalFlow: () -> Unit, + onBiometricEntrySelected: ( + EntryInfo, + BiometricPrompt.AuthenticationResult?, + BiometricError? + ) -> Unit, + fallbackToOriginalFlow: (BiometricFlowType) -> Unit, + getBiometricPromptState: () -> BiometricPromptState, + onBiometricPromptStateChange: (BiometricPromptState) -> Unit, ) { if (biometricEntry == null) { - fallbackToOriginalFlow() + fallbackToOriginalFlow(BiometricFlowType.GET) return } - runBiometricFlow( + runBiometricFlowForGet( biometricEntry = biometricEntry, context = LocalContext.current, openMoreOptionsPage = onMoreOptionSelected, sendDataToProvider = onBiometricEntrySelected, onCancelFlowAndFinish = onCancelFlowAndFinish, onIllegalStateAndFinish = onIllegalStateAndFinish, + getBiometricPromptState = getBiometricPromptState, + onBiometricPromptStateChange = onBiometricPromptStateChange, getRequestDisplayInfo = requestDisplayInfo, getProviderInfoList = providerInfoList, getProviderDisplayInfo = providerDisplayInfo, @@ -627,7 +666,13 @@ private fun findSingleProviderIdForPrimaryPage( return providerId } -/** Draws the secondary credential selection page, where all sign-in options are listed. */ +/** + * Draws the secondary credential selection page, where all sign-in options are listed. + * + * By default, this card has 'back' navigation whereby user can navigate back to invoke + * [onBackButtonClicked]. However if a different top bar with possibly a different navigation + * is required, then the caller of this Composable can set a [customTopBar]. + */ @Composable fun AllSignInOptionCard( providerInfoList: List<ProviderInfo>, @@ -636,16 +681,21 @@ fun AllSignInOptionCard( onBackButtonClicked: () -> Unit, onCancel: () -> Unit, onLog: @Composable (UiEventEnum) -> Unit, + customTopBar: (@Composable() () -> Unit)? = null ) { val sortedUserNameToCredentialEntryList = providerDisplayInfo.sortedUserNameToCredentialEntryList val authenticationEntryList = providerDisplayInfo.authenticationEntryList SheetContainerCard(topAppBar = { - MoreOptionTopAppBar( - text = stringResource(R.string.get_dialog_title_sign_in_options), - onNavigationIconClicked = onBackButtonClicked, - bottomPadding = 0.dp, - ) + if (customTopBar != null) { + customTopBar() + } else { + MoreOptionTopAppBar( + text = stringResource(R.string.get_dialog_title_sign_in_options), + onNavigationIconClicked = onBackButtonClicked, + bottomPadding = 0.dp, + ) + } }) { var isFirstSection = true // For username diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt index ac776af4f627..8e7886119a34 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt @@ -163,7 +163,11 @@ enum class GetScreenState { /** The single tap biometric selection page. */ BIOMETRIC_SELECTION, - /** The secondary credential selection page, where all sign-in options are listed. */ + /** + * The secondary credential selection page, where all sign-in options are listed. + * + * This state is expected to go back to PRIMARY_SELECTION on back navigation + */ ALL_SIGN_IN_OPTIONS, /** The snackbar only page when there's no account but only a remoteEntry. */ @@ -171,6 +175,14 @@ enum class GetScreenState { /** The snackbar when there are only auth entries and all of them turn out to be empty. */ UNLOCKED_AUTH_ENTRIES_ONLY, + + /** + * The secondary credential selection page, where all sign-in options are listed. + * + * This state has no option for the user to navigate back to PRIMARY_SELECTION, and + * instead can be terminated independently. + */ + ALL_SIGN_IN_OPTIONS_ONLY, } @@ -285,8 +297,8 @@ private fun toGetScreenState( providerDisplayInfo.remoteEntry != null) GetScreenState.REMOTE_ONLY else if (isRequestForAllOptions) - GetScreenState.ALL_SIGN_IN_OPTIONS - else if (isBiometricFlow(providerDisplayInfo)) + GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY + else if (isBiometricFlow(providerDisplayInfo, isFlowAutoSelectable(providerDisplayInfo))) GetScreenState.BIOMETRIC_SELECTION else GetScreenState.PRIMARY_SELECTION } @@ -294,9 +306,14 @@ private fun toGetScreenState( /** * Determines if the flow is a biometric flow by taking into account autoselect criteria. */ -internal fun isBiometricFlow(providerDisplayInfo: ProviderDisplayInfo) = - findBiometricFlowEntry(providerDisplayInfo, - findAutoSelectEntry(providerDisplayInfo) != null) != null +internal fun isBiometricFlow(providerDisplayInfo: ProviderDisplayInfo, isAutoSelectFlow: Boolean) = + findBiometricFlowEntry(providerDisplayInfo, isAutoSelectFlow) != null + +/** + * Determines if the flow is an autoselect flow. + */ +internal fun isFlowAutoSelectable(providerDisplayInfo: ProviderDisplayInfo) = + findAutoSelectEntry(providerDisplayInfo) != null internal class CredentialEntryInfoComparatorByTypeThenTimestamp( val typePriorityMap: Map<String, Int>, diff --git a/packages/CredentialManager/wear/res/drawable/passkey_icon.xml b/packages/CredentialManager/wear/res/drawable/passkey_icon.xml deleted file mode 100644 index be366bf2a255..000000000000 --- a/packages/CredentialManager/wear/res/drawable/passkey_icon.xml +++ /dev/null @@ -1,21 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:pathData="M23,10.5H17V13.5H23V10.5Z" - android:fillColor="#188038"/> - <path - android:pathData="M6.5,17.5C3.5,17.5 1,15 1,12C1,9 3.5,6.5 6.5,6.5C9.5,6.5 12,9 12,12C12,15 9.5,17.5 6.5,17.5ZM6.5,9.5C5.1,9.5 4,10.6 4,12C4,13.4 5.1,14.5 6.5,14.5C7.9,14.5 9,13.4 9,12C9,10.6 7.9,9.5 6.5,9.5Z" - android:fillColor="#4285F4"/> - <path - android:pathData="M21,13.5H19H17V16.5H19V15.5C19,14.9 19.4,14.5 20,14.5C20.6,14.5 21,14.9 21,15.5V16.5H23V13.5H21Z" - android:fillColor="#34A853"/> - <path - android:pathData="M11.8,10.5H8.5C8.8,10.9 9,11.4 9,12C9,12.6 8.8,13.1 8.5,13.5H11.8C11.9,13 12,12.5 12,12C12,11.5 11.9,11 11.8,10.5Z" - android:fillColor="#EA4335"/> - <path - android:pathData="M17,10.5H11.8C11.9,11 12,11.5 12,12C12,12.5 11.9,13 11.8,13.5H17V10.5Z" - android:fillColor="#FBBC04"/> -</vector> diff --git a/packages/CredentialManager/wear/res/values-watch/donottranslate.xml b/packages/CredentialManager/wear/res/values-watch/donottranslate.xml new file mode 100644 index 000000000000..c3ab3cbb1f27 --- /dev/null +++ b/packages/CredentialManager/wear/res/values-watch/donottranslate.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- font-family-device-default is expected to be preloaded in the font_customization.xml(/vendor/<OEM>/products/<PRODUCT>/fonts/fonts_customization.xml)--> + <!-- Falls back to system default when font-family-device-default doesn't exist --> + <string name="wear_material_compose_display_1_font_family">font-family-device-default</string> + <string name="wear_material_compose_display_2_font_family">font-family-device-default</string> + <string name="wear_material_compose_display_3_font_family">font-family-device-default</string> + <string name="wear_material_compose_title_1_font_family">font-family-medium-device-default</string> + <string name="wear_material_compose_title_2_font_family">font-family-medium-device-default</string> + <string name="wear_material_compose_title_3_font_family">font-family-device-default</string> + <string name="wear_material_compose_body_1_font_family">font-family-text-device-default</string> + <string name="wear_material_compose_body_2_font_family">font-family-text-device-default</string> + <string name="wear_material_compose_button_font_family">font-family-text-medium-device-default</string> + <string name="wear_material_compose_caption_1_font_family">font-family-text-medium-device-default</string> + <string name="wear_material_compose_caption_2_font_family">font-family-text-medium-device-default</string> + <string name="wear_material_compose_caption_3_font_family">font-family-text-medium-device-default</string> +</resources> diff --git a/packages/CredentialManager/wear/res/values/overlayable.xml b/packages/CredentialManager/wear/res/values/overlayable.xml new file mode 100644 index 000000000000..5b9d37259b98 --- /dev/null +++ b/packages/CredentialManager/wear/res/values/overlayable.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <overlayable name="CredentialSelectorStyles"> + <policy type="product|system|vendor|odm|oem"> + <!--START WEAR SPECIFIC FONT STRINGS --> + <item type="string" name="wear_material_compose_display_1_font_family" /> + <item type="string" name="wear_material_compose_display_2_font_family" /> + <item type="string" name="wear_material_compose_display_3_font_family" /> + <item type="string" name="wear_material_compose_title_1_font_family" /> + <item type="string" name="wear_material_compose_title_2_font_family" /> + <item type="string" name="wear_material_compose_title_3_font_family" /> + <item type="string" name="wear_material_compose_body_1_font_family" /> + <item type="string" name="wear_material_compose_body_2_font_family" /> + <item type="string" name="wear_material_compose_button_font_family" /> + <item type="string" name="wear_material_compose_caption_1_font_family" /> + <item type="string" name="wear_material_compose_caption_2_font_family" /> + <item type="string" name="wear_material_compose_caption_3_font_family" /> + <!--END WEAR SPECIFIC FONT STRINGS --> + + </policy> + + </overlayable> + +</resources> diff --git a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt index 3422d3dc4d94..c6013e2ffae6 100644 --- a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt +++ b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt @@ -65,29 +65,29 @@ class CredentialSelectorUiStateGetMapperTest { isLastUnlocked = true ) - val passkeyCredentialEntryInfo = + private val passkeyCredentialEntryInfo = createCredentialEntryInfo(credentialType = CredentialType.PASSKEY, userName = "userName") - val unknownCredentialEntryInfo = + private val unknownCredentialEntryInfo = createCredentialEntryInfo(credentialType = CredentialType.UNKNOWN, userName = "userName2") - val passwordCredentialEntryInfo = + private val passwordCredentialEntryInfo = createCredentialEntryInfo(credentialType = CredentialType.PASSWORD, userName = "userName") - val recentlyUsedPasskeyCredential = + private val recentlyUsedPasskeyCredential = createCredentialEntryInfo(credentialType = CredentialType.PASSKEY, lastUsedTimeMillis = 2L, userName = "userName") - val recentlyUsedPasswordCredential = + private val recentlyUsedPasswordCredential = createCredentialEntryInfo(credentialType = CredentialType.PASSWORD, lastUsedTimeMillis = 2L, userName = "userName") - val credentialList1 = listOf( + private val credentialList1 = listOf( passkeyCredentialEntryInfo, passwordCredentialEntryInfo ) - val credentialList2 = listOf( + private val credentialList2 = listOf( passkeyCredentialEntryInfo, passwordCredentialEntryInfo, recentlyUsedPasskeyCredential, @@ -100,7 +100,6 @@ class CredentialSelectorUiStateGetMapperTest { val getCredentialUiState = Request.Get( token = null, resultReceiver = null, - finalResponseReceiver = null, providerInfos = listOf(createProviderInfo(credentialList1))).toGet(isPrimary = true) assertThat(getCredentialUiState).isEqualTo( @@ -113,16 +112,16 @@ class CredentialSelectorUiStateGetMapperTest { val getCredentialUiState = Request.Get( token = null, resultReceiver = null, - finalResponseReceiver = null, providerInfos = listOf(createProviderInfo(listOf(passkeyCredentialEntryInfo, unknownCredentialEntryInfo)))).toGet(isPrimary = true) assertThat(getCredentialUiState).isEqualTo( - CredentialSelectorUiState.Get.SingleEntryPerAccount( + CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen( sortedEntries = listOf( passkeyCredentialEntryInfo, // userName unknownCredentialEntryInfo // userName2 ), + icon = mDrawable, authenticationEntryList = listOf(authenticationEntryInfo) )) // prefer passkey from account 1, then unknown from account 2 } @@ -132,7 +131,6 @@ class CredentialSelectorUiStateGetMapperTest { val getCredentialUiState = Request.Get( token = null, resultReceiver = null, - finalResponseReceiver = null, providerInfos = listOf(createProviderInfo(credentialList1))).toGet(isPrimary = false) assertThat(getCredentialUiState).isEqualTo( @@ -151,7 +149,6 @@ class CredentialSelectorUiStateGetMapperTest { val getCredentialUiState = Request.Get( token = null, resultReceiver = null, - finalResponseReceiver = null, providerInfos = listOf(createProviderInfo(credentialList1), createProviderInfo(credentialList2))).toGet(isPrimary = false) diff --git a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt index b79f34c54f51..cf839f83e689 100644 --- a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt +++ b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt @@ -121,7 +121,6 @@ class CredentialSelectorViewModelTest { stateFlow.value = Request.Get( token = null, resultReceiver = null, - finalResponseReceiver = null, providerInfos = emptyList()) mViewModel.back() @@ -136,7 +135,6 @@ class CredentialSelectorViewModelTest { stateFlow.value = Request.Get( token = null, resultReceiver = null, - finalResponseReceiver = null, providerInfos = emptyList()) mViewModel.back() diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt index 0fe35e695047..652e62cb26b4 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt @@ -21,7 +21,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels -import androidx.wear.compose.material.MaterialTheme +import com.android.credentialmanager.ui.theme.WearCredentialSelectorTheme import com.android.credentialmanager.ui.WearApp import com.google.android.horologist.annotations.ExperimentalHorologistApi import dagger.hilt.android.AndroidEntryPoint @@ -36,7 +36,7 @@ class CredentialSelectorActivity : Hilt_CredentialSelectorActivity() { super.onCreate(savedInstanceState) setTheme(android.R.style.Theme_DeviceDefault) setContent { - MaterialTheme { + WearCredentialSelectorTheme { WearApp( flowEngine = viewModel, onCloseApp = { finish() }, diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt index b7fa33e9372f..36085684db57 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt @@ -86,7 +86,7 @@ class CredentialSelectorViewModel @Inject constructor( when (uiState.value) { is Get.MultipleEntry -> isPrimaryScreen.value = true is Create, Close, is Cancel, Idle -> shouldClose.value = true - is Get.SingleEntry, is Get.SingleEntryPerAccount -> cancel() + is Get.SingleEntry, is Get.MultipleEntryPrimaryScreen -> cancel() } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt index c05fc93b8223..b2f55c108317 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt @@ -17,6 +17,7 @@ package com.android.credentialmanager import android.content.Intent +import android.graphics.drawable.Drawable import androidx.activity.result.IntentSenderRequest import androidx.compose.runtime.Composable import com.android.credentialmanager.model.EntryInfo @@ -71,14 +72,14 @@ sealed class CredentialSelectorUiState { /** Getting credential UI state when there is only one credential available. */ data class SingleEntry(val entry: CredentialEntryInfo) : Get() /** - * Getting credential UI state when there is only one account while with multiple - * credentials, with different types(eg, passkey vs password) or providers. + * Getting credential UI state on primary screen when there is are multiple accounts. */ - data class SingleEntryPerAccount( + data class MultipleEntryPrimaryScreen( + val icon: Drawable?, val sortedEntries: List<CredentialEntryInfo>, val authenticationEntryList: List<AuthenticationEntryInfo>, ) : Get() - /** Getting credential UI state when there are multiple accounts available. */ + /** Getting credential UI state on secondary screen when there are multiple accounts available. */ data class MultipleEntry( val accounts: List<PerUserNameEntries>, val actionEntryList: List<ActionEntryInfo>, diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt index 018db6899f6e..a75aeaff0c48 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt @@ -29,7 +29,7 @@ import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState import androidx.wear.compose.navigation.rememberSwipeDismissableNavController import androidx.wear.compose.navigation.rememberSwipeDismissableNavHostState import com.android.credentialmanager.CredentialSelectorUiState -import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntryPerAccount +import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntry import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry import com.android.credentialmanager.FlowEngine @@ -95,7 +95,7 @@ fun WearApp( scrollable(Screen.MultipleCredentialsScreenFold.route) { MultiCredentialsFoldScreen( - credentialSelectorUiState = (remember { uiState } as SingleEntryPerAccount), + credentialSelectorUiState = (remember { uiState } as MultipleEntryPrimaryScreen), columnState = it.columnState, flowEngine = flowEngine, ) @@ -124,7 +124,6 @@ fun WearApp( handleGetNavigation( navController = navController, state = state, - onCloseApp = onCloseApp, selectEntry = selectEntry ) } @@ -147,7 +146,6 @@ fun WearApp( private fun handleGetNavigation( navController: NavController, state: CredentialSelectorUiState.Get, - onCloseApp: () -> Unit, selectEntry: (entry: EntryInfo, isAutoSelected: Boolean) -> Unit, ) { when (state) { @@ -169,7 +167,7 @@ private fun handleGetNavigation( } } - is SingleEntryPerAccount -> { + is MultipleEntryPrimaryScreen -> { navController.navigateToMultipleCredentialsFoldScreen() } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt index 8b19e1b659d2..3088fed83c02 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt @@ -21,35 +21,25 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.wear.compose.material.MaterialTheme -import androidx.wear.compose.material.Text +import com.android.credentialmanager.common.ui.components.WearDisplayNameText +import com.android.credentialmanager.common.ui.components.WearUsernameText import com.google.android.horologist.compose.tools.WearPreview @Composable fun AccountRow( primaryText: String, secondaryText: String? = null, - modifier: Modifier = Modifier, ) { - Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) { - Text( + Column(modifier = Modifier.padding(bottom = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally) { + WearDisplayNameText( text = primaryText, - color = Color(0xFFE6FF7B), - overflow = TextOverflow.Ellipsis, - maxLines = 1, - style = MaterialTheme.typography.title2 ) if (secondaryText != null) { - Text( + WearUsernameText( text = secondaryText, - modifier = Modifier.padding(top = 7.dp), - color = Color(0xFFCAC5BC), - overflow = TextOverflow.Ellipsis, - maxLines = 2, - style = MaterialTheme.typography.body1, + modifier = Modifier.padding(top = 8.dp) ) } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt index 8e5a8666621f..c641d7f9f48f 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt @@ -22,12 +22,9 @@ import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.wear.compose.material.Chip @@ -35,11 +32,12 @@ import androidx.core.graphics.drawable.toBitmap import androidx.wear.compose.material.ChipColors import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign import androidx.wear.compose.material.ChipDefaults -import androidx.wear.compose.material.Text import com.android.credentialmanager.R +import com.android.credentialmanager.common.ui.components.WearButtonText +import com.android.credentialmanager.common.ui.components.WearSecondaryLabel import com.android.credentialmanager.model.get.AuthenticationEntryInfo -import com.android.credentialmanager.ui.components.CredentialsScreenChip.TOPPADDING /* Used as credential suggestion or user action chip. */ @Composable @@ -49,36 +47,61 @@ fun CredentialsScreenChip( secondaryLabel: String? = null, icon: Drawable? = null, isAuthenticationEntryLocked: Boolean = false, + textAlign: TextAlign = TextAlign.Center, modifier: Modifier = Modifier, - colors: ChipColors = ChipDefaults.secondaryChipColors(), + colors: ChipColors = ChipDefaults.secondaryChipColors() ) { + return CredentialsScreenChip( + onClick, + text = { + WearButtonText( + text = label, + textAlign = textAlign, + maxLines = if (secondaryLabel != null) 1 else 2 + ) + }, + secondaryLabel, + icon, + isAuthenticationEntryLocked, + modifier, + colors + ) +} + + + +/* Used as credential suggestion or user action chip. */ +@Composable +fun CredentialsScreenChip( + onClick: () -> Unit, + text: @Composable () -> Unit, + secondaryLabel: String? = null, + icon: Drawable? = null, + isAuthenticationEntryLocked: Boolean = false, + modifier: Modifier = Modifier, + colors: ChipColors = ChipDefaults.primaryChipColors(), + ) { val labelParam: (@Composable RowScope.() -> Unit) = { - Text( - text = label, - overflow = TextOverflow.Ellipsis, - maxLines = if (secondaryLabel != null) 1 else 2, - ) + text() } val secondaryLabelParam: (@Composable RowScope.() -> Unit)? = secondaryLabel?.let { { Row { - Text( + WearSecondaryLabel( text = secondaryLabel, - overflow = TextOverflow.Ellipsis, - maxLines = 1, ) if (isAuthenticationEntryLocked) - // TODO(b/324465527) change this to lock icon and correct size once figma mocks are - // updated + // TODO(b/324465527) change this to lock icon and correct size once figma mocks are + // updated Icon( bitmap = checkNotNull(icon?.toBitmap()?.asImageBitmap()), // Decorative purpose only. contentDescription = null, - modifier = Modifier.size(20.dp), + modifier = Modifier.size(10.dp), tint = Color.Unspecified ) } @@ -92,7 +115,7 @@ fun CredentialsScreenChip( bitmap = it, // Decorative purpose only. contentDescription = null, - modifier = Modifier.size(32.dp), + modifier = Modifier.size(24.dp), tint = Color.Unspecified ) } @@ -117,9 +140,6 @@ fun CredentialsScreenChipPreview() { onClick = { }, secondaryLabel = "beckett_bakery@gmail.com", icon = null, - modifier = Modifier - .clipToBounds() - .padding(top = 2.dp) ) } @@ -127,9 +147,8 @@ fun CredentialsScreenChipPreview() { fun SignInOptionsChip(onClick: () -> Unit) { CredentialsScreenChip( label = stringResource(R.string.dialog_sign_in_options_button), + textAlign = TextAlign.Start, onClick = onClick, - modifier = Modifier - .padding(top = TOPPADDING) ) } @@ -142,10 +161,13 @@ fun SignInOptionsChipPreview() { @Composable fun ContinueChip(onClick: () -> Unit) { CredentialsScreenChip( - label = stringResource(R.string.dialog_continue_button), onClick = onClick, - modifier = Modifier - .padding(top = TOPPADDING), + text = { + WearButtonText( + text = stringResource(R.string.dialog_continue_button), + textAlign = TextAlign.Center, + ) + }, colors = ChipDefaults.primaryChipColors(), ) } @@ -161,21 +183,8 @@ fun DismissChip(onClick: () -> Unit) { CredentialsScreenChip( label = stringResource(R.string.dialog_dismiss_button), onClick = onClick, - modifier = Modifier - .padding(top = TOPPADDING), - ) -} - -@Composable -fun SignInOnPhoneChip(onClick: () -> Unit) { - CredentialsScreenChip( - label = stringResource(R.string.sign_in_on_phone_button), - onClick = onClick, - modifier = Modifier - .padding(top = TOPPADDING), ) } - @Composable fun LockedProviderChip( authenticationEntryInfo: AuthenticationEntryInfo, @@ -191,9 +200,9 @@ fun LockedProviderChip( label = authenticationEntryInfo.title, icon = authenticationEntryInfo.icon, secondaryLabel = secondaryLabel, + textAlign = TextAlign.Start, isAuthenticationEntryLocked = !authenticationEntryInfo.isUnlockedAndEmpty, onClick = onClick, - modifier = Modifier.padding(top = TOPPADDING), ) } @@ -203,7 +212,3 @@ fun DismissChipPreview() { DismissChip({}) } -private object CredentialsScreenChip { - val TOPPADDING = 8.dp -} - diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt index 97900b723bc3..62e1c8501d7a 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt @@ -21,33 +21,22 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.wear.compose.material.MaterialTheme -import androidx.wear.compose.material.Text +import com.android.credentialmanager.common.ui.components.WearDisplayNameText +import com.android.credentialmanager.common.ui.components.WearUsernameText import com.google.android.horologist.compose.tools.WearPreview @Composable fun PasswordRow( email: String, - modifier: Modifier = Modifier, ) { - Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) { - Text( + Column(modifier = Modifier.padding(bottom = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally) { + WearDisplayNameText( text = email, - color = Color(0xFFE6FF7B), - overflow = TextOverflow.Ellipsis, - maxLines = 2, - style = MaterialTheme.typography.title2 ) - Text( - text = "••••••••••••••", - modifier = Modifier.padding(top = 7.dp), - color = Color(0xFFCAC5BC), - overflow = TextOverflow.Ellipsis, - maxLines = 1, - style = MaterialTheme.typography.body1, + WearUsernameText( + text = "••••••••••••••" ) } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt index 423662c30d6e..0afef5eba85e 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt @@ -18,49 +18,44 @@ package com.android.credentialmanager.ui.components import android.graphics.drawable.Drawable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.unit.dp import androidx.core.graphics.drawable.toBitmap -import androidx.wear.compose.material.Text -import androidx.compose.ui.graphics.Color -import androidx.compose.material3.Icon -import androidx.wear.compose.material.MaterialTheme as WearMaterialTheme -import androidx.compose.ui.text.style.TextAlign +import com.android.credentialmanager.common.ui.components.WearTitleText /* Used as header across Credential Selector screens. */ @Composable fun SignInHeader( icon: Drawable?, title: String, - modifier: Modifier = Modifier, ) { Column( - modifier = modifier, + modifier = Modifier, horizontalAlignment = Alignment.CenterHorizontally ) { if (icon != null) { Icon( bitmap = icon.toBitmap().asImageBitmap(), - modifier = Modifier.size(32.dp), + modifier = Modifier.size(24.dp), // Decorative purpose only. contentDescription = null, tint = Color.Unspecified, ) } + Spacer(modifier = Modifier.size(8.dp)) - Text( + WearTitleText( text = title, - textAlign = TextAlign.Center, - modifier = Modifier - .padding(top = 6.dp) - .padding(horizontal = 10.dp), - style = WearMaterialTheme.typography.title3 ) + + Spacer(modifier = Modifier.size(8.dp)) } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Spacers.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Spacers.kt new file mode 100644 index 000000000000..c87f176bc06c --- /dev/null +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Spacers.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.credentialmanager.ui.components + +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +/** + * Space beneath all elements of screen + */ +@Composable +fun BottomSpacer() { + Spacer(modifier = Modifier.size(40.dp)) + } + +/** + * Usual space between Credential Screen Chips + */ +@Composable +fun CredentialsScreenChipSpacer() { + Spacer(modifier = Modifier.size(4.dp)) +}
\ No newline at end of file diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt new file mode 100644 index 000000000000..22f6bf0f37ee --- /dev/null +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.credentialmanager.common.ui.components + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.wear.compose.material.MaterialTheme as WearMaterialTheme + +@Composable +fun WearTitleText(text: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier.wrapContentSize(), + text = text, + color = WearMaterialTheme.colors.onSurface, + textAlign = TextAlign.Center, + style = WearMaterialTheme.typography.title3, + ) +} + +@Composable +fun WearDisplayNameText(text: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier.wrapContentSize(), + text = text, + color = WearMaterialTheme.colors.onSurfaceVariant, + textAlign = TextAlign.Center, + overflow = TextOverflow.Ellipsis, + maxLines = 2, + style = WearMaterialTheme.typography.title2, + ) +} + +@Composable +fun WearUsernameText( + text: String, + textAlign: TextAlign = TextAlign.Center, + modifier: Modifier = Modifier, + onTextLayout: (TextLayoutResult) -> Unit = {}, +) { + Text( + modifier = modifier.padding(start = 8.dp, end = 8.dp).wrapContentSize(), + text = text, + color = WearMaterialTheme.colors.onSurfaceVariant, + style = WearMaterialTheme.typography.caption1, + overflow = TextOverflow.Ellipsis, + textAlign = textAlign, + maxLines = 2, + onTextLayout = onTextLayout, + ) +} + +// used for primary label in button +@Composable +fun WearButtonText( + text: String, + textAlign: TextAlign, + maxLines: Int = 1, + modifier: Modifier = Modifier, + color: Color = WearMaterialTheme.colors.onSurface, + onTextLayout: (TextLayoutResult) -> Unit = {}, +) { + Text( + modifier = modifier.wrapContentSize(), + text = text, + color = color, + style = WearMaterialTheme.typography.button, + overflow = TextOverflow.Ellipsis, + textAlign = textAlign, + maxLines = maxLines, + onTextLayout = onTextLayout, + ) +} + +@Composable +fun WearSecondaryLabel( + text: String, + modifier: Modifier = Modifier, + onTextLayout: (TextLayoutResult) -> Unit = {}, +) { + Text( + modifier = modifier.wrapContentSize(), + text = text, + color = WearMaterialTheme.colors.onSurfaceVariant, + style = WearMaterialTheme.typography.caption1, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.Start, + maxLines = 1, + onTextLayout = onTextLayout, + ) +} diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt index 7a936b603ec1..04175335b9db 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt @@ -16,6 +16,7 @@ package com.android.credentialmanager.ui.mappers +import android.graphics.drawable.Drawable import com.android.credentialmanager.model.Request import com.android.credentialmanager.CredentialSelectorUiState import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerUserNameEntries @@ -35,10 +36,19 @@ fun Request.Get.toGet(isPrimary: Boolean): CredentialSelectorUiState.Get { entry = accounts[0].value.minWith(comparator) ) } else { - CredentialSelectorUiState.Get.SingleEntryPerAccount( - sortedEntries = accounts.map { - it.value.minWith(comparator) - }.sortedWith(comparator), + val sortedEntries = accounts.map { + it.value.minWith(comparator) + }.sortedWith(comparator) + + var icon: Drawable? = null + // provide icon if all entries have the same provider + if (sortedEntries.all {it.providerId == sortedEntries[0].providerId}) { + icon = providerInfos[0].icon + } + + CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen( + sortedEntries = sortedEntries, + icon = icon, authenticationEntryList = providerInfos.flatMap { it.authenticationEntryList } ) } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt index b3ab0c4212db..0b07643056da 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt @@ -17,12 +17,9 @@ package com.android.credentialmanager.ui.screens import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier @Composable -fun LoadingScreen( - modifier: Modifier = Modifier -) { +fun LoadingScreen() { // Don't display anything, assuming that there should be minimal latency // to parse the Credential Manager intent and define the state of the // app. If latency is big, then a "loading" screen should be displayed diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt index d54103cd66e8..fb81e736171b 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt @@ -15,20 +15,21 @@ */ package com.android.credentialmanager.ui.screens.multiple +import com.android.credentialmanager.ui.components.CredentialsScreenChip import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.wear.compose.material.MaterialTheme -import androidx.wear.compose.material.Text -import com.android.credentialmanager.ui.components.SignInHeader import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry import com.android.credentialmanager.FlowEngine import com.android.credentialmanager.R +import com.android.credentialmanager.common.ui.components.WearButtonText +import com.android.credentialmanager.common.ui.components.WearSecondaryLabel import com.android.credentialmanager.model.get.CredentialEntryInfo -import com.android.credentialmanager.ui.components.CredentialsScreenChip +import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.google.android.horologist.compose.layout.ScalingLazyColumn import com.google.android.horologist.compose.layout.ScalingLazyColumnState @@ -55,20 +56,17 @@ fun MultiCredentialsFlattenScreen( ) { item { // make this credential specific if all credentials are same - SignInHeader( - icon = null, - title = stringResource(R.string.sign_in_options_title), + WearButtonText( + text = stringResource(R.string.sign_in_options_title), + textAlign = TextAlign.Start, ) } credentialSelectorUiState.accounts.forEach { userNameEntries -> item { - Text( + WearSecondaryLabel( text = userNameEntries.userName, - modifier = Modifier - .padding(top = 6.dp) - .padding(horizontal = 10.dp), - style = MaterialTheme.typography.title3 + modifier = Modifier.padding(top = 12.dp, bottom = 4.dp) ) } @@ -79,21 +77,20 @@ fun MultiCredentialsFlattenScreen( onClick = { selectEntry(credential, false) }, secondaryLabel = credential.credentialTypeDisplayName, icon = credential.icon, + textAlign = TextAlign.Start ) + + CredentialsScreenChipSpacer() } } } item { - Text( + WearSecondaryLabel( text = stringResource(R.string.provider_list_title), - modifier = Modifier - .padding(top = 6.dp) - .padding(horizontal = 10.dp), - style = MaterialTheme.typography.title3 + modifier = Modifier.padding(top = 12.dp, bottom = 4.dp) ) } - - credentialSelectorUiState.actionEntryList.forEach {actionEntry -> + credentialSelectorUiState.actionEntryList.forEach { actionEntry -> item { CredentialsScreenChip( label = actionEntry.title, @@ -101,9 +98,8 @@ fun MultiCredentialsFlattenScreen( secondaryLabel = null, icon = actionEntry.icon, ) + CredentialsScreenChipSpacer() } } } } - - diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt index 6f32c9906a1d..7addc74aecd0 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt @@ -16,10 +16,11 @@ package com.android.credentialmanager.ui.screens.multiple +import androidx.compose.foundation.layout.Spacer import com.android.credentialmanager.R import androidx.compose.ui.res.stringResource import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -35,6 +36,8 @@ import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.google.android.horologist.compose.layout.ScalingLazyColumn import com.google.android.horologist.compose.layout.ScalingLazyColumnState import com.android.credentialmanager.model.CredentialType +import com.android.credentialmanager.ui.components.BottomSpacer +import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer /** * Screen that shows multiple credentials to select from. @@ -45,7 +48,7 @@ import com.android.credentialmanager.model.CredentialType @OptIn(ExperimentalHorologistApi::class) @Composable fun MultiCredentialsFoldScreen( - credentialSelectorUiState: CredentialSelectorUiState.Get.SingleEntryPerAccount, + credentialSelectorUiState: CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen, columnState: ScalingLazyColumnState, flowEngine: FlowEngine, ) { @@ -58,42 +61,52 @@ fun MultiCredentialsFoldScreen( val credentials = credentialSelectorUiState.sortedEntries item { var title = stringResource(R.string.choose_sign_in_title) - if (credentials.all{ it.credentialType == CredentialType.PASSKEY }) { + + if (credentials.isEmpty()) { + title = stringResource(R.string.choose_sign_in_title) + } else if (credentials.all{ it.credentialType == CredentialType.PASSKEY }) { title = stringResource(R.string.choose_passkey_title) } else if (credentials.all { it.credentialType == CredentialType.PASSWORD }) { title = stringResource(R.string.choose_password_title) } SignInHeader( - icon = null, + icon = credentialSelectorUiState.icon, title = title, - modifier = Modifier - .padding(top = 6.dp), ) } credentials.forEach { credential: CredentialEntryInfo -> - item { - CredentialsScreenChip( - label = credential.userName, - onClick = { selectEntry(credential, false) }, - secondaryLabel = credential.credentialTypeDisplayName, - icon = credential.icon, - ) - } + item { + CredentialsScreenChip( + label = credential.userName, + onClick = { selectEntry(credential, false) }, + secondaryLabel = credential.credentialTypeDisplayName, + icon = credential.icon, + ) + CredentialsScreenChipSpacer() } + } credentialSelectorUiState.authenticationEntryList.forEach { authenticationEntryInfo -> item { LockedProviderChip(authenticationEntryInfo) { - selectEntry(authenticationEntryInfo, false) } + selectEntry(authenticationEntryInfo, false) + } + CredentialsScreenChipSpacer() } } + + item { + Spacer(modifier = Modifier.size(8.dp)) + } + item { SignInOptionsChip { flowEngine.openSecondaryScreen() } } item { DismissChip { flowEngine.cancel() } + BottomSpacer() } } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt index 56b1c2e3d5a4..03608a48beb6 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt @@ -29,17 +29,19 @@ import com.android.credentialmanager.model.get.CredentialEntryInfo import com.android.credentialmanager.R import com.android.credentialmanager.ui.components.AccountRow import com.android.credentialmanager.ui.components.ContinueChip +import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer import com.android.credentialmanager.ui.components.DismissChip import com.android.credentialmanager.ui.components.SignInHeader import com.android.credentialmanager.ui.components.SignInOptionsChip import com.android.credentialmanager.ui.screens.single.SingleAccountScreen import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.google.android.horologist.compose.layout.ScalingLazyColumnState +import com.android.credentialmanager.ui.components.BottomSpacer /** - * Screen that shows sign in with provider credential. + * Screen that shows single passkey credential. * - * @param entry The password entry + * @param entry The passkey entry * @param columnState ScalingLazyColumn configuration to be be applied to SingleAccountScreen * @param modifier styling for composable * @param flowEngine [FlowEngine] that updates ui state for this screen @@ -49,7 +51,6 @@ import com.google.android.horologist.compose.layout.ScalingLazyColumnState fun SinglePasskeyScreen( entry: CredentialEntryInfo, columnState: ScalingLazyColumnState, - modifier: Modifier = Modifier, flowEngine: FlowEngine, ) { SingleAccountScreen( @@ -60,21 +61,31 @@ fun SinglePasskeyScreen( ) }, accountContent = { - AccountRow( - primaryText = checkNotNull(entry.displayName), + val displayName = entry.displayName + if (displayName == null || + entry.displayName.equals(entry.userName, ignoreCase = true)) { + AccountRow( + primaryText = entry.userName, + ) + } else { + AccountRow( + primaryText = displayName, secondaryText = entry.userName, - modifier = Modifier.padding(top = 10.dp), ) + } }, columnState = columnState, - modifier = modifier.padding(horizontal = 10.dp) + modifier = Modifier.padding(horizontal = 10.dp) ) { item { val selectEntry = flowEngine.getEntrySelector() Column { ContinueChip { selectEntry(entry, false) } + CredentialsScreenChipSpacer() SignInOptionsChip{ flowEngine.openSecondaryScreen() } + CredentialsScreenChipSpacer() DismissChip { flowEngine.cancel() } + BottomSpacer() } } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt index 2ca8ef13c0cf..818723bf52bf 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt @@ -33,11 +33,13 @@ import com.android.credentialmanager.ui.components.SignInHeader import com.android.credentialmanager.ui.components.SignInOptionsChip import com.android.credentialmanager.ui.screens.single.SingleAccountScreen import com.android.credentialmanager.model.get.CredentialEntryInfo +import com.android.credentialmanager.ui.components.BottomSpacer +import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.google.android.horologist.compose.layout.ScalingLazyColumnState /** - * Screen that shows sign in with provider credential. + * Screen that shows password credential. * * @param entry The password entry. * @param columnState ScalingLazyColumn configuration to be be applied to SingleAccountScreen @@ -49,7 +51,6 @@ import com.google.android.horologist.compose.layout.ScalingLazyColumnState fun SinglePasswordScreen( entry: CredentialEntryInfo, columnState: ScalingLazyColumnState, - modifier: Modifier = Modifier, flowEngine: FlowEngine, ) { val selectEntry = flowEngine.getEntrySelector() @@ -63,17 +64,19 @@ fun SinglePasswordScreen( accountContent = { PasswordRow( email = entry.userName, - modifier = Modifier.padding(top = 10.dp), ) }, columnState = columnState, - modifier = modifier.padding(horizontal = 10.dp) + modifier = Modifier.padding(horizontal = 10.dp) ) { item { Column { ContinueChip { selectEntry(entry, false) } + CredentialsScreenChipSpacer() SignInOptionsChip{ flowEngine.openSecondaryScreen() } + CredentialsScreenChipSpacer() DismissChip { flowEngine.cancel() } + BottomSpacer() } } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt index 3a86feb4203b..34d6e977533e 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt @@ -24,7 +24,9 @@ import androidx.compose.ui.unit.dp import com.android.credentialmanager.FlowEngine import com.android.credentialmanager.model.get.CredentialEntryInfo import com.android.credentialmanager.ui.components.AccountRow +import com.android.credentialmanager.ui.components.BottomSpacer import com.android.credentialmanager.ui.components.ContinueChip +import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer import com.android.credentialmanager.ui.components.DismissChip import com.android.credentialmanager.ui.components.SignInHeader import com.android.credentialmanager.ui.components.SignInOptionsChip @@ -35,7 +37,7 @@ import com.google.android.horologist.compose.layout.ScalingLazyColumnState /** * Screen that shows sign in with provider credential. * - * @param entry The password entry. + * @param entry The custom credential entry. * @param columnState ScalingLazyColumn configuration to be be applied to SingleAccountScreen * @param modifier styling for composable * @param flowEngine [FlowEngine] that updates ui state for this screen @@ -57,16 +59,15 @@ fun SignInWithProviderScreen( }, accountContent = { val displayName = entry.displayName - if (displayName != null) { + if (displayName == null || + entry.displayName.equals(entry.userName, ignoreCase = true)) { AccountRow( - primaryText = displayName, - secondaryText = entry.userName, - modifier = Modifier.padding(top = 10.dp), + primaryText = entry.userName, ) } else { AccountRow( - primaryText = entry.userName, - modifier = Modifier.padding(top = 10.dp), + primaryText = displayName, + secondaryText = entry.userName, ) } }, @@ -77,8 +78,11 @@ fun SignInWithProviderScreen( val selectEntry = flowEngine.getEntrySelector() Column { ContinueChip { selectEntry(entry, false) } + CredentialsScreenChipSpacer() SignInOptionsChip{ flowEngine.openSecondaryScreen() } + CredentialsScreenChipSpacer() DismissChip { flowEngine.cancel() } + BottomSpacer() } } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialSelectorTheme.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialSelectorTheme.kt new file mode 100644 index 000000000000..ee0ba7ba2274 --- /dev/null +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialSelectorTheme.kt @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.credentialmanager.ui.theme + +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.annotation.StringRes +import androidx.wear.compose.material.Colors +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.DeviceFontFamilyName +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.wear.compose.material.Typography +import androidx.wear.compose.material.MaterialTheme +import com.android.credentialmanager.R +import androidx.compose.ui.graphics.Color + +/** The Material 3 Theme Wrapper for Supporting RRO. */ +@Composable +fun WearCredentialSelectorTheme(content: @Composable () -> Unit) { + val context = LocalContext.current + val colors = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + overlayColors(context) + .copy(error = MaterialTheme.colors.error, onError = MaterialTheme.colors.onError) + } else { + MaterialTheme.colors + } + MaterialTheme(colors = colors, typography = deviceDefaultTypography(context), content = content) +} + +/** + * Creates a dynamic color maps that can be overlaid. 100 - Lightest shade; 0 - Darkest Shade; In + * wear we only support dark theme for the time being. Thus the fill colors and variants are dark + * and anything on top is light. We will use this custom redirection until wear compose material + * supports color scheming. + * + * The mapping is best case match on wear material color tokens from + * /android/clockwork/common/wearable/wearmaterial/color/res/values/color-tokens.xml + * + * @param context The context required to get system resource data. + */ +@RequiresApi(Build.VERSION_CODES.S) +internal fun overlayColors(context: Context): Colors { + val tonalPalette = dynamicTonalPalette(context) + return Colors( + background = Color.Black, + onBackground = Color.White, + primary = tonalPalette.primary90, + primaryVariant = tonalPalette.primary80, + onPrimary = tonalPalette.primary10, + secondary = tonalPalette.tertiary90, + secondaryVariant = tonalPalette.tertiary60, + onSecondary = tonalPalette.tertiary10, + surface = tonalPalette.neutral20, + onSurface = tonalPalette.neutral95, + onSurfaceVariant = tonalPalette.neutralVariant80, + ) +} + +private fun fontFamily(context: Context, @StringRes id: Int): FontFamily { + val typefaceName = context.resources.getString(id) + val font = Font(familyName = DeviceFontFamilyName(typefaceName)) + return FontFamily(font) +} + +/* + Only customizes font family. The material 3 roles to 2.5 are mapped to the best case matching of + google3/java/com/google/android/wearable/libraries/compose/theme/GoogleMaterialTheme.kt +*/ +internal fun deviceDefaultTypography(context: Context): Typography { + val defaultTypography = Typography() + return Typography( + display1 = + defaultTypography.display1.copy( + fontFamily = + fontFamily(context, R.string.wear_material_compose_display_1_font_family) + ), + display2 = + defaultTypography.display2.copy( + fontFamily = + fontFamily(context, R.string.wear_material_compose_display_2_font_family) + ), + display3 = + defaultTypography.display1.copy( + fontFamily = + fontFamily(context, R.string.wear_material_compose_display_3_font_family) + ), + title1 = + defaultTypography.title1.copy( + fontFamily = fontFamily(context, R.string.wear_material_compose_title_1_font_family) + ), + title2 = + defaultTypography.title2.copy( + fontFamily = fontFamily(context, R.string.wear_material_compose_title_2_font_family) + ), + title3 = + defaultTypography.title3.copy( + fontFamily = fontFamily(context, R.string.wear_material_compose_title_3_font_family) + ), + body1 = + defaultTypography.body1.copy( + fontFamily = fontFamily(context, R.string.wear_material_compose_body_1_font_family) + ), + body2 = + defaultTypography.body2.copy( + fontFamily = fontFamily(context, R.string.wear_material_compose_body_2_font_family) + ), + button = + defaultTypography.button.copy( + fontFamily = fontFamily(context, R.string.wear_material_compose_button_font_family) + ), + caption1 = + defaultTypography.caption1.copy( + fontFamily = + fontFamily(context, R.string.wear_material_compose_caption_1_font_family) + ), + caption2 = + defaultTypography.caption2.copy( + fontFamily = + fontFamily(context, R.string.wear_material_compose_caption_2_font_family) + ), + caption3 = + defaultTypography.caption3.copy( + fontFamily = + fontFamily(context, R.string.wear_material_compose_caption_3_font_family) + ), + ) +}
\ No newline at end of file diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialTonalPalette.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialTonalPalette.kt new file mode 100644 index 000000000000..1d6ed33e65e2 --- /dev/null +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialTonalPalette.kt @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.credentialmanager.ui.theme + +import android.R +import android.content.Context +import android.os.Build +import androidx.annotation.ColorRes +import androidx.annotation.DoNotInline +import androidx.annotation.RequiresApi + +import androidx.compose.ui.graphics.Color + +/** + * Tonal Palette structure in Material. + * + * A tonal palette is comprised of 5 tonal ranges. Each tonal range includes the 13 stops, or tonal + * swatches. + * + * Tonal range names are: + * - Neutral (N) + * - Neutral variant (NV) + * - Primary (P) + * - Secondary (S) + * - Tertiary (T) + */ +internal class WearCredentialSelectorTonalPalette( + // The neutral tonal range. + val neutral100: Color, + val neutral99: Color, + val neutral95: Color, + val neutral90: Color, + val neutral80: Color, + val neutral70: Color, + val neutral60: Color, + val neutral50: Color, + val neutral40: Color, + val neutral30: Color, + val neutral20: Color, + val neutral10: Color, + val neutral0: Color, + + // The neutral variant tonal range, sometimes called "neutral 2" + val neutralVariant100: Color, + val neutralVariant99: Color, + val neutralVariant95: Color, + val neutralVariant90: Color, + val neutralVariant80: Color, + val neutralVariant70: Color, + val neutralVariant60: Color, + val neutralVariant50: Color, + val neutralVariant40: Color, + val neutralVariant30: Color, + val neutralVariant20: Color, + val neutralVariant10: Color, + val neutralVariant0: Color, + + // The primary tonal range, also known as accent 1 + val primary100: Color, + val primary99: Color, + val primary95: Color, + val primary90: Color, + val primary80: Color, + val primary70: Color, + val primary60: Color, + val primary50: Color, + val primary40: Color, + val primary30: Color, + val primary20: Color, + val primary10: Color, + val primary0: Color, + + // The Secondary tonal range, also know as accent 2 + val secondary100: Color, + val secondary99: Color, + val secondary95: Color, + val secondary90: Color, + val secondary80: Color, + val secondary70: Color, + val secondary60: Color, + val secondary50: Color, + val secondary40: Color, + val secondary30: Color, + val secondary20: Color, + val secondary10: Color, + val secondary0: Color, + + // The tertiary tonal range, also known as accent 3 + val tertiary100: Color, + val tertiary99: Color, + val tertiary95: Color, + val tertiary90: Color, + val tertiary80: Color, + val tertiary70: Color, + val tertiary60: Color, + val tertiary50: Color, + val tertiary40: Color, + val tertiary30: Color, + val tertiary20: Color, + val tertiary10: Color, + val tertiary0: Color, +) +/** Dynamic colors for wear compose material to support resource overlay. */ +@RequiresApi(Build.VERSION_CODES.S) +// TODO: once we have proper support for this on Wear 6+, we will do something similar to +// https://source.corp.google.com/h/android/platform/superproject/+/androidx-main:frameworks/support/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt;l=307-362?q=dynamicTonalPalette&sq=repo:android%2Fplatform%2Fsuperproject%20b:androidx-main +// Tracking Bug: b/270720571 +internal fun dynamicTonalPalette(context: Context) = + WearCredentialSelectorTonalPalette( + // The neutral tonal range from the generated dynamic color palette. + neutral100 = ColorResourceHelper.getColor(context, R.color.system_neutral1_0), + neutral99 = ColorResourceHelper.getColor(context, R.color.system_neutral1_10), + neutral95 = ColorResourceHelper.getColor(context, R.color.system_neutral1_50), + neutral90 = ColorResourceHelper.getColor(context, R.color.system_neutral1_100), + neutral80 = ColorResourceHelper.getColor(context, R.color.system_neutral1_200), + neutral70 = ColorResourceHelper.getColor(context, R.color.system_neutral1_300), + neutral60 = ColorResourceHelper.getColor(context, R.color.system_neutral1_400), + neutral50 = ColorResourceHelper.getColor(context, R.color.system_neutral1_500), + neutral40 = ColorResourceHelper.getColor(context, R.color.system_neutral1_600), + neutral30 = ColorResourceHelper.getColor(context, R.color.system_neutral1_700), + neutral20 = ColorResourceHelper.getColor(context, R.color.system_neutral1_800), + neutral10 = ColorResourceHelper.getColor(context, R.color.system_neutral1_900), + neutral0 = ColorResourceHelper.getColor(context, R.color.system_neutral1_1000), + + // The neutral variant tonal range, sometimes called "neutral 2", from the + // generated dynamic color palette. + neutralVariant100 = ColorResourceHelper.getColor(context, R.color.system_neutral2_0), + neutralVariant99 = ColorResourceHelper.getColor(context, R.color.system_neutral2_10), + neutralVariant95 = ColorResourceHelper.getColor(context, R.color.system_neutral2_50), + neutralVariant90 = ColorResourceHelper.getColor(context, R.color.system_neutral2_100), + neutralVariant80 = ColorResourceHelper.getColor(context, R.color.system_neutral2_200), + neutralVariant70 = ColorResourceHelper.getColor(context, R.color.system_neutral2_300), + neutralVariant60 = ColorResourceHelper.getColor(context, R.color.system_neutral2_400), + neutralVariant50 = ColorResourceHelper.getColor(context, R.color.system_neutral2_500), + neutralVariant40 = ColorResourceHelper.getColor(context, R.color.system_neutral2_600), + neutralVariant30 = ColorResourceHelper.getColor(context, R.color.system_neutral2_700), + neutralVariant20 = ColorResourceHelper.getColor(context, R.color.system_neutral2_800), + neutralVariant10 = ColorResourceHelper.getColor(context, R.color.system_neutral2_900), + neutralVariant0 = ColorResourceHelper.getColor(context, R.color.system_neutral2_1000), + + // The primary tonal range from the generated dynamic color palette. + primary100 = ColorResourceHelper.getColor(context, R.color.system_accent1_0), + primary99 = ColorResourceHelper.getColor(context, R.color.system_accent1_10), + primary95 = ColorResourceHelper.getColor(context, R.color.system_accent1_50), + primary90 = ColorResourceHelper.getColor(context, R.color.system_accent1_100), + primary80 = ColorResourceHelper.getColor(context, R.color.system_accent1_200), + primary70 = ColorResourceHelper.getColor(context, R.color.system_accent1_300), + primary60 = ColorResourceHelper.getColor(context, R.color.system_accent1_400), + primary50 = ColorResourceHelper.getColor(context, R.color.system_accent1_500), + primary40 = ColorResourceHelper.getColor(context, R.color.system_accent1_600), + primary30 = ColorResourceHelper.getColor(context, R.color.system_accent1_700), + primary20 = ColorResourceHelper.getColor(context, R.color.system_accent1_800), + primary10 = ColorResourceHelper.getColor(context, R.color.system_accent1_900), + primary0 = ColorResourceHelper.getColor(context, R.color.system_accent1_1000), + + // The secondary tonal range from the generated dynamic color palette. + secondary100 = ColorResourceHelper.getColor(context, R.color.system_accent2_0), + secondary99 = ColorResourceHelper.getColor(context, R.color.system_accent2_10), + secondary95 = ColorResourceHelper.getColor(context, R.color.system_accent2_50), + secondary90 = ColorResourceHelper.getColor(context, R.color.system_accent2_100), + secondary80 = ColorResourceHelper.getColor(context, R.color.system_accent2_200), + secondary70 = ColorResourceHelper.getColor(context, R.color.system_accent2_300), + secondary60 = ColorResourceHelper.getColor(context, R.color.system_accent2_400), + secondary50 = ColorResourceHelper.getColor(context, R.color.system_accent2_500), + secondary40 = ColorResourceHelper.getColor(context, R.color.system_accent2_600), + secondary30 = ColorResourceHelper.getColor(context, R.color.system_accent2_700), + secondary20 = ColorResourceHelper.getColor(context, R.color.system_accent2_800), + secondary10 = ColorResourceHelper.getColor(context, R.color.system_accent2_900), + secondary0 = ColorResourceHelper.getColor(context, R.color.system_accent2_1000), + + // The tertiary tonal range from the generated dynamic color palette. + tertiary100 = ColorResourceHelper.getColor(context, R.color.system_accent3_0), + tertiary99 = ColorResourceHelper.getColor(context, R.color.system_accent3_10), + tertiary95 = ColorResourceHelper.getColor(context, R.color.system_accent3_50), + tertiary90 = ColorResourceHelper.getColor(context, R.color.system_accent3_100), + tertiary80 = ColorResourceHelper.getColor(context, R.color.system_accent3_200), + tertiary70 = ColorResourceHelper.getColor(context, R.color.system_accent3_300), + tertiary60 = ColorResourceHelper.getColor(context, R.color.system_accent3_400), + tertiary50 = ColorResourceHelper.getColor(context, R.color.system_accent3_500), + tertiary40 = ColorResourceHelper.getColor(context, R.color.system_accent3_600), + tertiary30 = ColorResourceHelper.getColor(context, R.color.system_accent3_700), + tertiary20 = ColorResourceHelper.getColor(context, R.color.system_accent3_800), + tertiary10 = ColorResourceHelper.getColor(context, R.color.system_accent3_900), + tertiary0 = ColorResourceHelper.getColor(context, R.color.system_accent3_1000), + ) + +private object ColorResourceHelper { + @DoNotInline + fun getColor(context: Context, @ColorRes id: Int): Color { + return Color(context.resources.getColor(id, context.theme)) + } +}
\ No newline at end of file diff --git a/packages/InputDevices/res/raw/keyboard_layout_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_german.kcm index fbb9bb68160b..1fb0924904f0 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_german.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_german.kcm @@ -28,82 +28,93 @@ map key 86 PLUS # < > | key GRAVE { label: '^' - base: '^' + base: '\u0302' shift: '\u00b0' } key 1 { label: '1' base: '1' - shift: '!' + shift, capslock: '!' + shift+capslock: '1' } key 2 { label: '2' base: '2' - shift: '"' + shift, capslock: '"' + shift+capslock: '2' ralt: '\u00b2' } key 3 { label: '3' base: '3' - shift: '\u00a7' + shift, capslock: '\u00a7' + shift+capslock: '3' ralt: '\u00b3' } key 4 { label: '4' base: '4' - shift: '$' + shift, capslock: '$' + shift+capslock: '4' } key 5 { label: '5' base: '5' - shift: '%' + shift, capslock: '%' + shift+capslock: '5' } key 6 { label: '6' base: '6' - shift: '&' + shift, capslock: '&' + shift+capslock: '6' } key 7 { label: '7' base: '7' - shift: '/' + shift, capslock: '/' + shift+capslock: '7' ralt: '{' } key 8 { label: '8' base: '8' - shift: '(' + shift, capslock: '(' + shift+capslock: '8' ralt: '[' } key 9 { label: '9' base: '9' - shift: ')' + shift, capslock: ')' + shift+capslock: '9' ralt: ']' } key 0 { label: '0' base: '0' - shift: '=' + shift, capslock: '=' + shift+capslock: '0' ralt: '}' } key SLASH { label: '\u00df' base: '\u00df' - capslock: '\u1e9e' - shift: '?' + shift, capslock: '?' + shift+capslock: '\u00df' ralt: '\\' + shift+ralt: '\u1e9e' } key EQUALS { @@ -196,7 +207,8 @@ key LEFT_BRACKET { key RIGHT_BRACKET { label: '+' base: '+' - shift: '*' + shift, capslock: '*' + shift+capslock: '+' ralt: '~' } @@ -282,7 +294,8 @@ key APOSTROPHE { key BACKSLASH { label: '#' base: '#' - shift: '\'' + shift, capslock: '\'' + shift+capslock: '#' } ### ROW 4 @@ -347,13 +360,15 @@ key M { key COMMA { label: ',' base: ',' - shift: ';' + shift, capslock: ';' + shift+capslock: ',' } key PERIOD { label: '.' base: '.' - shift: ':' + shift, capslock: ':' + shift+capslock: '.' } key MINUS { diff --git a/packages/InputDevices/res/raw/keyboard_layout_thai_kedmanee.kcm b/packages/InputDevices/res/raw/keyboard_layout_thai_kedmanee.kcm new file mode 100644 index 000000000000..2283032e9450 --- /dev/null +++ b/packages/InputDevices/res/raw/keyboard_layout_thai_kedmanee.kcm @@ -0,0 +1,321 @@ +# Copyright 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# 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. + +# +# Thai Kedmanee keyboard layout. +# + +type OVERLAY + +map key 86 PLUS + +### ROW 1 + +key GRAVE { + label: '_' + base: '_' + shift, capslock: '%' +} + +key 1 { + label: '\u0e45' + base: '\u0e45' + shift, capslock: '+' +} + +key 2 { + label: '/' + base: '/' + shift, capslock: '\u0e51' +} + +key 3 { + label: '-' + base: '-' + shift, capslock: '\u0e52' +} + +key 4 { + label: '\u0e20' + base: '\u0e20' + shift, capslock: '\u0e53' +} + +key 5 { + label: '\u0e16' + base: '\u0e16' + shift, capslock: '\u0e54' +} + +key 6 { + label: '\u0e38' + base: '\u0e38' + shift, capslock: '\u0e39' +} + +key 7 { + label: '\u0e36' + base: '\u0e36' + shift, capslock: '\u0e3f' +} + +key 8 { + label: '\u0e04' + base: '\u0e04' + shift, capslock: '\u0e55' +} + +key 9 { + label: '\u0e15' + base: '\u0e15' + shift, capslock: '\u0e56' +} + +key 0 { + label: '\u0e08' + base: '\u0e08' + shift, capslock: '\u0e57' +} + +key MINUS { + label: '\u0e02' + base: '\u0e02' + shift, capslock: '\u0e58' +} + +key EQUALS { + label: '\u0e0a' + base: '\u0e0a' + shift, capslock: '\u0e59' +} + +### ROW 2 + +key Q { + label: '\u0e46' + base: '\u0e46' + shift, capslock: '\u0e50' +} + +key W { + label: '\u0e44' + base: '\u0e44' + shift, capslock: '\u0022' +} + +key E { + label: '\u0e33' + base: '\u0e33' + shift, capslock: '\u0e0e' +} + +key R { + label: '\u0e1e' + base: '\u0e1e' + shift, capslock: '\u0e11' +} + +key T { + label: '\u0e30' + base: '\u0e30' + shift, capslock: '\u0e18' +} + +key Y { + label: '\u0e31' + base: '\u0e31' + shift, capslock: '\u0e4d' +} + +key U { + label: '\u0e35' + base: '\u0e35' + shift, capslock: '\u0e4a' +} + +key I { + label: '\u0e23' + base: '\u0e23' + shift, capslock: '\u0e13' +} + +key O { + label: '\u0e19' + base: '\u0e19' + shift, capslock: '\u0e2f' +} + +key P { + label: '\u0e22' + base: '\u0e22' + shift, capslock: '\u0e0d' +} + +key LEFT_BRACKET { + label: '\u0e1a' + base: '\u0e1a' + shift, capslock: '\u0e10' + ctrl: '%' +} + +key RIGHT_BRACKET { + label: '\u0e25' + base: '\u0e25' + shift, capslock: ',' + ctrl: '\u0e51' +} + +### ROW 3 + +key A { + label: '\u0e1f' + base: '\u0e1f' + shift, capslock: '\u0e24' +} + +key S { + label: '\u0e2b' + base: '\u0e2b' + shift, capslock: '\u0e06' +} + +key D { + label: '\u0e01' + base: '\u0e01' + shift, capslock: '\u0e0f' +} + +key F { + label: '\u0e14' + base: '\u0e14' + shift, capslock: '\u0e42' +} + +key G { + label: '\u0e40' + base: '\u0e40' + shift, capslock: '\u0e0c' +} + +key H { + label: '\u0e49' + base: '\u0e49' + shift, capslock: '\u0e47' +} + +key J { + label: '\u0e48' + base: '\u0e48' + shift, capslock: '\u0e4b' +} + +key K { + label: '\u0e32' + base: '\u0e32' + shift, capslock: '\u0e29' +} + +key L { + label: '\u0e2a' + base: '\u0e2a' + shift, capslock: '\u0e28' +} + +key SEMICOLON { + label: '\u0e27' + base: '\u0e27' + shift, capslock: '\u0e0b' +} + +key APOSTROPHE { + label: '\u0e07' + base: '\u0e07' + shift, capslock: '.' +} + +key BACKSLASH { + label: '\u0e03' + base: '\u0e03' + shift, capslock: '\u0e05' + ctrl: '+' +} + +### ROW 4 + +key PLUS { + label: '\u0e03' + base: '\u0e03' + shift, capslock: '\u0e05' + ctrl: '\u0e52' +} + +key Z { + label: '\u0e1c' + base: '\u0e1c' + shift, capslock: '(' +} + +key X { + label: '\u0e1b' + base: '\u0e1b' + shift, capslock: ')' +} + +key C { + label: '\u0e41' + base: '\u0e41' + shift, capslock: '\u0e09' +} + +key V { + label: '\u0e2d' + base: '\u0e2d' + shift, capslock: '\u0e2e' +} + +key B { + label: '\u0e34' + base: '\u0e34' + shift, capslock: '\u0e3a' +} + +key N { + label: '\u0e37' + base: '\u0e37' + shift, capslock: '\u0e4c' +} + +key M { + label: '\u0e17' + base: '\u0e17' + shift, capslock: '?' +} + +key COMMA { + label: '\u0e21' + base: '\u0e21' + shift, capslock: '\u0e12' +} + +key PERIOD { + label: '\u0e43' + base: '\u0e43' + shift, capslock: '\u0e2c' +} + +key SLASH { + label: '\u0e1d' + base: '\u0e1d' + shift, capslock: '\u0e26' +}
\ No newline at end of file diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml index 7208894e1517..5d0c02211345 100644 --- a/packages/InputDevices/res/values-af/strings.xml +++ b/packages/InputDevices/res/values-af/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarussies"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgies"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml index 16981501d4aa..39d57173dbfd 100644 --- a/packages/InputDevices/res/values-am/strings.xml +++ b/packages/InputDevices/res/values-am/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ቤላሩስኛ"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ሞንጎሊያኛ"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ጂዮርጂያኛ"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml index 8ed19722c6ce..431585349bb3 100644 --- a/packages/InputDevices/res/values-ar/strings.xml +++ b/packages/InputDevices/res/values-ar/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"البيلاروسية"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"المنغولية"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"الجورجية"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml index 9744a7d39ef9..01714424dcfd 100644 --- a/packages/InputDevices/res/values-as/strings.xml +++ b/packages/InputDevices/res/values-as/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"বেলাৰুছিয়ান"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml index ee3a337e3ac4..39a12b7daa79 100644 --- a/packages/InputDevices/res/values-az/strings.xml +++ b/packages/InputDevices/res/values-az/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarus dili"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Monqol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcü"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-b+sr+Latn/strings.xml b/packages/InputDevices/res/values-b+sr+Latn/strings.xml index 1fc84f3aee11..64aa7f63490c 100644 --- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml +++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"beloruski"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolska"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijska"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml index 50c591088563..a8c11bee63af 100644 --- a/packages/InputDevices/res/values-be/strings.xml +++ b/packages/InputDevices/res/values-be/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Беларуская"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Мангольская"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузінская"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml index 1ee9565a666b..6d82a0b03bf4 100644 --- a/packages/InputDevices/res/values-bg/strings.xml +++ b/packages/InputDevices/res/values-bg/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"беларуски"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузински"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml index a9965385fdbc..3fc13157d5d6 100644 --- a/packages/InputDevices/res/values-bn/strings.xml +++ b/packages/InputDevices/res/values-bn/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"বেলারুশীয়"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"মঙ্গোলিয়ান"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"জর্জিয়ান"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml index c6cacbc93552..b2cf5257010d 100644 --- a/packages/InputDevices/res/values-bs/strings.xml +++ b/packages/InputDevices/res/values-bs/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"bjeloruska"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijski"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml index 761c248bcdf7..ed04b9434061 100644 --- a/packages/InputDevices/res/values-ca/strings.xml +++ b/packages/InputDevices/res/values-ca/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorús"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgià"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml index 3f1b3d0629bd..5cd3ff5708b8 100644 --- a/packages/InputDevices/res/values-cs/strings.xml +++ b/packages/InputDevices/res/values-cs/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"běloruština"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolština"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínština"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml index b160341d003a..4a6c70cb1342 100644 --- a/packages/InputDevices/res/values-da/strings.xml +++ b/packages/InputDevices/res/values-da/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Hviderussisk"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml index 17d6e4ad8b03..628a7423043d 100644 --- a/packages/InputDevices/res/values-de/strings.xml +++ b/packages/InputDevices/res/values-de/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarussisch"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisch"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml index 1b9b42e0f946..7b9651c1f847 100644 --- a/packages/InputDevices/res/values-el/strings.xml +++ b/packages/InputDevices/res/values-el/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Λευκορωσικά"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Μογγολικά"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Γεωργιανά"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml index ab48729d5006..76bb2f16abcc 100644 --- a/packages/InputDevices/res/values-en-rAU/strings.xml +++ b/packages/InputDevices/res/values-en-rAU/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml index 116178300348..aa4614b600c7 100644 --- a/packages/InputDevices/res/values-en-rCA/strings.xml +++ b/packages/InputDevices/res/values-en-rCA/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml index ab48729d5006..76bb2f16abcc 100644 --- a/packages/InputDevices/res/values-en-rGB/strings.xml +++ b/packages/InputDevices/res/values-en-rGB/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml index ab48729d5006..76bb2f16abcc 100644 --- a/packages/InputDevices/res/values-en-rIN/strings.xml +++ b/packages/InputDevices/res/values-en-rIN/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml index 92c5a5c2f65e..58dbc43add8e 100644 --- a/packages/InputDevices/res/values-en-rXC/strings.xml +++ b/packages/InputDevices/res/values-en-rXC/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml index b9fe046aa28c..05f5473b691a 100644 --- a/packages/InputDevices/res/values-es-rUS/strings.xml +++ b/packages/InputDevices/res/values-es-rUS/strings.xml @@ -4,7 +4,7 @@ <string name="app_label" msgid="8016145283189546017">"Dispositivos de entrada"</string> <string name="keyboard_layouts_label" msgid="6688773268302087545">"Teclado de Android"</string> <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Inglés (Reino Unido)"</string> - <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglés (EE. UU.)"</string> + <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglés (EE.UU.)"</string> <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglés (EE. UU.), internacional"</string> <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglés (EE. UU.), Colemak"</string> <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglés (EE. UU.), Dvorak"</string> @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorruso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml index 216e79fb2599..cd68ad870845 100644 --- a/packages/InputDevices/res/values-es/strings.xml +++ b/packages/InputDevices/res/values-es/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorruso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml index 87c486f086cf..9b37264324bf 100644 --- a/packages/InputDevices/res/values-et/strings.xml +++ b/packages/InputDevices/res/values-et/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"valgevene"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruusia"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml index 64628a82fe35..61c64157fdc2 100644 --- a/packages/InputDevices/res/values-eu/strings.xml +++ b/packages/InputDevices/res/values-eu/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusiarra"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliarra"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiarra"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml index a086060a6a17..43892051ba65 100644 --- a/packages/InputDevices/res/values-fa/strings.xml +++ b/packages/InputDevices/res/values-fa/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"بلاروسی"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"مغولی"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"گرجستانی"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml index f3bef4d97117..0e8efff287cb 100644 --- a/packages/InputDevices/res/values-fi/strings.xml +++ b/packages/InputDevices/res/values-fi/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"valkovenäjä"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgia"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml index 636358248937..e176c7ef2ff3 100644 --- a/packages/InputDevices/res/values-fr-rCA/strings.xml +++ b/packages/InputDevices/res/values-fr-rCA/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Biélorusse"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml index 37cde0517feb..4388ec1b396b 100644 --- a/packages/InputDevices/res/values-fr/strings.xml +++ b/packages/InputDevices/res/values-fr/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Biélorusse"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml index 9995f79ee732..827071e5c17b 100644 --- a/packages/InputDevices/res/values-gl/strings.xml +++ b/packages/InputDevices/res/values-gl/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belaruso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Xeorxiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml index 9dfda76c59bc..df095ae6cf7a 100644 --- a/packages/InputDevices/res/values-gu/strings.xml +++ b/packages/InputDevices/res/values-gu/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"બેલારુશિયન"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"મોંગોલિયન"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"જ્યોર્જિઅન"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml index 2562854378d1..550759d185a2 100644 --- a/packages/InputDevices/res/values-hi/strings.xml +++ b/packages/InputDevices/res/values-hi/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"बेलारूसी"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन कीबोर्ड का लेआउट"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml index 6832437e1a4a..e955e77c24c9 100644 --- a/packages/InputDevices/res/values-hr/strings.xml +++ b/packages/InputDevices/res/values-hr/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"bjeloruski"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolski"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzijska"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml index f2ac8a2b8085..565bf69a63d6 100644 --- a/packages/InputDevices/res/values-hu/strings.xml +++ b/packages/InputDevices/res/values-hu/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"belarusz"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"grúz"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml index a6676fe9875a..9722342ff209 100644 --- a/packages/InputDevices/res/values-hy/strings.xml +++ b/packages/InputDevices/res/values-hy/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"բելառուսերեն"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Մոնղոլերեն"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"վրացերեն"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml index 92bd24df2791..19fd692e6822 100644 --- a/packages/InputDevices/res/values-in/strings.xml +++ b/packages/InputDevices/res/values-in/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusia"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolia"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgia"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml index b761a7eb36f0..f76d9d74d52b 100644 --- a/packages/InputDevices/res/values-is/strings.xml +++ b/packages/InputDevices/res/values-is/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"hvítrússneska"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongólska"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgíska"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml index a992b8666ba8..ccde851a9dd7 100644 --- a/packages/InputDevices/res/values-it/strings.xml +++ b/packages/InputDevices/res/values-it/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorusso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolo"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml index de9b2767dbd6..4a8b802d7dd1 100644 --- a/packages/InputDevices/res/values-iw/strings.xml +++ b/packages/InputDevices/res/values-iw/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"בלארוסית"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"מונגולית"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"גיאורגית"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml index 6be0b4c7a8e7..b9bab69cbb98 100644 --- a/packages/InputDevices/res/values-ja/strings.xml +++ b/packages/InputDevices/res/values-ja/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ベラルーシ語"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"モンゴル語"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ジョージア語"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml index 92d94705b0fe..1610d2679735 100644 --- a/packages/InputDevices/res/values-ka/strings.xml +++ b/packages/InputDevices/res/values-ka/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ბელორუსული"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"მონღოლური"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ქართული"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml index c8ab7968d844..43bea18f824a 100644 --- a/packages/InputDevices/res/values-kk/strings.xml +++ b/packages/InputDevices/res/values-kk/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Белорус"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Моңғол"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузин"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml index fd63ab33cd03..eb4324715940 100644 --- a/packages/InputDevices/res/values-km/strings.xml +++ b/packages/InputDevices/res/values-km/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"បេឡារុស"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"មុងហ្គោលី"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ហ្សកហ្ស៊ី"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml index 761b7ccef00e..575058515cc7 100644 --- a/packages/InputDevices/res/values-kn/strings.xml +++ b/packages/InputDevices/res/values-kn/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ಬೆಲರೂಸಿಯನ್"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ಮಂಗೋಲಿಯನ್"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ಜಾರ್ಜಿಯನ್"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml index 2a1cbb00174b..b44249208bae 100644 --- a/packages/InputDevices/res/values-ko/strings.xml +++ b/packages/InputDevices/res/values-ko/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"벨라루스어"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"몽골어"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"조지아어"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml index 70295e1859a8..36cd53990d1d 100644 --- a/packages/InputDevices/res/values-ky/strings.xml +++ b/packages/InputDevices/res/values-ky/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Беларусча"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монголчо"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинче"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml index 2b8946b43d64..ab64e24ae5db 100644 --- a/packages/InputDevices/res/values-lo/strings.xml +++ b/packages/InputDevices/res/values-lo/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ເບລາຣັສຊຽນ"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ມອງໂກລຽນ"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ຈໍຈຽນ"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml index 5fca46bf3e5a..ec9893753c94 100644 --- a/packages/InputDevices/res/values-lt/strings.xml +++ b/packages/InputDevices/res/values-lt/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Baltarusių k."</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolų"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzinų"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml index d2253297c8ff..05e5d2f79bc9 100644 --- a/packages/InputDevices/res/values-lv/strings.xml +++ b/packages/InputDevices/res/values-lv/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Baltkrievu"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoļu"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzīnu"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml index d98b58b8d799..c2bc8c076187 100644 --- a/packages/InputDevices/res/values-mk/strings.xml +++ b/packages/InputDevices/res/values-mk/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"белоруски"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузиски"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml index f3468810decd..33f8f2252236 100644 --- a/packages/InputDevices/res/values-ml/strings.xml +++ b/packages/InputDevices/res/values-ml/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ബെലാറുഷ്യൻ"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"മംഗോളിയൻ"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ജോര്ജ്ജിയൻ"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml index 16970971243a..7aad90dc6c92 100644 --- a/packages/InputDevices/res/values-mn/strings.xml +++ b/packages/InputDevices/res/values-mn/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Беларусь хэл"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгол"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Гүрж"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml index 6382f6fc4d61..db607e3960e6 100644 --- a/packages/InputDevices/res/values-mr/strings.xml +++ b/packages/InputDevices/res/values-mr/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"बेलारुशियन"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml index 9bff171385ee..9a001260ac7e 100644 --- a/packages/InputDevices/res/values-ms/strings.xml +++ b/packages/InputDevices/res/values-ms/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bahasa Belarus"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Bahasa Mongolia"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Bahasa Georgia"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml index 01b55074d9f7..d87a7b4cf9a1 100644 --- a/packages/InputDevices/res/values-my/strings.xml +++ b/packages/InputDevices/res/values-my/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ဘီလာရုဇ်"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"မွန်ဂိုလီးယား"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ဂျော်ဂျီယာ"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml index 40eb25ad9f23..fbefd3866520 100644 --- a/packages/InputDevices/res/values-nb/strings.xml +++ b/packages/InputDevices/res/values-nb/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusisk"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml index 6e98bf6d9384..642fc5c73bcc 100644 --- a/packages/InputDevices/res/values-ne/strings.xml +++ b/packages/InputDevices/res/values-ne/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"बेलारुसियाली"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मङ्गोलियाली"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"जर्जियाली"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml index f3a58142f461..a93772f7b23d 100644 --- a/packages/InputDevices/res/values-nl/strings.xml +++ b/packages/InputDevices/res/values-nl/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Wit-Russisch"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml index 5b6aaea9ddf9..47af22e3a879 100644 --- a/packages/InputDevices/res/values-or/strings.xml +++ b/packages/InputDevices/res/values-or/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ବେଲାରୁସିଆନ୍"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ମଙ୍ଗୋଲିଆନ୍"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ଜର୍ଜିଆନ୍"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml index 988b4492d5f3..c634223f0d79 100644 --- a/packages/InputDevices/res/values-pa/strings.xml +++ b/packages/InputDevices/res/values-pa/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ਬੇਲਾਰੂਸੀ"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ਮੰਗੋਲੀਆਈ"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ਜਾਰਜੀਆਈ"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml index 4d1821594736..232a50590f36 100644 --- a/packages/InputDevices/res/values-pl/strings.xml +++ b/packages/InputDevices/res/values-pl/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"białoruski"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruziński"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml index e44f4ae131f9..aba7afc444fb 100644 --- a/packages/InputDevices/res/values-pt-rBR/strings.xml +++ b/packages/InputDevices/res/values-pt-rBR/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml index 3ad3e638a680..3d7c603abc79 100644 --- a/packages/InputDevices/res/values-pt-rPT/strings.xml +++ b/packages/InputDevices/res/values-pt-rPT/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml index e44f4ae131f9..aba7afc444fb 100644 --- a/packages/InputDevices/res/values-pt/strings.xml +++ b/packages/InputDevices/res/values-pt/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusso"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml index 3867e1cae1d6..4cdd54afcb0f 100644 --- a/packages/InputDevices/res/values-ro/strings.xml +++ b/packages/InputDevices/res/values-ro/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusă"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolă"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiană"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml index 7c5c95aebe68..fcdd405cb239 100644 --- a/packages/InputDevices/res/values-ru/strings.xml +++ b/packages/InputDevices/res/values-ru/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"белорусский"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монгольский"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузинский"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml index f4147f3008ee..44dfd6038174 100644 --- a/packages/InputDevices/res/values-si/strings.xml +++ b/packages/InputDevices/res/values-si/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"බෙලරුසියානු"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"මොන්ගෝලියානු"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ජෝර්ජියානු"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml index 2a375529c3c7..f02b0be1d412 100644 --- a/packages/InputDevices/res/values-sk/strings.xml +++ b/packages/InputDevices/res/values-sk/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"bieloruské"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolské"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínske"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml index 334326c0954a..ab70e0800f8f 100644 --- a/packages/InputDevices/res/values-sl/strings.xml +++ b/packages/InputDevices/res/values-sl/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"beloruščina"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolščina"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzinščina"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml index 0863138423b4..d01b2bcf1af0 100644 --- a/packages/InputDevices/res/values-sq/strings.xml +++ b/packages/InputDevices/res/values-sq/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bjellorusisht"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisht"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gjeorgjisht"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml index 973b833e6a6a..88978f65712b 100644 --- a/packages/InputDevices/res/values-sr/strings.xml +++ b/packages/InputDevices/res/values-sr/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"белоруски"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголска"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузијска"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml index b1e5d755b788..a255d248e1f8 100644 --- a/packages/InputDevices/res/values-sv/strings.xml +++ b/packages/InputDevices/res/values-sv/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"vitryska"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoliska"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgiska"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml index 0f4c8466e47e..00979e5fc691 100644 --- a/packages/InputDevices/res/values-sw/strings.xml +++ b/packages/InputDevices/res/values-sw/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Kibelarusi"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Kimongolia"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Kijojia"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml index d3535d440981..355f78dc40c9 100644 --- a/packages/InputDevices/res/values-ta/strings.xml +++ b/packages/InputDevices/res/values-ta/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"பெலரூசியன்"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"மங்கோலியன்"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ஜார்ஜியன்"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml index 5a10f6e03f71..1fe885d4d467 100644 --- a/packages/InputDevices/res/values-te/strings.xml +++ b/packages/InputDevices/res/values-te/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"బెలారష్యన్"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"మంగోలియన్"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"జార్జియన్"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml index 131c53613beb..f1b433b7e358 100644 --- a/packages/InputDevices/res/values-th/strings.xml +++ b/packages/InputDevices/res/values-th/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"เบลารุส"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ภาษามองโกเลีย"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ภาษาจอร์เจีย"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml index c42adbcbd785..21ad90927f2e 100644 --- a/packages/InputDevices/res/values-tl/strings.xml +++ b/packages/InputDevices/res/values-tl/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml index 1a84d0acf276..a1ac7fd5003a 100644 --- a/packages/InputDevices/res/values-tr/strings.xml +++ b/packages/InputDevices/res/values-tr/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusça"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Moğolca"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcüce"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml index 71b3496c929f..dcc5bcf52a59 100644 --- a/packages/InputDevices/res/values-uk/strings.xml +++ b/packages/InputDevices/res/values-uk/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Білоруська"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгольська"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинська"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml index 0cc9b61ed5ec..e8f327c05c7e 100644 --- a/packages/InputDevices/res/values-ur/strings.xml +++ b/packages/InputDevices/res/values-ur/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"بيلاروسی"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"منگؤلی"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"جارجیائی"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml index 52ecdfca5492..0968d7a68bdf 100644 --- a/packages/InputDevices/res/values-uz/strings.xml +++ b/packages/InputDevices/res/values-uz/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarus"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzin"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml index 0c638faaecd0..f7c3658e9b08 100644 --- a/packages/InputDevices/res/values-vi/strings.xml +++ b/packages/InputDevices/res/values-vi/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Tiếng Belarus"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Tiếng Mông Cổ"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Tiếng Georgia"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml index b24977982bce..7d0a12838889 100644 --- a/packages/InputDevices/res/values-zh-rCN/strings.xml +++ b/packages/InputDevices/res/values-zh-rCN/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"白俄罗斯语"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古语"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"格鲁吉亚语"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml index 60a52e98ae98..a0c3c1a52ca5 100644 --- a/packages/InputDevices/res/values-zh-rHK/strings.xml +++ b/packages/InputDevices/res/values-zh-rHK/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"白俄羅斯文"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"格魯吉亞文"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml index c3217e368492..1b8484171953 100644 --- a/packages/InputDevices/res/values-zh-rTW/strings.xml +++ b/packages/InputDevices/res/values-zh-rTW/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"白俄羅斯文"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"喬治亞文"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml index 88d55f2ff32a..c4b5d7a73acc 100644 --- a/packages/InputDevices/res/values-zu/strings.xml +++ b/packages/InputDevices/res/values-zu/strings.xml @@ -50,4 +50,6 @@ <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string> <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"isi-Mongolian"</string> <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string> + <!-- no translation found for keyboard_layout_thai_kedmanee (6637147314580760938) --> + <skip /> </resources> diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml index 1e1394096926..33a1d760f417 100644 --- a/packages/InputDevices/res/values/strings.xml +++ b/packages/InputDevices/res/values/strings.xml @@ -146,4 +146,7 @@ <!-- Georgian keyboard layout label. [CHAR LIMIT=35] --> <string name="keyboard_layout_georgian">Georgian</string> + + <!-- Thai (Kedmanee variant) keyboard layout label. [CHAR LIMIT=35] --> + <string name="keyboard_layout_thai_kedmanee">Thai (Kedmanee)</string> </resources> diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml index ee49b23b3860..4b7ea90eeb38 100644 --- a/packages/InputDevices/res/xml/keyboard_layouts.xml +++ b/packages/InputDevices/res/xml/keyboard_layouts.xml @@ -318,4 +318,11 @@ android:label="@string/keyboard_layout_georgian" android:keyboardLayout="@raw/keyboard_layout_georgian" android:keyboardLocale="ka-Geor" /> + + <keyboard-layout + android:name="keyboard_layout_thai_kedmanee" + android:label="@string/keyboard_layout_thai_kedmanee" + android:keyboardLayout="@raw/keyboard_layout_thai_kedmanee" + android:keyboardLocale="th-Thai" + android:keyboardLayoutType="extended" /> </keyboard-layouts> diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml index e788bf7e2f8f..55f960d3af2b 100644 --- a/packages/PackageInstaller/res/values-ky/strings.xml +++ b/packages/PackageInstaller/res/values-ky/strings.xml @@ -63,7 +63,7 @@ <string name="archive_application_text_all_users" msgid="3151229641681672580">"Бул колдонмо бардык колдонуучулар үчүн архивделсинби? Жеке маалыматыңыз сакталат"</string> <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Бул колдонмо жумуш профилиңизде архивделсинби? Жеке маалыматыңыз сакталат"</string> <string name="archive_application_text_user" msgid="2586558895535581451">"Бул колдонмо <xliff:g id="USERNAME">%1$s</xliff:g> үчүн архивделсинби? Жеке маалыматыңыз сакталат"</string> - <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Бул колдонмо жеке чөйрөдөн архивделсинби? Жеке маалыматыңыз сакталат"</string> + <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Бул колдонмо жеке мейкиндиктен архивделсинби? Жеке маалыматыңыз сакталат"</string> <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Бул колдонмо "<b>"бардык"</b>" колдонуучулардан алынып салынсынбы? Бул колдонмо жана анын дайындары бул түзмөктүн "<b>"бардык"</b>" колдонуучуларынан өчүрүлөт."</string> <string name="uninstall_application_text_user" msgid="498072714173920526">"Бул колдонмону <xliff:g id="USERNAME">%1$s</xliff:g> үчүн чыгарып саласызбы?"</string> <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Бул колдонмону жумуш профилиңизден чыгарып саласызбы?"</string> @@ -72,7 +72,7 @@ <string name="uninstall_keep_data" msgid="7002379587465487550">"Колдонмонун <xliff:g id="SIZE">%1$s</xliff:g> дайындарын сактоо."</string> <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Бул колдонмону өчүрөсүзбү?"</string> <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Бул колдонмону чыгарып саласызбы? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону да өчүрүлөт."</string> - <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Бул колдонмону жеке чөйрөдөн чыгарып саласызбы?"</string> + <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Бул колдонмону жеке мейкиндиктен чыгарып саласызбы?"</string> <string name="uninstalling_notification_channel" msgid="840153394325714653">"Чыгарылып салынууда"</string> <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Чыгарылып салынбай калгандар"</string> <string name="uninstalling" msgid="8709566347688966845">"Чыгарылып салынууда…"</string> diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml index 149783d9f5f8..bd288e4bde17 100644 --- a/packages/PackageInstaller/res/values-nl/strings.xml +++ b/packages/PackageInstaller/res/values-nl/strings.xml @@ -98,7 +98,7 @@ <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"Uit veiligheidsoverwegingen heeft je tv momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string> <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"Uit veiligheidsoverwegingen heeft je smartwatch momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string> <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"Uit veiligheidsoverwegingen heeft je telefoon momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string> - <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Je telefoon en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je telefoon of gegevensverlies als gevolg van het gebruik van de app."</string> + <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Je telefoon en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Door deze app te installeren, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je telefoon of gegevensverlies als gevolg van het gebruik van de app."</string> <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Je tablet en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tablet of gegevensverlies als gevolg van het gebruik van de app."</string> <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Je tv en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tv of gegevensverlies als gevolg van het gebruik van de app."</string> <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon"</string> diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml index 7f3708432a19..739d2726b56c 100644 --- a/packages/PackageInstaller/res/values-th/strings.xml +++ b/packages/PackageInstaller/res/values-th/strings.xml @@ -94,10 +94,10 @@ <string name="Parse_error_dlg_text" msgid="1661404001063076789">"พบปัญหาในการแยกวิเคราะห์แพ็กเกจ"</string> <string name="message_staging" msgid="8032722385658438567">"กำลังปรับสภาพแวดล้อมของแอป…"</string> <string name="app_name_unknown" msgid="6881210203354323926">"ไม่ทราบ"</string> - <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในแท็บเล็ต คุณเปลี่ยนแปลงได้ในการตั้งค่า"</string> - <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในทีวี คุณเปลี่ยนแปลงได้ในการตั้งค่า"</string> - <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"ปัจจุบันนาฬิกาไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้เพื่อความปลอดภัยของคุณ คุณเปลี่ยนค่านี้ได้ในการตั้งค่า"</string> - <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในโทรศัพท์ ซึ่งคุณเปลี่ยนเป็นอนุญาตได้ในการตั้งค่า"</string> + <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"เพื่อความปลอดภัย โทรศัพท์ของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string> + <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"เพื่อความปลอดภัย โทรศัพท์ของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string> + <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"เพื่อความปลอดภัย นาฬิกาของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string> + <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"เพื่อความปลอดภัย โทรศัพท์ของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string> <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"โทรศัพท์และข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับโทรศัพท์หรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string> <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"แท็บเล็ตและข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับแท็บเล็ตหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string> <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ทีวีและข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับทีวีหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string> diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java index 8f5d07c15b0b..407ab5f1729b 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java @@ -245,8 +245,7 @@ public class UninstallAlertDialogFragment extends DialogFragment implements } private static boolean isArchivingEnabled() { - return android.content.pm.Flags.archiving() - || SystemProperties.getBoolean("pm.archiving.enabled", false); + return android.content.pm.Flags.archiving(); } private boolean isCloneProfile(UserHandle userHandle) { diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml index 5298f8b329ba..6ffad709b2f3 100644 --- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml +++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml @@ -35,7 +35,7 @@ <string name="install_for_print_preview" msgid="6366303997385509332">"Installer un lecteur PDF pour voir l\'aperçu"</string> <string name="printing_app_crashed" msgid="854477616686566398">"L\'application à l\'origine de l\'impression a planté"</string> <string name="generating_print_job" msgid="3119608742651698916">"Génération tâche impression…"</string> - <string name="save_as_pdf" msgid="5718454119847596853">"Enregistrer en format PDF"</string> + <string name="save_as_pdf" msgid="5718454119847596853">"Enregistrer au format PDF"</string> <string name="all_printers" msgid="5018829726861876202">"Toutes les imprimantes…"</string> <string name="print_dialog" msgid="32628687461331979">"Boîte de dialogue d\'impression"</string> <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> sur <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string> diff --git a/packages/PrintSpooler/res/values-night/themes.xml b/packages/PrintSpooler/res/values-night/themes.xml index 4428dbbbaaae..3cc64a6ef266 100644 --- a/packages/PrintSpooler/res/values-night/themes.xml +++ b/packages/PrintSpooler/res/values-night/themes.xml @@ -30,6 +30,7 @@ <item name="android:windowIsTranslucent">true</item> <item name="android:windowActionBar">false</item> <item name="android:windowNoTitle">true</item> + <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> </style> </resources> diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml index 4dcad10c793c..bd9602540878 100644 --- a/packages/PrintSpooler/res/values/themes.xml +++ b/packages/PrintSpooler/res/values/themes.xml @@ -31,6 +31,7 @@ <item name="android:windowActionBar">false</item> <item name="android:windowNoTitle">true</item> <item name="android:windowLightStatusBar">true</item> + <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> </style> </resources> diff --git a/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml index 9095f8e4d750..f0bee5e18709 100644 --- a/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="help_feedback_label" msgid="7106780063063027882">"Ajuda e comentários"</string> + <string name="help_feedback_label" msgid="7106780063063027882">"Ajuda e feedback"</string> </resources> diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml index fa5df16bf35a..b5534b9c9246 100644 --- a/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml +++ b/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml @@ -18,5 +18,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="enabled_by_admin" msgid="6630472777476410137">"एडमिन की ओर से चालू किया गया"</string> - <string name="disabled_by_admin" msgid="4023569940620832713">"एडमिन की ओर से बंद किया गया"</string> + <string name="disabled_by_admin" msgid="4023569940620832713">"एडमिन ने यह सुविधा बंद की है"</string> </resources> diff --git a/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml b/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml index 23f46bf3d655..473231a10bfc 100644 --- a/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"সেটিংসে সার্চ করুন"</string> + <string name="search_menu" msgid="1914043873178389845">"সার্চ সেটিংস"</string> </resources> diff --git a/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml b/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml index 0d3a4daf2213..99a9b05b9a62 100644 --- a/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"Tetapan carian"</string> + <string name="search_menu" msgid="1914043873178389845">"Cari tetapan"</string> </resources> diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt index 761bb7918afd..91bd7916b0ab 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt @@ -40,7 +40,7 @@ import com.android.settingslib.spa.gallery.page.FooterPageProvider import com.android.settingslib.spa.gallery.page.IllustrationPageProvider import com.android.settingslib.spa.gallery.page.LoadingBarPageProvider import com.android.settingslib.spa.gallery.page.ProgressBarPageProvider -import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider +import com.android.settingslib.spa.gallery.scaffold.NonScrollablePagerPageProvider import com.android.settingslib.spa.gallery.page.SliderPageProvider import com.android.settingslib.spa.gallery.preference.ListPreferencePageProvider import com.android.settingslib.spa.gallery.preference.MainSwitchPreferencePageProvider @@ -48,10 +48,12 @@ import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider import com.android.settingslib.spa.gallery.preference.PreferencePageProvider import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvider import com.android.settingslib.spa.gallery.preference.TwoTargetSwitchPreferencePageProvider +import com.android.settingslib.spa.gallery.scaffold.PagerMainPageProvider import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider import com.android.settingslib.spa.gallery.ui.CategoryPageProvider import com.android.settingslib.spa.gallery.ui.CopyablePageProvider +import com.android.settingslib.spa.gallery.scaffold.ScrollablePagerPageProvider import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider import com.android.settingslib.spa.slice.SpaSliceBroadcastReceiver @@ -84,7 +86,9 @@ class GallerySpaEnvironment(context: Context) : SpaEnvironment(context) { ArgumentPageProvider, SliderPageProvider, SpinnerPageProvider, - SettingsPagerPageProvider, + PagerMainPageProvider, + NonScrollablePagerPageProvider, + ScrollablePagerPageProvider, FooterPageProvider, IllustrationPageProvider, CategoryPageProvider, diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt index 1f028d5e7bc9..654719d906a9 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt @@ -39,9 +39,9 @@ import com.android.settingslib.spa.gallery.page.FooterPageProvider import com.android.settingslib.spa.gallery.page.IllustrationPageProvider import com.android.settingslib.spa.gallery.page.LoadingBarPageProvider import com.android.settingslib.spa.gallery.page.ProgressBarPageProvider -import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider import com.android.settingslib.spa.gallery.page.SliderPageProvider import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider +import com.android.settingslib.spa.gallery.scaffold.PagerMainPageProvider import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider import com.android.settingslib.spa.gallery.ui.CategoryPageProvider @@ -63,7 +63,7 @@ object HomePageProvider : SettingsPageProvider { SuwScaffoldPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), SliderPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), SpinnerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), - SettingsPagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), + PagerMainPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), FooterPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), IllustrationPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), CategoryPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/NonScrollablePagerPageProvider.kt index dc45e6da0bc1..029773fdf8df 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/NonScrollablePagerPageProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.settingslib.spa.gallery.page +package com.android.settingslib.spa.gallery.scaffold import android.os.Bundle import androidx.compose.foundation.layout.Box @@ -33,24 +33,19 @@ import com.android.settingslib.spa.widget.scaffold.SettingsPager import com.android.settingslib.spa.widget.scaffold.SettingsScaffold import com.android.settingslib.spa.widget.ui.PlaceholderTitle -private const val TITLE = "Sample SettingsPager" +object NonScrollablePagerPageProvider : SettingsPageProvider { + override val name = "NonScrollablePager" + private const val TITLE = "Sample Non Scrollable SettingsPager" -object SettingsPagerPageProvider : SettingsPageProvider { - override val name = "SettingsPager" - - fun buildInjectEntry(): SettingsEntryBuilder { - return SettingsEntryBuilder.createInject(owner = createSettingsPage()) - .setUiLayoutFn { - Preference(object : PreferenceModel { - override val title = TITLE - override val onClick = navigator(name) - }) - } - } + fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = createSettingsPage()) + .setUiLayoutFn { + Preference(object : PreferenceModel { + override val title = TITLE + override val onClick = navigator(name) + }) + } - override fun getTitle(arguments: Bundle?): String { - return TITLE - } + override fun getTitle(arguments: Bundle?) = TITLE @Composable override fun Page(arguments: Bundle?) { @@ -66,8 +61,8 @@ object SettingsPagerPageProvider : SettingsPageProvider { @Preview(showBackground = true) @Composable -private fun SettingsPagerPagePreview() { +private fun NonScrollablePagerPageProviderPreview() { SettingsTheme { - SettingsPagerPageProvider.Page(null) + NonScrollablePagerPageProvider.Page(null) } } diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/PagerMainPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/PagerMainPageProvider.kt new file mode 100644 index 000000000000..66cc38f74b07 --- /dev/null +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/PagerMainPageProvider.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.gallery.scaffold + +import android.os.Bundle +import com.android.settingslib.spa.framework.common.SettingsEntryBuilder +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.common.createSettingsPage +import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel + +object PagerMainPageProvider : SettingsPageProvider { + override val name = "PagerMain" + private val owner = createSettingsPage() + private const val TITLE = "Category: Pager" + + override fun buildEntry(arguments: Bundle?) = listOf( + NonScrollablePagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), + ScrollablePagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(), + ) + + fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner) + .setUiLayoutFn { + Preference(object : PreferenceModel { + override val title = TITLE + override val onClick = navigator(name) + }) + } + + override fun getTitle(arguments: Bundle?) = TITLE +} diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/ScrollablePagerPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/ScrollablePagerPageProvider.kt new file mode 100644 index 000000000000..689a98a16b23 --- /dev/null +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/ScrollablePagerPageProvider.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.gallery.scaffold + +import android.os.Bundle +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.android.settingslib.spa.framework.common.SettingsEntryBuilder +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.common.createSettingsPage +import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.framework.theme.SettingsTheme +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spa.widget.scaffold.SettingsPager +import com.android.settingslib.spa.widget.scaffold.SettingsScaffold + +object ScrollablePagerPageProvider : SettingsPageProvider { + override val name = "ScrollablePager" + private const val TITLE = "Sample Scrollable SettingsPager" + + fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = createSettingsPage()) + .setUiLayoutFn { + Preference(object : PreferenceModel { + override val title = TITLE + override val onClick = navigator(name) + }) + } + + override fun getTitle(arguments: Bundle?) = TITLE + + @Composable + override fun Page(arguments: Bundle?) { + SettingsScaffold(title = getTitle(arguments)) { paddingValues -> + Box(Modifier.padding(paddingValues)) { + SettingsPager(listOf("Personal", "Work")) { + LazyColumn { + items(30) { + Preference(object : PreferenceModel { + override val title = it.toString() + }) + } + } + } + } + } + } +} + +@Preview(showBackground = true) +@Composable +private fun ScrollablePagerPageProviderPreview() { + SettingsTheme { + ScrollablePagerPageProvider.Page(null) + } +} diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt index 6fc8de3ac49c..a0ab2ce6945d 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt @@ -22,6 +22,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.SignalCellularAlt import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPageProvider @@ -37,6 +41,8 @@ import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton import com.android.settingslib.spa.widget.scaffold.SuwScaffold import com.android.settingslib.spa.widget.ui.SettingsBody +import com.android.settingslib.spa.widget.ui.Spinner +import com.android.settingslib.spa.widget.ui.SpinnerOption private const val TITLE = "Sample SuwScaffold" @@ -67,13 +73,12 @@ private fun Page() { actionButton = BottomAppBarButton("Next") {}, dismissButton = BottomAppBarButton("Cancel") {}, ) { - Column(Modifier.padding(SettingsDimension.itemPadding)) { - SettingsBody("To add another SIM, download a new eSIM.") - } - Illustration(object : IllustrationModel { - override val resId = R.drawable.accessibility_captioning_banner - override val resourceType = ResourceType.IMAGE - }) + var selectedId by rememberSaveable { mutableIntStateOf(1) } + Spinner( + options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, + selectedId = selectedId, + setId = { selectedId = it }, + ) Column(Modifier.padding(SettingsDimension.itemPadding)) { SettingsBody("To add another SIM, download a new eSIM.") } diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml index 0ee9d595d875..85ad160f6d66 100644 --- a/packages/SettingsLib/Spa/gradle/libs.versions.toml +++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml @@ -15,7 +15,7 @@ # [versions] -agp = "8.3.1" +agp = "8.3.2" compose-compiler = "1.5.11" dexmaker-mockito = "2.28.3" jvm = "17" diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.7-bin.zip Binary files differindex 5c9634782bbe..7a9ac5afe013 100644 --- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip +++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.7-bin.zip diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties index 50ff9dff549b..182095e76e76 100644 --- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties +++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties @@ -16,6 +16,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=gradle-8.6-bin.zip +distributionUrl=gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png Binary files differindex 3e016f791962..75c8e6efd2e2 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png Binary files differindex d156f95afa79..06f0059ef547 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png Binary files differindex b8bb25fc9382..b72c8db9debc 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png Binary files differindex d156f95afa79..06f0059ef547 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png Binary files differindex 90442080fe22..e43f27d49dee 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png Binary files differindex 36cbadc5bdaf..15c86dc67736 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png Binary files differindex a279481d2a5c..5be3a217ec91 100644 --- a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png +++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts index 2f2ac2467a6c..6344501ce789 100644 --- a/packages/SettingsLib/Spa/spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/spa/build.gradle.kts @@ -65,7 +65,7 @@ dependencies { api("androidx.lifecycle:lifecycle-runtime-compose") api("androidx.navigation:navigation-compose:2.8.0-alpha05") api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha") - api("com.google.android.material:material:1.7.0-alpha03") + api("com.google.android.material:material:1.11.0") debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion") implementation("com.airbnb.android:lottie-compose:5.2.0") diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt index 791893b3c056..ef1a137198c2 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt @@ -37,6 +37,7 @@ fun TwoTargetSwitchPreference( SettingsSwitch( checked = model.checked(), changeable = model.changeable, + contentDescription = model.title, onCheckedChange = model.onCheckedChange, ) } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt index f372a45f9e59..163766a7a9c5 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt @@ -19,7 +19,6 @@ package com.android.settingslib.spa.widget.scaffold import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding @@ -33,6 +32,8 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.movableContentOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import com.android.settingslib.spa.framework.theme.SettingsDimension @@ -50,7 +51,7 @@ fun SuwScaffold( title: String, actionButton: BottomAppBarButton? = null, dismissButton: BottomAppBarButton? = null, - content: @Composable ColumnScope.() -> Unit, + content: @Composable () -> Unit, ) { ActivityTitle(title) Scaffold { innerPadding -> @@ -59,6 +60,7 @@ fun SuwScaffold( .padding(innerPadding) .padding(top = SettingsDimension.itemPaddingAround) ) { + val movableContent = remember(content) { movableContentOf { content() } } // Use single column layout in portrait, two columns in landscape. val useSingleColumn = maxWidth < maxHeight if (useSingleColumn) { @@ -69,7 +71,7 @@ fun SuwScaffold( .verticalScroll(rememberScrollState()) ) { Header(imageVector, title) - content() + movableContent() } BottomBar(actionButton, dismissButton) } @@ -82,8 +84,9 @@ fun SuwScaffold( Column( Modifier .weight(1f) - .verticalScroll(rememberScrollState())) { - content() + .verticalScroll(rememberScrollState()) + ) { + movableContent() } } BottomBar(actionButton, dismissButton) diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt index a0da2418acbc..5155406b6d79 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt @@ -20,12 +20,16 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.material3.Switch import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import com.android.settingslib.spa.framework.util.wrapOnSwitchWithLog @Composable internal fun SettingsSwitch( checked: Boolean?, changeable: () -> Boolean, + contentDescription: String? = null, onCheckedChange: ((newChecked: Boolean) -> Unit)? = null, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) { @@ -33,6 +37,9 @@ internal fun SettingsSwitch( Switch( checked = checked, onCheckedChange = wrapOnSwitchWithLog(onCheckedChange), + modifier = if (contentDescription != null) Modifier.semantics { + this.contentDescription = contentDescription + } else Modifier, enabled = changeable(), interactionSource = interactionSource, ) diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml index 9a8e7ddc6ef5..f259541fc0d4 100644 --- a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml +++ b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml @@ -20,8 +20,8 @@ <string name="no_applications" msgid="5800789569715871963">"ليس هناك أي تطبيقات."</string> <string name="menu_show_system" msgid="906304605807554788">"إظهار عمليات النظام"</string> <string name="menu_hide_system" msgid="374571689914923020">"إخفاء عمليات النظام"</string> - <string name="app_permission_summary_allowed" msgid="6115213465364138103">"مسموح به"</string> - <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غير مسموح به"</string> + <string name="app_permission_summary_allowed" msgid="6115213465364138103">"تطبيق مسموح به"</string> + <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"تطبيق غير مسموح به"</string> <string name="version_text" msgid="4001669804596458577">"الإصدار <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string> <string name="cloned_app_info_label" msgid="1765651167024478391">"نسخة طبق الأصل من \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\""</string> </resources> diff --git a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml index a2a4289c1bf5..b1d572195391 100644 --- a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml +++ b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml @@ -17,7 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="no_applications" msgid="5800789569715871963">"Tidak ada aplikasi."</string> + <string name="no_applications" msgid="5800789569715871963">"Tidak ada aplikasi"</string> <string name="menu_show_system" msgid="906304605807554788">"Tampilkan sistem"</string> <string name="menu_hide_system" msgid="374571689914923020">"Sembunyikan sistem"</string> <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Diizinkan"</string> diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml index 7f3a52325814..87d0762cf1e9 100644 --- a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml +++ b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml @@ -18,8 +18,8 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="no_applications" msgid="5800789569715871963">"कुनै पनि एप छैन।"</string> - <string name="menu_show_system" msgid="906304605807554788">"सिस्टम देखाइयोस्"</string> - <string name="menu_hide_system" msgid="374571689914923020">"सिस्टम लुकाइयोस्"</string> + <string name="menu_show_system" msgid="906304605807554788">"सिस्टम देखाउनुहोस्"</string> + <string name="menu_hide_system" msgid="374571689914923020">"सिस्टम लुकाउनुहोस्"</string> <string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमति दिइएका एप"</string> <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमति नदिइएका एप"</string> <string name="version_text" msgid="4001669804596458577">"संस्करण <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt index a395266ba5f9..e1e1ee5a8feb 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt @@ -151,7 +151,7 @@ class AppListRepositoryImpl( } private fun isArchivingEnabled(featureFlags: FeatureFlags) = - featureFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false) + featureFlags.archiving() override fun showSystemPredicate( userIdFlow: Flow<Int>, diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java index a4089c0d8697..7f4bebcf4a62 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java @@ -52,16 +52,12 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; -/** - * Description of a single dashboard tile that the user can select. - */ +/** Description of a single dashboard tile that the user can select. */ public abstract class Tile implements Parcelable { private static final String TAG = "Tile"; - /** - * Optional list of user handles which the intent should be launched on. - */ + /** Optional list of user handles which the intent should be launched on. */ public ArrayList<UserHandle> userHandle = new ArrayList<>(); public HashMap<UserHandle, PendingIntent> pendingIntentMap = new HashMap<>(); @@ -76,6 +72,7 @@ public abstract class Tile implements Parcelable { private CharSequence mSummaryOverride; private Bundle mMetaData; private String mCategory; + private String mGroupKey; public Tile(ComponentInfo info, String category, Bundle metaData) { mComponentInfo = info; @@ -83,6 +80,9 @@ public abstract class Tile implements Parcelable { mComponentName = mComponentInfo.name; mCategory = category; mMetaData = metaData; + if (mMetaData != null) { + mGroupKey = metaData.getString(META_DATA_PREFERENCE_GROUP_KEY); + } mIntent = new Intent().setClassName(mComponentPackage, mComponentName); if (isNewTask()) { mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -102,6 +102,7 @@ public abstract class Tile implements Parcelable { if (isNewTask()) { mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } + mGroupKey = in.readString(); } @Override @@ -121,16 +122,13 @@ public abstract class Tile implements Parcelable { } dest.writeString(mCategory); dest.writeBundle(mMetaData); + dest.writeString(mGroupKey); } - /** - * Unique ID of the tile - */ + /** Unique ID of the tile */ public abstract int getId(); - /** - * Human-readable description of the tile - */ + /** Human-readable description of the tile */ public abstract String getDescription(); protected abstract ComponentInfo getComponentInfo(Context context); @@ -147,16 +145,12 @@ public abstract class Tile implements Parcelable { return mComponentName; } - /** - * Intent to launch when the preference is selected. - */ + /** Intent to launch when the preference is selected. */ public Intent getIntent() { return mIntent; } - /** - * Category in which the tile should be placed. - */ + /** Category in which the tile should be placed. */ public String getCategory() { return mCategory; } @@ -165,9 +159,7 @@ public abstract class Tile implements Parcelable { mCategory = newCategoryKey; } - /** - * Priority of this tile, used for display ordering. - */ + /** Priority of this tile, used for display ordering. */ public int getOrder() { if (hasOrder()) { return mMetaData.getInt(META_DATA_KEY_ORDER); @@ -176,32 +168,24 @@ public abstract class Tile implements Parcelable { } } - /** - * Check whether tile has order. - */ + /** Check whether tile has order. */ public boolean hasOrder() { return mMetaData != null && mMetaData.containsKey(META_DATA_KEY_ORDER) && mMetaData.get(META_DATA_KEY_ORDER) instanceof Integer; } - /** - * Check whether tile has a switch. - */ + /** Check whether tile has a switch. */ public boolean hasSwitch() { return mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_SWITCH_URI); } - /** - * Check whether tile has a pending intent. - */ + /** Check whether tile has a pending intent. */ public boolean hasPendingIntent() { return !pendingIntentMap.isEmpty(); } - /** - * Title of the tile that is shown to the user. - */ + /** Title of the tile that is shown to the user. */ public CharSequence getTitle(Context context) { CharSequence title = null; ensureMetadataNotStale(context); @@ -238,9 +222,7 @@ public abstract class Tile implements Parcelable { mSummaryOverride = summaryOverride; } - /** - * Optional summary describing what this tile controls. - */ + /** Optional summary describing what this tile controls. */ public CharSequence getSummary(Context context) { if (mSummaryOverride != null) { return mSummaryOverride; @@ -275,16 +257,12 @@ public abstract class Tile implements Parcelable { mMetaData = metaData; } - /** - * The metaData from the activity that defines this tile. - */ + /** The metaData from the activity that defines this tile. */ public Bundle getMetaData() { return mMetaData; } - /** - * Optional key to use for this tile. - */ + /** Optional key to use for this tile. */ public String getKey(Context context) { ensureMetadataNotStale(context); if (!hasKey()) { @@ -297,9 +275,7 @@ public abstract class Tile implements Parcelable { } } - /** - * Check whether title has key. - */ + /** Check whether title has key. */ public boolean hasKey() { return mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_KEYHINT); } @@ -325,8 +301,9 @@ public abstract class Tile implements Parcelable { if (iconResId != 0 && iconResId != android.R.color.transparent) { final Icon icon = Icon.createWithResource(componentInfo.packageName, iconResId); if (isIconTintable(context)) { - final TypedArray a = context.obtainStyledAttributes(new int[]{ - android.R.attr.colorControlNormal}); + final TypedArray a = + context.obtainStyledAttributes( + new int[] {android.R.attr.colorControlNormal}); final int tintColor = a.getColor(0, 0); a.recycle(); icon.setTint(tintColor); @@ -349,26 +326,22 @@ public abstract class Tile implements Parcelable { return false; } - /** - * Whether the {@link Activity} should be launched in a separate task. - */ + /** Whether the {@link Activity} should be launched in a separate task. */ public boolean isNewTask() { - if (mMetaData != null - && mMetaData.containsKey(META_DATA_NEW_TASK)) { + if (mMetaData != null && mMetaData.containsKey(META_DATA_NEW_TASK)) { return mMetaData.getBoolean(META_DATA_NEW_TASK); } return false; } - /** - * Ensures metadata is not stale for this tile. - */ + /** Ensures metadata is not stale for this tile. */ private void ensureMetadataNotStale(Context context) { final PackageManager pm = context.getApplicationContext().getPackageManager(); try { - final long lastUpdateTime = pm.getPackageInfo(mComponentPackage, - PackageManager.GET_META_DATA).lastUpdateTime; + final long lastUpdateTime = + pm.getPackageInfo(mComponentPackage, PackageManager.GET_META_DATA) + .lastUpdateTime; if (lastUpdateTime == mLastUpdateTime) { // All good. Do nothing return; @@ -382,72 +355,60 @@ public abstract class Tile implements Parcelable { } } - public static final Creator<Tile> CREATOR = new Creator<Tile>() { - public Tile createFromParcel(Parcel source) { - final boolean isProviderTile = source.readBoolean(); - // reset the Parcel pointer before delegating to the real constructor. - source.setDataPosition(0); - return isProviderTile ? new ProviderTile(source) : new ActivityTile(source); - } + public static final Creator<Tile> CREATOR = + new Creator<Tile>() { + public Tile createFromParcel(Parcel source) { + final boolean isProviderTile = source.readBoolean(); + // reset the Parcel pointer before delegating to the real constructor. + source.setDataPosition(0); + return isProviderTile ? new ProviderTile(source) : new ActivityTile(source); + } - public Tile[] newArray(int size) { - return new Tile[size]; - } - }; + public Tile[] newArray(int size) { + return new Tile[size]; + } + }; - /** - * Check whether tile only has primary profile. - */ + /** Check whether tile only has primary profile. */ public boolean isPrimaryProfileOnly() { return isPrimaryProfileOnly(mMetaData); } static boolean isPrimaryProfileOnly(Bundle metaData) { - String profile = metaData != null - ? metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL; + String profile = metaData != null ? metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL; profile = (profile != null ? profile : PROFILE_ALL); return TextUtils.equals(profile, PROFILE_PRIMARY); } - /** - * Returns whether the tile belongs to another group / category. - */ + /** Returns whether the tile belongs to another group / category. */ public boolean hasGroupKey() { - return mMetaData != null - && !TextUtils.isEmpty(mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY)); + return !TextUtils.isEmpty(mGroupKey); } - /** - * Returns the group / category key this tile belongs to. - */ + /** Set the group / PreferenceCategory key this tile belongs to. */ + public void setGroupKey(String groupKey) { + mGroupKey = groupKey; + } + + /** Returns the group / category key this tile belongs to. */ public String getGroupKey() { - return (mMetaData == null) ? null : mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY); + return mGroupKey; } - /** - * Returns if this is searchable. - */ + /** Returns if this is searchable. */ public boolean isSearchable() { return mMetaData == null || mMetaData.getBoolean(META_DATA_PREFERENCE_SEARCHABLE, true); } - /** - * The type of the tile. - */ + /** The type of the tile. */ public enum Type { - /** - * A preference that can be tapped on to open a new page. - */ + /** A preference that can be tapped on to open a new page. */ ACTION, - /** - * A preference that can be tapped on to open an external app. - */ + /** A preference that can be tapped on to open an external app. */ EXTERNAL_ACTION, - /** - * A preference that shows an on / off switch that can be toggled by the user. - */ + /** A preference that shows an on / off switch that can be toggled by the user. */ SWITCH, /** @@ -460,7 +421,7 @@ public abstract class Tile implements Parcelable { * A preference category with a title that can be used to group multiple preferences * together. */ - GROUP; + GROUP } /** diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java index d0929e19bc9b..b949cd58a862 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java @@ -77,9 +77,7 @@ public class TileUtils { */ public static final String IA_SETTINGS_ACTION = "com.android.settings.action.IA_SETTINGS"; - /** - * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities. - */ + /** Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities. */ private static final String SETTINGS_ACTION = "com.android.settings.action.SETTINGS"; private static final String OPERATOR_SETTINGS = @@ -101,9 +99,7 @@ public class TileUtils { */ static final String EXTRA_CATEGORY_KEY = "com.android.settings.category"; - /** - * The key used to get the package name of the icon resource for the preference. - */ + /** The key used to get the package name of the icon resource for the preference. */ static final String EXTRA_PREFERENCE_ICON_PACKAGE = "com.android.settings.icon_package"; /** @@ -145,18 +141,17 @@ public class TileUtils { "com.android.settings.bg.argb"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify the content provider providing the icon that should be displayed for - * the preference. + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the + * content provider providing the icon that should be displayed for the preference. * - * Icon provided by the content provider overrides any static icon. + * <p>Icon provided by the content provider overrides any static icon. */ public static final String META_DATA_PREFERENCE_ICON_URI = "com.android.settings.icon_uri"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify whether the icon is tintable. This should be a boolean value {@code true} or - * {@code false}, set using {@code android:value} + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify whether + * the icon is tintable. This should be a boolean value {@code true} or {@code false}, set using + * {@code android:value} */ public static final String META_DATA_PREFERENCE_ICON_TINTABLE = "com.android.settings.icon_tintable"; @@ -171,41 +166,36 @@ public class TileUtils { public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify the content provider providing the title text that should be displayed for the - * preference. + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the + * content provider providing the title text that should be displayed for the preference. * - * Title provided by the content provider overrides any static title. + * <p>Title provided by the content provider overrides any static title. */ - public static final String META_DATA_PREFERENCE_TITLE_URI = - "com.android.settings.title_uri"; + public static final String META_DATA_PREFERENCE_TITLE_URI = "com.android.settings.title_uri"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify the summary text that should be displayed for the preference. + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the + * summary text that should be displayed for the preference. */ public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify the content provider providing the summary text that should be displayed for the - * preference. + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the + * content provider providing the summary text that should be displayed for the preference. * - * Summary provided by the content provider overrides any static summary. + * <p>Summary provided by the content provider overrides any static summary. */ public static final String META_DATA_PREFERENCE_SUMMARY_URI = "com.android.settings.summary_uri"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify the content provider providing the switch that should be displayed for the - * preference. + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the + * content provider providing the switch that should be displayed for the preference. * - * This works with {@link #META_DATA_PREFERENCE_KEYHINT} which should also be set in the + * <p>This works with {@link #META_DATA_PREFERENCE_KEYHINT} which should also be set in the * AndroidManifest.xml */ - public static final String META_DATA_PREFERENCE_SWITCH_URI = - "com.android.settings.switch_uri"; + public static final String META_DATA_PREFERENCE_SWITCH_URI = "com.android.settings.switch_uri"; /** * Name of the meta-data item that can be set from the content provider providing the intent @@ -215,8 +205,8 @@ public class TileUtils { "com.android.settings.pending_intent"; /** - * Value for {@link #META_DATA_KEY_PROFILE}. When the device has a managed profile, - * the app will always be run in the primary profile. + * Value for {@link #META_DATA_KEY_PROFILE}. When the device has a managed profile, the app will + * always be run in the primary profile. * * @see #META_DATA_KEY_PROFILE */ @@ -231,11 +221,11 @@ public class TileUtils { public static final String PROFILE_ALL = "all_profiles"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify the profile in which the app should be run when the device has a managed profile. - * The default value is {@link #PROFILE_ALL} which means the user will be presented with a - * dialog to choose the profile. If set to {@link #PROFILE_PRIMARY} the app will always be - * run in the primary profile. + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the + * profile in which the app should be run when the device has a managed profile. The default + * value is {@link #PROFILE_ALL} which means the user will be presented with a dialog to choose + * the profile. If set to {@link #PROFILE_PRIMARY} the app will always be run in the primary + * profile. * * @see #PROFILE_PRIMARY * @see #PROFILE_ALL @@ -243,20 +233,16 @@ public class TileUtils { public static final String META_DATA_KEY_PROFILE = "com.android.settings.profile"; /** - * Name of the meta-data item that should be set in the AndroidManifest.xml - * to specify whether the {@link android.app.Activity} should be launched in a separate task. - * This should be a boolean value {@code true} or {@code false}, set using {@code android:value} + * Name of the meta-data item that should be set in the AndroidManifest.xml to specify whether + * the {@link android.app.Activity} should be launched in a separate task. This should be a + * boolean value {@code true} or {@code false}, set using {@code android:value} */ public static final String META_DATA_NEW_TASK = "com.android.settings.new_task"; - /** - * If the entry should be shown in settings search results. Defaults to true. - */ + /** If the entry should be shown in settings search results. Defaults to true. */ public static final String META_DATA_PREFERENCE_SEARCHABLE = "com.android.settings.searchable"; - /** - * Build a list of DashboardCategory. - */ + /** Build a list of DashboardCategory. */ public static List<DashboardCategory> getCategories(Context context, Map<Pair<String, String>, Tile> cache) { final long startTime = System.currentTimeMillis(); @@ -341,8 +327,8 @@ public class TileUtils { UserHandle user, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles, Intent intent) { final PackageManager pm = context.getPackageManager(); - final List<ResolveInfo> results = pm.queryIntentContentProvidersAsUser(intent, - 0 /* flags */, user.getIdentifier()); + final List<ResolveInfo> results = + pm.queryIntentContentProvidersAsUser(intent, 0 /* flags */, user.getIdentifier()); for (ResolveInfo resolved : results) { if (!resolved.system) { // Do not allow any app to add to settings, only system ones. @@ -403,6 +389,8 @@ public class TileUtils { tile.setMetaData(metaData); } + tile.setGroupKey(metaData.getString(META_DATA_PREFERENCE_GROUP_KEY)); + if (!tile.userHandle.contains(user)) { tile.userHandle.add(user); } @@ -448,15 +436,15 @@ public class TileUtils { /** * Returns the complete uri from the meta data key of the tile. * - * A complete uri should contain at least one path segment and be one of the following types: - * content://authority/method - * content://authority/method/key + * <p>A complete uri should contain at least one path segment and be one of the following types: + * <br>content://authority/method + * <br>content://authority/method/key * - * If the uri from the tile is not complete, build a uri by the default method and the + * <p>If the uri from the tile is not complete, build a uri by the default method and the * preference key. * - * @param tile Tile which contains meta data - * @param metaDataKey Key mapping to the uri in meta data + * @param tile Tile which contains meta data + * @param metaDataKey Key mapping to the uri in meta data * @param defaultMethod Method to be attached to the uri by default if it has no path segment * @return Uri associated with the key */ @@ -501,9 +489,9 @@ public class TileUtils { /** * Gets the icon package name and resource id from content provider. * - * @param context context + * @param context context * @param packageName package name of the target activity - * @param uri URI for the content provider + * @param uri URI for the content provider * @param providerMap Maps URI authorities to providers * @return package name and resource id of the icon specified */ @@ -532,10 +520,10 @@ public class TileUtils { /** * Gets text associated with the input key from the content provider. * - * @param context context - * @param uri URI for the content provider + * @param context context + * @param uri URI for the content provider * @param providerMap Maps URI authorities to providers - * @param key Key mapping to the text in bundle returned by the content provider + * @param key Key mapping to the text in bundle returned by the content provider * @return Text associated with the key, if returned by the content provider */ public static String getTextFromUri(Context context, Uri uri, @@ -547,10 +535,10 @@ public class TileUtils { /** * Gets boolean associated with the input key from the content provider. * - * @param context context - * @param uri URI for the content provider + * @param context context + * @param uri URI for the content provider * @param providerMap Maps URI authorities to providers - * @param key Key mapping to the text in bundle returned by the content provider + * @param key Key mapping to the text in bundle returned by the content provider * @return Boolean associated with the key, if returned by the content provider */ public static boolean getBooleanFromUri(Context context, Uri uri, @@ -562,11 +550,11 @@ public class TileUtils { /** * Puts boolean associated with the input key to the content provider. * - * @param context context - * @param uri URI for the content provider + * @param context context + * @param uri URI for the content provider * @param providerMap Maps URI authorities to providers - * @param key Key mapping to the text in bundle returned by the content provider - * @param value Boolean associated with the key + * @param key Key mapping to the text in bundle returned by the content provider + * @param value Boolean associated with the key * @return Bundle associated with the action, if returned by the content provider */ public static Bundle putBooleanToUriAndGetResult(Context context, Uri uri, diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig index e09ab0086451..89f54d9b3b3b 100644 --- a/packages/SettingsLib/aconfig/settingslib.aconfig +++ b/packages/SettingsLib/aconfig/settingslib.aconfig @@ -36,14 +36,14 @@ flag { name: "enable_le_audio_sharing" namespace: "pixel_cross_device_control" description: "Gates whether to enable LE audio sharing" - bug: "305620450" + bug: "323125723" } flag { name: "enable_le_audio_qr_code_private_broadcast_sharing" namespace: "pixel_cross_device_control" description: "Gates whether to enable LE audio private broadcast sharing via QR code" - bug: "308368124" + bug: "323125723" } flag { @@ -52,3 +52,13 @@ flag { description: "Hide exclusively managed Bluetooth devices in BT settings menu." bug: "324475542" } + +flag { + name: "enable_set_preferred_transport_for_le_audio_device" + namespace: "bluetooth" + description: "Enable setting preferred transport for Le Audio device" + bug: "330581926" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml b/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml index 89d6ac39598b..3ed17247a5e3 100644 --- a/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml +++ b/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml @@ -53,7 +53,7 @@ <EditText android:id="@+id/user_name" android:layout_width="match_parent" - android:layout_height="@dimen/user_name_height_in_user_info_dialog" + android:layout_height="wrap_content" android:layout_gravity="center" android:minWidth="200dp" android:layout_marginStart="6dp" diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index eb3d4afca431..ef77a56e3a78 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktief, net links"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktief, net regs"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktief, links en regs"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiewe (net media), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-battery"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiewe (net media), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>-battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>-battery"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Gekoppelde (steun oudiodeling), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-battery"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Gekoppelde (steun oudiodeling), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>-battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>-battery"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Gekoppelde (steun oudiodeling), linkerkantse <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Gekoppelde (steun oudiodeling), regterkantse <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktief (net media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Steun oudiodeling"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktief (net media), net linkerkant"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktief (net media), net regterkant"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktief (net media), linker- en regterkant"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media-oudio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Foonoproepe"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Lêeroordrag"</string> @@ -335,8 +324,8 @@ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Wanneer hierdie modus geaktiveer is, kan hierdie toestel se MAC-adres verander elke keer wanneer dit aan \'n netwerk koppel waarvoor MAC-verewekansiging geaktiveer is."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Beperk"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Onbeperk"</string> - <string name="select_logd_size_title" msgid="1604578195914595173">"Loggerbuffer se groottes"</string> - <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Kies loggergroottes per logbuffer"</string> + <string name="select_logd_size_title" msgid="1604578195914595173">"Logskepperbuffer se groottes"</string> + <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Kies logskeppergroottes per logbuffer"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Maak logskrywer se aanhoudende berging skoon?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Wanneer ons nie meer monitering met die aanhoudende logskrywer uitvoer nie, word ons vereis om die logskrywerdata wat op jou toestel is, uit te vee."</string> <string name="select_logpersist_title" msgid="447071974007104196">"Berg logskrywerdata aanhoudend op toestel"</string> @@ -411,7 +400,7 @@ <string name="show_non_rect_clip" msgid="7499758654867881817">"Ontfout nie-reghoekige knipbedrywighede"</string> <string name="track_frame_time" msgid="522674651937771106">"Profiel-HWUI-lewering"</string> <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Aktiveer GPU-ontfoutlae"</string> - <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Laat laai van GPU-ontfoutlae vir ontfoutprogramme toe"</string> + <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Laat laai van GPU-ontfoutlae vir ontfoutapps toe"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Aktiveer woordryke verkoperloginskrywing"</string> <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Sluit bykomende toestelspesifieke verkoperloglêers by foutverslae in, wat privaat inligting kan bevat, meer batterykrag kan gebruik, en/of meer berging kan gebruik."</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Vensteranimasieskaal"</string> @@ -514,7 +503,7 @@ <string name="disabled" msgid="8017887509554714950">"Gedeaktiveer"</string> <string name="external_source_trusted" msgid="1146522036773132905">"Toegelaat"</string> <string name="external_source_untrusted" msgid="5037891688911672227">"Nie toegelaat nie"</string> - <string name="install_other_apps" msgid="3232595082023199454">"Installeer onbekende programme"</string> + <string name="install_other_apps" msgid="3232595082023199454">"Installeer onbekende apps"</string> <string name="home" msgid="973834627243661438">"Instellingstuisblad"</string> <string-array name="battery_labels"> <item msgid="7878690469765357158">"0%"</item> @@ -709,7 +698,7 @@ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Verstek"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"Skakel skerm aan"</string> <string name="allow_turn_screen_on" msgid="6194845766392742639">"Laat toe dat die skerm aangeskakel word"</string> - <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Laat ’n program toe om die skerm aan te skakel. As jy toestemming gee, kan die program die skerm enige tyd sonder jou uitdruklike bedoeling aanskakel."</string> + <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Laat ’n app toe om die skerm aan te skakel. As jy toestemming gee, kan die app die skerm enige tyd sonder jou uitdruklike bedoeling aanskakel."</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hou op om <xliff:g id="APP_NAME">%1$s</xliff:g> uit te saai?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"As jy <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitsaai of die uitvoer verander, sal jou huidige uitsending stop"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Saai <xliff:g id="SWITCHAPP">%1$s</xliff:g> uit"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index bda027756952..b590287098ef 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ገቢር፣ ግራ ብቻ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ገቢር፣ ቀኝ ብቻ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ገቢር፣ ግራ እና ቀኝ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"ገቢር (ሚዲያ ብቻ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ገቢር (ሚዲያ ብቻ), ግ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ባትሪ፣ ቀ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"የተገናኘ (የድምፅ ማጋራት ይደግፋል), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"የተገናኘ (የድምፅ ማጋራት ይደግፋል) ግ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ባትሪ፣ ቀ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"የተገናኘ (የድምፅ ማጋራት ይደግፋል)፣ ግራ<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"የተገናኘ (የድምፅ ማጋራት ይደግፋል)፣ ቀኝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ገቢር (ሚዲያ ብቻ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ድምፅ ማጋራትን ይደግፋል"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ገቢር (ሚዲያ ብቻ)፣ ግራ ብቻ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ገቢር (ሚዲያ ብቻ) ቀኝ ብቻ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ገቢር (ሚዲያ ብቻ)፣ ግራ እና ቀኝ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"የማህደረ መረጃ ኦዲዮ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"የስልክ ጥሪዎች"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ፋይል ማስተላለፍ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index ba93f65aa5b6..353df68740ae 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -106,32 +106,21 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"السمّاعة الطبية اليسرى فقط مفعَّلة"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"السمّاعة الطبية اليمنى فقط مفعَّلة"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"السمّاعتان اليسرى واليمنى مفعَّلتان"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"البلوتوث مفعَّل (للوسائط فقط)، مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"البلوتوث مفعَّل (للوسائط فقط)، مستوى الشحن في السماعة اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في السماعة اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة)، مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة)، مستوى الشحن في السماعة اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في السماعة اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة)، مستوى الشحن في السماعة اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة)، مستوى الشحن في السماعة اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"البلوتوث مفعَّل (للوسائط فقط)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"تتوفّر ميزة \"مشاركة الصوت\""</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"السماعة اليسرى فقط مشغَّلة (للوسائط فقط)"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"السماعة اليمنى فقط مشغَّلة (للوسائط فقط)"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"السماعتان اليسرى واليمنى مشغَّلتان (للوسائط فقط)"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"الإعدادات الصوتية للوسائط"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"المكالمات الهاتفية"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"نقل الملف"</string> - <string name="bluetooth_profile_hid" msgid="2969922922664315866">"جهاز الإرسال"</string> + <string name="bluetooth_profile_hid" msgid="2969922922664315866">"جهاز إدخال بيانات"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"الوصول إلى الإنترنت"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"السماح بالوصول إلى جهات الاتصال وسجلّ المكالمات"</string> <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"سيتم استخدام المعلومات لإرسال إشعارات المكالمات وغيرها"</string> @@ -202,8 +191,8 @@ <string name="launch_defaults_some" msgid="3631650616557252926">"تم ضبط بعض الإعدادات التلقائية"</string> <string name="launch_defaults_none" msgid="8049374306261262709">"لم يتم ضبط إعدادات تلقائية"</string> <string name="tts_settings" msgid="8130616705989351312">"إعدادات تحويل النص إلى كلام"</string> - <string name="tts_settings_title" msgid="7602210956640483039">"إخراج النص إلى كلام"</string> - <string name="tts_default_rate_title" msgid="3964187817364304022">"معدل سرعة الكلام"</string> + <string name="tts_settings_title" msgid="7602210956640483039">"الصوت عند تحويل النص إلى كلام"</string> + <string name="tts_default_rate_title" msgid="3964187817364304022">"سرعة الكلام"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعة قول الكلام"</string> <string name="tts_default_pitch_title" msgid="6988592215554485479">"درجة الصوت"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"للتأثير في نبرة الكلام المُرَكَّب"</string> @@ -512,8 +501,8 @@ <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"إعدادات يتحكم فيها المشرف"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"يتحكّم فيه إعداد محظور"</string> <string name="disabled" msgid="8017887509554714950">"غير مفعّل"</string> - <string name="external_source_trusted" msgid="1146522036773132905">"مسموح به"</string> - <string name="external_source_untrusted" msgid="5037891688911672227">"غير مسموح به"</string> + <string name="external_source_trusted" msgid="1146522036773132905">"تطبيق مسموح به"</string> + <string name="external_source_untrusted" msgid="5037891688911672227">"تطبيق غير مسموح به"</string> <string name="install_other_apps" msgid="3232595082023199454">"تثبيت التطبيقات غير المعروفة"</string> <string name="home" msgid="973834627243661438">"الشاشة الرئيسية للإعدادات"</string> <string-array name="battery_labels"> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"المنبّهات والتذكيرات"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"السماح بضبط المنبّهات والتذكيرات"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"المنبّهات والتذكيرات"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات لتنفيذها في الوقت المناسب. ويسمح هذا الإذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من البطارية.\n\nفي حال عدم تفعيل هذا الإذن، لن تعمل المنبهات الحالية والأحداث المستندة إلى الوقت المضبوطة في هذا التطبيق."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات لتنفيذها في الوقت المناسب. ويسمح هذا الإذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من البطارية.\n\nفي حال عدم تفعيل هذا الإذن، لن تعمل المنبهات المضبوطة والأحداث المستندة إلى الوقت المجدولة حاليًا في هذا التطبيق."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"جدول زمني، جدولة، منبّه، تذكير، ساعة"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"تفعيل"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"تفعيل ميزة \"عدم الإزعاج\""</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index ef53fafa6e36..a9ad715b2232 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"কেৱল বাঁওফালৰটো সক্ৰিয় হৈছে"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"কেৱল সোঁফালৰটো সক্ৰিয় হৈছে"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাওঁ আৰু সোঁ দুয়োফালৰ সক্ৰিয় হৈছে"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰী, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰী, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), বাওঁ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), সোঁ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল বাওঁ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল সোঁ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), বাওঁ আৰু সোঁ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"মিডিয়াৰ অডিঅ’"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ফ\'ন কলসমূহ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তৰণ"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index 48c68f41bafd..10ac5fce416f 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, yalnız sol"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, yalnız sağ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, sol və sağ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiv (yalnız media), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiv (yalnız media), Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batareya, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Qoşulub (audio paylaşma dəstəklənir), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Qoşulub (audio paylaşma dəstəklənir), Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batareya, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Qoşulub (audio paylaşma dəstəklənir), sol <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Qoşulub (audio paylaşma dəstəklənir), sağ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (yalnız media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio paylaşma dəstəklənir"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (yalnız media), yalnız sol"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (yalnız media), yalnız sağ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (yalnız media), sol və sağ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefon zəngləri"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl transferi"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 04c6d944ceac..86229e8f2636 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo s leve strane"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, s desne strane"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, s leve i desne strane"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktivan (samo za medije), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktivan (samo za medije), levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Povezan (podržava deljenje zvuka), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Povezan (podržava deljenje zvuka), levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Povezan (podržava deljenje zvuka), levo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Povezan (podržava deljenje zvuka), desno <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivan (samo za medije)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava deljenje zvuka"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivan (samo za medije), samo levo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivan (samo za medije), samo desno"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivan (samo za medije), levo i desno"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk medija"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski pozivi"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index f8c88e67bf5d..680aaa2a4dfa 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Уключана, толькі для левага вуха"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Уключана, толькі для правага вуха"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Уключана, для левага і правага вуха"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Выкарыстоўваецца (толькі для мультымедыя), зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Выкарыстоўваецца (толькі для мультымедыя), зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Падключана (падтрымліваецца абагульванне аўдыя), зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Падключана (падтрымліваецца абагульванне аўдыя), зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Падключана (падтрымліваецца абагульванне аўдыя), зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (левы навушнік)"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Падключана (падтрымліваецца абагульванне аўдыя), зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (правы навушнік)"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Выкарыстоўваецца (толькі для мультымедыя)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Падтрымліваецца абагульванне аўдыя"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Выкарыстоўваецца (толькі для мультымедыя), толькі левы навушнік"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Выкарыстоўваецца (толькі для мультымедыя), толькі правы навушнік"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Выкарыстоўваецца (толькі для мультымедыя), левы і правы навушнікі"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Аўдыя медыяфайлаў"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Тэлефонныя выклікі"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Перадача файлаў"</string> diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml index 9388e660e840..31d24c1f7d74 100644 --- a/packages/SettingsLib/res/values-bg/arrays.xml +++ b/packages/SettingsLib/res/values-bg/arrays.xml @@ -188,7 +188,7 @@ <item msgid="409235464399258501">"Изключено"</item> <item msgid="4195153527464162486">"Рег. буфер – 64 КБ"</item> <item msgid="7464037639415220106">"Рег. буфер – 256 КБ"</item> - <item msgid="8539423820514360724">"Рег. буфер – 1 МБ"</item> + <item msgid="8539423820514360724">"Рег. буфер – 1 млн."</item> <item msgid="1984761927103140651">"Рег. буфер – 4 МБ"</item> <item msgid="2983219471251787208">"Регистрационен буфер – 8 МБ"</item> </string-array> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 0457f10bd5ab..1cfe768fbd57 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -106,35 +106,24 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно – само лявото"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно – само дясното"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно – лявото и дясното"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Активно (само за мултимедия), батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Активно (само за мултимедия), Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Свързано (поддържа споделяне на звука), батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Свързано (поддържа споделяне на звука), Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Свързано (поддържа споделяне на звука), лява – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Свързано (поддържа споделяне на звука), дясна – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само за мултимедия)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддържа споделяне на звука"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само за мултимедия), само лявата"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (само за мултимедия), само дясната"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (само за мултимедия), лявата и дясната"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Мултимедийно аудио"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонни обаждания"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Прехвърляне на файл"</string> <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Входно устройство"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Достъп до интернет"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Разреш. на достъпа до контактите и историята на обажд."</string> - <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Информацията ще се ползва за съобщения чрез обаждания и др."</string> + <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Информацията ще се ползва за обявяване на обажданията и др."</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Споделяне на връзката с интернет"</string> <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстови съобщения"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Достъп до SIM картата"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index e9367ff44c63..6e5135a9dfe0 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"শুধুমাত্র বাঁদিকের হিয়ারিং এড অ্যাক্টিভ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"শুধুমাত্র ডানদিকের হিয়ারিং এড অ্যাক্টিভ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাঁ ও ডানদিকের হিয়ারিং এড, অ্যাক্টিভ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"চালু আছে (শুধুমাত্র মিডিয়া), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ব্যাটারি, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ব্যাটারি, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), বাঁদিক <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), ডানদিক <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"চালু আছে (শুধুমাত্র মিডিয়া)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিও শেয়ারিংয়ে কাজ করে"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র বাঁদিক"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র ডানদিক"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক ও ডানদিক"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"মিডিয়া অডিও"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ফোন কল"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তর"</string> @@ -537,7 +526,7 @@ <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"সিস্টেমের ভাষাগুলি ব্যবহার করুন"</string> <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> জন্য সেটিংস খুলতে ব্যর্থ হয়েছে"</string> <string name="ime_security_warning" msgid="6547562217880551450">"এই ইনপুট পদ্ধতিটি হয়ত পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ আপনার টাইপ করা সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> অ্যাপ থেকে এসেছে। এই ইনপুট পদ্ধতিটি ব্যবহার করবেন?"</string> - <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"দ্রষ্টব্য: পুনরায় চালু করার পরে, আপনি আপনার ফোন আনলক না করা পর্যন্ত এই অ্যাপটিকে চালু করতে পারবেন না"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"দ্রষ্টব্য: রিবুট করার পরে, আপনি আপনার ফোন আনলক না করা পর্যন্ত এই অ্যাপটিকে চালু করতে পারবেন না"</string> <string name="ims_reg_title" msgid="8197592958123671062">"IMS রেজিস্ট্রেশনের স্থিতি"</string> <string name="ims_reg_status_registered" msgid="884916398194885457">"রেজিস্টার করা"</string> <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"রেজিস্টার করা নয়"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 7fb522552c94..d991bd6f7cc9 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevi"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desni"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevi i desni"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktivno (samo za medijski sadržaj), baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktivno (samo za medijski sadržaj), baterija L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, baterija D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Povezano (podržava dijeljenje zvuka), baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Povezano (podržava dijeljenje zvuka), baterija L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, baterija D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Povezano (podržava dijeljenje zvuka), lijevo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Povezano (podržava dijeljenje zvuka), desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo za medijski sadržaj)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava dijeljenje zvuka"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo za medijski sadržaj), samo lijevo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo za medijski sadržaj), samo desno"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo za medijski sadržaj), lijevo i desno"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk medija"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski pozivi"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenošenje fajla"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 18da1bec6f34..738871588541 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actiu, només l\'esquerre"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actiu, només el dret"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actiu, esquerre i dret"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Actiu (només contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Actiu (només contingut multimèdia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connectat (admet compartició d\'àudio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connectat (admet compartició d\'àudio), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connectat (admet compartició d\'àudio), esquerre <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connectat (admet compartició d\'àudio), dret <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actiu (només contingut multimèdia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admet compartició d\'àudio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actiu (només contingut multimèdia), només esquerre"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actiu (només contingut multimèdia), només dret"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actiu (només contingut multimèdia), esquerre i dret"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Àudio multimèdia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Trucades telefòniques"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferència de fitxers"</string> @@ -487,7 +476,7 @@ <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> segons l\'ús que en facis"</string> <string name="power_discharge_by" msgid="4113180890060388350">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_discharge_by_only" msgid="92545648425937000">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_discharge_by_only_short" msgid="5883041507426914446">"fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"És possible que la bateria s\'esgoti a les <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> @@ -514,7 +503,7 @@ <string name="disabled" msgid="8017887509554714950">"Desactivat"</string> <string name="external_source_trusted" msgid="1146522036773132905">"Amb permís"</string> <string name="external_source_untrusted" msgid="5037891688911672227">"Sense permís"</string> - <string name="install_other_apps" msgid="3232595082023199454">"Instal·lar aplicacions desconegudes"</string> + <string name="install_other_apps" msgid="3232595082023199454">"Instal·la aplicacions desconegudes"</string> <string name="home" msgid="973834627243661438">"Pàgina d\'inici de configuració"</string> <string-array name="battery_labels"> <item msgid="7878690469765357158">"0%"</item> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index f4bfe505c437..e09d303f7c5e 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivní, pouze levé"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivní, pouze pravé"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivní, levé a pravé"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktivní (pouze média), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktivní (pouze média), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Připojeno (podporuje sdílení zvuku), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Připojeno (podporuje sdílení zvuku), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Připojeno (podporuje sdílení zvuku), levé <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Připojeno (podporuje sdílení zvuku), pravé <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivní (pouze média)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje sdílení zvuku"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivní (pouze média), pouze levé"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivní (pouze média), pouze pravé"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivní (pouze média), levé a pravé"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk médií"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonní hovory"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Přenos souborů"</string> @@ -709,7 +698,7 @@ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Výchozí"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"Zapínání obrazovky"</string> <string name="allow_turn_screen_on" msgid="6194845766392742639">"Povolit zapínání obrazovky"</string> - <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Povolte aplikaci zapínat obrazovku. Pokud aplikace bude mít toto oprávnění, může kdykoli zapnout obrazovku bez požadavku uživatele."</string> + <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Aplikaci můžete povolit zapínat obrazovku. Pokud bude mít toto oprávnění, může kdykoli zapnout obrazovku bez požadavku uživatele."</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zastavit vysílání v aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Pokud budete vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g> nebo změníte výstup, aktuální vysílání se zastaví"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index d51f8b9fb818..09902b856c96 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, kun venstre"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, kun højre"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og højre"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiveret (kun for medier), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiveret (kun for medier), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Forbundet (understøtter lyddeling), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Forbundet (understøtter lyddeling), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Forbundet (understøtter lyddeling), venstre <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Forbundet (understøtter lyddeling), højre <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiveret (kun for medier)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Understøtter lyddeling"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiveret (kun for medier), kun venstre"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiveret (kun for medier), kun højre"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiveret (kun for medier), venstre og højre"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medielyd"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonopkald"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverførsel"</string> @@ -709,7 +698,7 @@ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standard"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"Aktivér skærmen"</string> <string name="allow_turn_screen_on" msgid="6194845766392742639">"Tillad aktivering af skærmen"</string> - <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Tillad, at en app aktiverer skærmen. Hvis du giver denne tilladelse, kan appen til enhver tid aktiverer skærmen, uden at du eksplicit har bedt om det."</string> + <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Tillad, at en app aktiverer skærmen. Hvis du giver denne tilladelse, kan appen til enhver tid aktivere skærmen, uden at du eksplicit har bedt om det."</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop udsendelsen <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Hvis du udsender <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller skifter output, stopper din aktuelle udsendelse"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Udsend <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 08ca14a248e8..d542d0fc9ee8 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, nur links"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, nur rechts"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, links und rechts"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiv (nur Medien), Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiv (nur Medien), Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Verbunden (unterstützt Audiofreigabe), Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Verbunden (unterstützt Audiofreigabe), Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Verbunden (unterstützt Audiofreigabe), Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Verbunden (unterstützt Audiofreigabe), Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (nur Medien)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Unterstützt Audiofreigabe"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (nur Medien), nur links"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (nur Medien), nur rechts"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (nur Medien), links und rechts"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medien-Audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonanrufe"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dateiübertragung"</string> @@ -472,7 +461,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Die Farbkorrektur kann nützlich sein, wenn du:<br/> <ol> <li>&nbsp;Farben noch genauer sehen möchtest</li> <li>&nbsp;bestimmte Farben entfernen möchtest, um dich besser zu konzentrieren</li> </ol>"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Die Farbkorrektur kann nützlich sein, wenn du:<br/> <ol> <li>&nbsp;Farben noch genauer sehen möchtest</li> <li>&nbsp;Bestimmte Farben entfernen möchtest, um dich besser zu konzentrieren</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladevorgang zum Schutz des Akkus angehalten"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index c38034a585dc..af21647ca8fc 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ενεργό, μόνο το αριστερό"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ενεργό, μόνο το δεξί"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ενεργό, αριστερό και δεξί"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Ενεργό (μόνο για μέσα), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Ενεργό (μόνο για μέσα), Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> μπαταρία, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου), Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> μπαταρία, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου), αριστερό <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου), δεξί <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ενεργό (μόνο για μέσα)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Υποστηρίζει κοινή χρήση ήχου"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ενεργό (μόνο για μέσα), μόνο αριστερό"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ενεργό (μόνο για μέσα), μόνο δεξί"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ενεργό (μόνο για μέσα), αριστερό και δεξί"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Ήχος πολυμέσων"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Τηλεφωνικές κλήσεις"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Μεταφορά αρχείου"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index c787c6360cb0..93c17bde9550 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Active (media only), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Active (media only), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connected (supports audio sharing), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connected (supports audio sharing), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connected (supports audio sharing), left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connected (supports audio sharing), right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Phone calls"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index c787c6360cb0..93c17bde9550 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Active (media only), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Active (media only), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connected (supports audio sharing), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connected (supports audio sharing), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connected (supports audio sharing), left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connected (supports audio sharing), right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Phone calls"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index c787c6360cb0..93c17bde9550 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Active (media only), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Active (media only), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connected (supports audio sharing), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connected (supports audio sharing), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connected (supports audio sharing), left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connected (supports audio sharing), right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Phone calls"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml index be125725a53c..4d4d7c9be0e3 100644 --- a/packages/SettingsLib/res/values-es-rUS/arrays.xml +++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml @@ -186,10 +186,10 @@ </string-array> <string-array name="select_logd_size_summaries"> <item msgid="409235464399258501">"Desactivado"</item> - <item msgid="4195153527464162486">"64 K/búfer registro"</item> - <item msgid="7464037639415220106">"256 K/búfer registro"</item> - <item msgid="8539423820514360724">"1 M/búfer registro"</item> - <item msgid="1984761927103140651">"4 M/búfer registro"</item> + <item msgid="4195153527464162486">"64 K/búfer de registro"</item> + <item msgid="7464037639415220106">"256 K/búfer de registro"</item> + <item msgid="8539423820514360724">"1 M/búfer de registro"</item> + <item msgid="1984761927103140651">"4 M/búfer de registro"</item> <item msgid="2983219471251787208">"8 M/búfer de registro"</item> </string-array> <string-array name="select_logpersist_titles"> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 1903c6be8125..682f7322f8d9 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo; solo oído izquierdo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo; solo oído derecho"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo; oídos izquierdo y derecho"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Activo (solo para contenido multimedia); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Activo (solo para contenido multimedia); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Conectado (admite el uso compartido de audio); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Conectado (admite el uso compartido de audio); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Conectado (admite el uso compartido de audio); izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Conectado (admite el uso compartido de audio); derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo para contenido multimedia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admite el uso compartido de audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo para contenido multimedia); solo izquierdo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (solo para contenido multimedia); solo derecho"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (solo para contenido multimedia); izquierdo y derecho"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimedia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Llamadas telefónicas"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string> @@ -335,7 +324,7 @@ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Si este modo está habilitado, es posible que la dirección MAC del dispositivo cambie cada vez que se conecte a una red que tenga habilitada la aleatorización de MAC."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"De uso medido"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Sin tarifa plana"</string> - <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaños de búfer de Logger"</string> + <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaños de los búferes de registro"</string> <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Selecciona el tamaño del Logger por búfer"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"¿Borrar el almacenamiento persistente del registrador?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Cuando ya no usamos el registrador persistente para monitorear, debemos borrar los datos que almacena el registrador en tu dispositivo."</string> @@ -411,7 +400,7 @@ <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operaciones de recorte no rectangulares"</string> <string name="track_frame_time" msgid="522674651937771106">"Perfil procesamiento HWUI"</string> <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Habilitar depuración GPU"</string> - <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite capas de GPU para apps de depuración"</string> + <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite cargar capas de depuración de GPU para apps de depuración"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Habilitar registro detallado"</string> <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Incluye otros registros de proveedor específicos del dispositivo en los informes de errores, que podrían contener información privada, consumir más batería o usar más espacio de almacenamiento."</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animación de ventana"</string> @@ -471,7 +460,7 @@ <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteronomalía (rojo-verde)"</string> <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string> - <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string> + <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de colores"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La corrección de colores puede ser útil cuando quieres hacer lo siguiente:<br/> <ol> <li>&nbsp;Ver los colores con mayor precisión</li> <li>&nbsp;Quitar colores para concentrarte</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 29b29b6b5e72..f3a23f05c432 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -106,35 +106,24 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo, solo oído izquierdo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo, solo oído derecho"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo, oídos izquierdo y derecho"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Activo (solo multimedia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Activo (solo multimedia), izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería, derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Conectado (permite compartir audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Conectado (permite compartir audio), izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería, derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Conectado (permite compartir audio), izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Conectado (permite compartir audio), derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo multimedia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Permite compartir audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo multimedia), solo el izquierdo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (solo multimedia), solo el derecho"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (solo multimedia), izquierdo y derecho"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimedia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Llamadas de teléfono"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string> <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Acceso a contactos e historial de llamadas"</string> - <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"La información se utilizará para avisos de llamada y más"</string> + <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"La información se usará para avisos de llamada y más"</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartir conexión a Internet"</string> <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensajes de texto"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a tarjeta SIM"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 9f77bd9d2008..8ad05d8affe2 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivne, ainult vasak"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivne, ainult parem"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivne, vasak ja parem"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiivne (ainult meedia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> aku täituvus"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiivne (ainult meedia), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> aku täituvus, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> aku täituvus"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Ühendatud (toetab heli jagamist), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> aku täituvus"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Ühendatud (toetab heli jagamist), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> aku täituvus, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> aku täituvus"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Ühendatud (toetab heli jagamist), vasak <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Ühendatud (toetab heli jagamist), parem <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivne (ainult meedia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Toetab heli jagamist"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivne (ainult meedia), ainult vasak"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiivne (ainult meedia), ainult parem"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiivne (ainult meedia), vasak ja parem"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Meediaheli"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonikõned"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failiedastus"</string> @@ -505,7 +494,7 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Juhtmevaba laadimine"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laadimine"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei lae"</string> - <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Ühendatud, kuid ei laadita"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Ühendatud, kuid ei laeta"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Laetud"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Täielikult laetud"</string> <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Laadimine on ootele pandud"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 05f3ac713c6e..f43d6175be2e 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -106,32 +106,21 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerrekoa soilik"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuinekoa soilik"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, ezkerreko eta eskuineko audifonoak"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktibo (multimedia-edukia soilik); bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktibo (multimedia-edukia soilik); L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Konektatuta (audioa partekatzeko eginbidea onartzen du); bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Konektatuta (audioa partekatzeko eginbidea onartzen du); L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Konektatuta (audioa partekatzeko eginbidea onartzen du); ezkerreko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Konektatuta (audioa partekatzeko eginbidea onartzen du); eskuineko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (multimedia-edukia soilik)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audioa partekatzeko eginbidea onartzen du"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (multimedia-edukia soilik); ezkerreko aldea soilik"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktibo (multimedia-edukia soilik); eskuineko aldea soilik"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktibo (multimedia-edukia soilik); ezkerreko eta eskuineko aldeak"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Euskarriaren audioa"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefono-deiak"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fitxategi-transferentzia"</string> - <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sarrerako gailua"</string> + <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sarrera-gailua"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneteko konexioa"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Eman kontaktuak eta deien historia erabiltzeko baimena"</string> <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Deiak iragartzeko eta abarrerako erabiliko da informazioa"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 658fb0fcca31..c404f54d0155 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، فقط چپ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، فقط راست"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، چپ و راست"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"فعال (فقط رسانه)، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> باتری"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"فعال (فقط رسانه)، چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> باتری، راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> باتری"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"متصل (از اشتراک صدا پشتیبانی میکند)، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> باتری"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"متصل (از اشتراک صدا پشتیبانی میکند)، چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> باتری، راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> باتری"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"متصل (از اشتراک صدا پشتیبانی میکند)، چپ<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"متصل (از اشتراک صدا پشتیبانی میکند)، راست <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (فقط رسانه)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"از اشتراک صدا پشتیبانی میکند"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (فقط رسانه)، فقط چپ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"فعال (فقط رسانه)، فقط راست"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"فعال (فقط رسانه)، چپ و راست"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"رسانه صوتی"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"تماسهای تلفنی"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"انتقال فایل"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 14b1701e7d9b..6c52bf25cddc 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivinen, vain vasen"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivinen, vain oikea"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivinen, vasen ja oikea"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiivinen (vain media), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiivinen (vain media), vasen: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> virtaa, oikea: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Yhdistetty (tukee audionjakoa), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Yhdistetty (tukee audionjakoa), vasen: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> virtaa, oikea: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Yhdistetty (tukee audionjakoa), vasen: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Yhdistetty (tukee audionjakoa), oikea: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivinen (vain media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Tukee audionjakoa"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivinen (vain media), vain vasen"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiivinen (vain media), vain oikea"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiivinen (vain media), vasen ja oikea"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Median ääni"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Puhelut"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Tiedostonsiirto"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index e4ae14557949..3b2a1855cedb 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche seulement"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, droite seulement"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, gauche et droite"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Actif (contenu multimédia uniquement), pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Actif (contenu multimédia uniquement), G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connecté (prise en charge du partage audio), pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connecté (prise en charge du partage audio), G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connecté (prise en charge du partage audio), côté gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connecté (prise en charge du partage audio), côté droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actif (contenu multimédia uniquement)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Prise en charge du partage audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actif (contenu multimédia uniquement), côté gauche seulement"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actif (contenu multimédia uniquement), côté droit seulement"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actif (contenu multimédia uniquement), côtés gauche et droit"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Paramètres audio du support"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Appels téléphoniques"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichier"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 09b40acef578..5be267d251a2 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche uniquement"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actif, droit uniquement"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actifs, gauche et droit"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Activé (multimédia uniquement), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Activé (multimédia uniquement), gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connecté (compatible avec le partage audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connecté (compatible avec le partage audio), gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connecté (compatible avec le partage audio), gauche <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connecté (compatible avec le partage audio), droit <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activé (multimédia uniquement)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible avec le partage audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activé (multimédia uniquement), gauche uniquement"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activé (multimédia uniquement), droit uniquement"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activé (multimédia uniquement), gauche et droit"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimédia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Appels téléphoniques"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichiers"</string> @@ -339,7 +328,7 @@ <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Tailles enreg. par tampon journal"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Effacer l\'espace de stockage persistant de l\'enregistreur ?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Lorsque nous n\'effectuons plus de suivi avec l\'enregistreur persistant, nous sommes tenus d\'effacer les données associées à ce dernier qui sont stockées sur votre appareil."</string> - <string name="select_logpersist_title" msgid="447071974007104196">"Stocker données enregistreur en permanence sur appareil"</string> + <string name="select_logpersist_title" msgid="447071974007104196">"Stocker données journaux sur appareil de manière persistante"</string> <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Sélectionner les mémoires tampon journal à stocker en permanence sur l\'appareil"</string> <string name="select_usb_configuration_title" msgid="6339801314922294586">"Sélectionner une configuration USB"</string> <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Sélectionner une configuration USB"</string> @@ -718,7 +707,7 @@ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activer les animations système pour la prévisualisation du Retour"</string> <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ce paramètre active les animations système pour la prévisualisation du geste de retour. Pour cela, enableOnBackInvokedCallback doit être défini sur \"True\" dans le fichier manifeste de chaque appli."</string> <string name="font_scale_percentage" msgid="2624057443622817886">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> - <string name="not_specified" msgid="5423502443185110328">"Non défini"</string> + <string name="not_specified" msgid="5423502443185110328">"Non personnalisé"</string> <string name="neuter" msgid="2075249330106127310">"Neutre"</string> <string name="feminine" msgid="1529155595310784757">"Féminin"</string> <string name="masculine" msgid="4653978041013996303">"Masculin"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index db40500d4e00..1dc9ec41e089 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo (só o esquerdo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo (só o dereito)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activos (o esquerdo e o dereito)"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Activo (só contido multimedia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Activo (só contido multimedia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Conectado (compatible con audio compartido), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Conectado (compatible con audio compartido), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Conectado (compatible con audio compartido), esquerdo<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Conectado (compatible con audio compartido), dereito <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (só contido multimedia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible con audio compartido"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (só contido multimedia), só esquerdo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (só contido multimedia), só dereito"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (só contido multimedia), esquerdo e dereito"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimedia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefónicas"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de ficheiros"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index c1eeca5c7cc0..9127301a22eb 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"સક્રિય, માત્ર ડાબું"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"સક્રિય, માત્ર જમણું"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"સક્રિય, ડાબું અને જમણું બન્ને"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"સક્રિય છે (માત્ર મીડિયા માટે), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"સક્રિય છે (માત્ર મીડિયા માટે), ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> બૅટરી, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"કનેક્ટેડ છે (ઑડિયો શેરિંગને સપોર્ટ કરે છે), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"કનેક્ટેડ છે (ઑડિયો શેરિંગને સપોર્ટ કરે છે), ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> બૅટરી, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"કનેક્ટેડ છે (ઑડિયો શેરિંગને સપોર્ટ કરે છે), ડાબી બાજુ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"કનેક્ટેડ છે (ઑડિયો શેરિંગને સપોર્ટ કરે છે), જમણી બાજુ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"સક્રિય છે (માત્ર મીડિયા માટે)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ઑડિયો શેરિંગને સપોર્ટ કરે છે"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર ડાબી બાજુ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર જમણી બાજુ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"સક્રિય છે (માત્ર મીડિયા માટે), ડાબી અને જમણી બાજુ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"મીડિયા ઑડિયો"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ફોન કૉલ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ફાઇલ સ્થાનાંતરણ"</string> @@ -335,7 +324,7 @@ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"આ મોડ ચાલુ કરેલો હોય ત્યારે MAC રેન્ડમાઇઝેશન ચાલુ કરેલું હોય તેવા નેટવર્ક સાથે આ ડિવાઇસ કનેક્ટ થશે, ત્યારે દર વખતે તેનું MAC ઍડ્રેસ બદલાય તેવું બની શકે છે."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"મીટર કરેલું"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"મીટર ન કરેલ"</string> - <string name="select_logd_size_title" msgid="1604578195914595173">"લોગર બફર કદ"</string> + <string name="select_logd_size_title" msgid="1604578195914595173">"લૉગર બફર કદ"</string> <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"લૉગર નિરંતર સ્ટોરેજ સાફ કરીએ?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"જ્યારે અમે હવે નિરંતર લૉગર સાથે મોનીટર કરતાં નથી, તો તમારા ઉપકરણ પર રહેલો લૉગર ડેટા કાઢી નાખવાની જરૂર છે."</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index a5b3c88e1606..3f956e36db5f 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"सिर्फ़ बाईं तरफ़ वाला चालू है"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सिर्फ़ दाईं तरफ़ वाला चालू है"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"बाईं और दाईं तरफ़ वाला चालू है"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"चालू है (सिर्फ़ मीडिया के लिए), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"चालू है (सिर्फ़ मीडिया के लिए), बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बैटरी, दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है), बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बैटरी, दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है), बायां हेडसेट<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है), दायां हेडसेट <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"चालू है (सिर्फ़ मीडिया के लिए)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडियो शेयर करने की सुविधा काम करती है"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ बाएं कान की मशीन"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ दाएं कान की मशीन"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"चालू है (सिर्फ़ मीडिया के लिए), बाएं और दाएं कान की मशीन"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मीडिया ऑडियो"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"फ़ोन कॉल"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फ़ाइल स्थानांतरण"</string> @@ -537,7 +526,7 @@ <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिस्टम की भाषाओं का इस्तेमाल करें"</string> <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> के लिए सेटिंग खोलने में विफल रहा"</string> <string name="ime_security_warning" msgid="6547562217880551450">"इनपुट का यह तरीका, आपके पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा के साथ-साथ उस सभी डेटा को इकट्ठा कर सकता है जिसे आप लिखते हैं. यह <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ऐप्लिकेशन से आता है. इनपुट के इस तरीके का इस्तेमाल करें?"</string> - <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"नोट: पुनः बूट करने के बाद, यह ऐप्लिकेशन तब तक शुरू नहीं हो सकता है जब तक कि आप अपना फ़ोन अनलॉक ना कर लें"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ध्यान दें: डिवाइस को फिर से चालू करने पर, यह ऐप्लिकेशन तब तक शुरू नहीं होगा, जब तक आप अपना फ़ोन अनलॉक न कर लें"</string> <string name="ims_reg_title" msgid="8197592958123671062">"IMS रजिस्ट्रेशन की स्थिति"</string> <string name="ims_reg_status_registered" msgid="884916398194885457">"रजिस्टर है"</string> <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"रजिस्टर नहीं है"</string> @@ -616,7 +605,7 @@ <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबंधित प्रोफ़ाइल"</string> <string name="user_add_user_title" msgid="5457079143694924885">"नया उपयोगकर्ता जोड़ें?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"नए उपयोगकर्ता जोड़कर इस डिवाइस को दूसरे लोगों के साथ शेयर किया जा सकता है. हर उपयोगकर्ता के पास अपनी जगह होती है, जिसमें वे ऐप्लिकेशन, वॉलपेपर, और दूसरी चीज़ों में मनमुताबिक बदलाव कर सकते हैं. उपयोगकर्ता, वाई-फ़ाई जैसी डिवाइस सेटिंग में भी बदलाव कर सकते हैं. इसका असर हर किसी पर पड़ता है.\n\nजब किसी नए उपयोगकर्ता को जोड़ा जाता है, तो उसे अपनी जगह सेट अप करनी होती है.\n\nकोई भी उपयोगकर्ता, दूसरे सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है. ऐसा भी हो सकता है कि सुलभता सेटिंग और सेवाएं नए उपयोगकर्ता को ट्रांसफ़र न हो पाएं."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"कोई नया उपयोगकर्ता जोड़ने पर, उसे अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"जब किसी नए उपयोगकर्ता को जोड़ा जाता है, तो उस व्यक्ति को डिवाइस में अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string> <string name="user_grant_admin_title" msgid="5157031020083343984">"क्या इस व्यक्ति को एडमिन बनाना है?"</string> <string name="user_grant_admin_message" msgid="1673791931033486709">"एडमिन के पास अन्य लोगों के मुकाबले खास अधिकार होते हैं. एडमिन के पास ये अधिकार होते हैं: सभी लोगों को मैनेज करना, इस डिवाइस को अपडेट या रीसेट करना, सेटिंग में बदलाव करना, इंस्टॉल किए गए सभी ऐप्लिकेशन देखना, और अन्य लोगों को एडमिन के खास अधिकार देना या उन्हें वापस लेना."</string> <string name="user_grant_admin_button" msgid="5441486731331725756">"एडमिन बनाएं"</string> @@ -638,7 +627,7 @@ <string name="add_user_failed" msgid="4809887794313944872">"नया उपयोगकर्ता जोड़ा नहीं जा सका"</string> <string name="add_guest_failed" msgid="8074548434469843443">"नया मेहमान खाता नहीं बनाया जा सका"</string> <string name="user_nickname" msgid="262624187455825083">"निकनेम"</string> - <string name="edit_user_info_message" msgid="6677556031419002895">"आपकी चुनी गई फ़ोटो और नाम, उन सभी लोगों को दिखेगा जो इस डिवाइस का इस्तेमाल करते हैं."</string> + <string name="edit_user_info_message" msgid="6677556031419002895">"आपका नाम और चुनी गई फ़ोटो, इस डिवाइस का इस्तेमाल करने वाले हर व्यक्ति को दिखेगी."</string> <string name="user_add_user" msgid="7876449291500212468">"उपयोगकर्ता जोड़ें"</string> <string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान को हटाएं"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index a504c9a010bb..fcac2c853a43 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevo i desno"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktivno (samo medijski sadržaji), razina baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktivno (samo medijski sadržaji), L: razina baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: razina baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Povezano (podržava zajedničko slušanje), razina baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Povezano (podržava zajedničko slušanje), L: razina baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: razina baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Povezano (podržava zajedničko slušanje), lijeva <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Povezano (podržava zajedničko slušanje), desna <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo medijski sadržaji)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava zajedničko slušanje"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo medijski sadržaji), samo lijeva"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo medijski sadržaji), samo desna"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo medijski sadržaji), lijeva i desna"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk medija"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski pozivi"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prijenos datoteke"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 3838d7d078f8..5cf57963b68a 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktív, csak bal"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktív, csak jobb"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktív, bal és jobb"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktív (csak médiatartalom lejátszása), akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktív (csak médiatartalom lejátszása), bal eszköz akkumulátorának töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, jobb eszköz akkumulátorának töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Csatlakoztatva (támogatja a hang megosztását), akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Csatlakoztatva (támogatja a hang megosztását), bal eszköz akkumulátorának töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, jobb eszköz akkumulátorának töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Csatlakoztatva (támogatja a hang megosztását), bal eszköz akkumulátorának töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Csatlakoztatva (támogatja a hang megosztását), jobb eszköz akkumulátorának töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktív (csak médiatartalom lejátszása)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Támogatja a hang megosztását"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktív (csak médiatartalom lejátszása), csak a bal"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktív (csak médiatartalom lejátszása), csak a jobb"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktív (csak médiatartalom lejátszása), bal és jobb"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Médiahang"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonhívások"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fájlátvitel"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 00691758b6a3..327c048944f3 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ակտիվ, միայն ձախ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ակտիվ, միայն աջ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ակտիվ, ձախ և աջ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Ակտիվ է (միայն մեդիա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Ակտիվ է (միայն մեդիա), Ձ՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Ա՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Միացված է (աջակցում է աուդիոյի փոխանցում), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Միացված է (աջակցում է աուդիոյի փոխանցում), Ձ՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Ա՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Միացված է (աջակցում է աուդիոյի փոխանցում), ձախ՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Միացված է (աջակցում է աուդիոյի փոխանցում), աջ՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ակտիվ է (միայն մեդիա)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Աջակցում է աուդիոյի փոխանցում"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ակտիվ է (միայն մեդիա), միայն ձախ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ակտիվ է (միայն մեդիա), միայն աջ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ակտիվ է (միայն մեդիա), աջ և ձախ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Մեդիա աուդիո"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Հեռախոսազանգեր"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Ֆայլերի փոխանցում"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 6254f7bd72ba..1677985518b0 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -106,32 +106,21 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, hanya kiri"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, hanya kanan"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktif (hanya media), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktif (hanya media), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterai, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterai"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Terhubung (mendukung berbagi audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Terhubung (mendukung berbagi audio), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterai, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterai"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Terhubung (mendukung berbagi audio), kiri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Terhubung (mendukung berbagi audio), kanan <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (hanya media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mendukung berbagi audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (hanya media), hanya kiri"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktif (hanya media), hanya kanan"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktif (hanya media), kiri dan kanan"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio media"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Panggilan telepon"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer file"</string> - <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Perangkat masukan"</string> + <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Perangkat input"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Izinkan akses ke kontak dan histori panggilan"</string> <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Info akan digunakan untuk pengumuman panggilan dan lain-lain"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm dan pengingat"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Izinkan menyetel alarm dan pengingat"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm & pengingat"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Mengizinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadwal, alarm, pengingat, jam"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktifkan"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktifkan mode Jangan Ganggu"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 0f57670d04f3..f4afdb523945 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Virkt, aðeins vinstra"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Virkt, aðeins hægra"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Virkt, vinstra og hægra"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Virkt (eingöngu margmiðlunarefni), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlaða"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Virkt (eingöngu margmiðlunarefni), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> rafhlaða, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlaða"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Tengt (styður hljóðdeilingu), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlaða"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Tengt (styður hljóðdeilingu), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> rafhlaða, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlaða"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Tengt (styður hljóðdeilingu), vinstri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Tengt (styður hljóðdeilingu), hægri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Virkt (eingöngu margmiðlunarefni)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Styður hljóðdeilingu"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Virkt (eingöngu margmiðlunarefni), eingöngu vinstri"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Virkt (eingöngu margmiðlunarefni), eingöngu hægri"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Virkt (eingöngu margmiðlunarefni), vinstri og hægri"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Hljóð efnis"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Símtöl"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Skráaflutningur"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 950237400d55..8b1132543c07 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Attiva, solo sinistra"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Attiva, solo destra"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Attivo, destra e sinistra"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Attivo (solo contenuti multimediali), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Attivo (solo contenuti multimediali), S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connesso (supporta la condivisione audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connesso (supporta la condivisione audio), S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connesso (supporta la condivisione audio), sinistro <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connesso (supporta la condivisione audio), destro <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Attivo (solo contenuti multimediali)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supporta la condivisione audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Attivo (solo contenuti multimediali), solo sinistro"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Attivo (solo contenuti multimediali), solo destro"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Attivo (solo contenuti multimediali), sinistro e destro"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimediale"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonate"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Trasferimento file"</string> @@ -167,7 +156,7 @@ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Annulla"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"L\'accoppiamento consente l\'accesso ai tuoi contatti e alla cronologia chiamate quando i dispositivi sono connessi."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Impossibile eseguire l\'accoppiamento con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Impossibile eseguire l\'accoppiamento con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. La password o il PIN sono errati."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Impossibile eseguire l\'accoppiamento con <xliff:g id="DEVICE_NAME">%1$s</xliff:g> perché la passkey o il PIN sono errati."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Impossibile comunicare con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Accoppiamento rifiutato da <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computer"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index dea8ca361e99..7fd38b3ad7df 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -106,32 +106,21 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"פועל: שמאל בלבד"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"פועל: ימין בלבד"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"פועל: ימין ושמאל"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"פעיל (מדיה בלבד), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> סוללה"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"פעיל (מדיה בלבד), שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> סוללה, ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> סוללה"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"מחובר (תמיכה בשיתוף אודיו), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> סוללה"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"מחובר (תמיכה בשיתוף אודיו), שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> סוללה, ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> סוללה"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"מחובר (תמיכה בשיתוף אודיו), שמאל <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"מחובר (תמיכה בשיתוף אודיו), ימין <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"פעיל (מדיה בלבד)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"תמיכה בשיתוף אודיו"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"פעיל (מדיה בלבד), שמאל בלבד"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"פעיל (מדיה בלבד), ימין בלבד"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"פעיל (מדיה בלבד), שמאל וימין"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"אודיו של מדיה"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"שיחות טלפון"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"העברת קבצים"</string> - <string name="bluetooth_profile_hid" msgid="2969922922664315866">"מכשיר קלט"</string> + <string name="bluetooth_profile_hid" msgid="2969922922664315866">"התקן קלט"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"גישה לאינטרנט"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"אישור גישה אל אנשי קשר והיסטוריית שיחות"</string> <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"המידע ישמש להודעות על שיחות ועוד"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index c7f3c0a8aa87..b8aae295888d 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"有効、左のみ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"有効、右のみ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"有効、左と右"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"有効(メディアのみ)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"有効(メディアのみ)、左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"接続済み(音声の共有をサポート)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"接続済み(音声の共有をサポート)、左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"接続済み(音声の共有をサポート)、左 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"接続済み(音声の共有をサポート)、右 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"有効(メディアのみ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"音声の共有をサポートしています"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"有効(メディアのみ)、左のみ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"有効(メディアのみ)、右のみ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"有効(メディアのみ)、左右"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"メディアの音声"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"電話"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ファイル転送"</string> @@ -279,7 +268,7 @@ <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"デバイスをペア設定しています…"</string> <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"デバイスをペア設定できませんでした。QR コードが間違っているか、デバイスが同じネットワークに接続されていません。"</string> <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP アドレスとポート"</string> - <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR コードのスキャン"</string> + <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR コードをスキャン"</string> <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR コードをスキャンして Wi-Fi 経由でデバイスをペア設定します"</string> <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi ネットワークに接続してください"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, デバッグ, dev"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index a94a4011c8f2..35ebabd2af83 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"აქტიური, მხოლოდ მარცხნივ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"აქტიური, მხოლოდ მარჯვნივ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"აქტიური, მარცხნივ და მარჯვნივ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"აქტიური (მხოლოდ მედია), ბატარეა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"აქტიური (მხოლოდ მედია), მარცხენა: ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა: ბატარეა<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია), ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია), მარცხენა: ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა: ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია), მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია), მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"აქტიური (მხოლოდ მედია)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"აუდიოს გაზიარება მხარდაჭერილია"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"აქტიური (მხოლოდ მედია), მხოლოდ მარცხენა"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"აქტიური (მხოლოდ მედია), მხოლოდ მარჯვენა"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"აქტიური (მხოლოდ მედია), მარცხენა და მარჯვენა"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"მედია აუდიო"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"სატელეფონო ზარები"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ფაილების გადაცემა"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 1c80ad471f82..e79e3c568e44 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -106,32 +106,21 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Тек сол жағы қосулы"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Тек оң жағы қосулы"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Екеуі де қосулы"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Істеп тұр (тек мультимедиа), батарея зарядының деңгейі: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Істеп тұр (тек мультимедиа). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Қосылды (аудио бөлісуге мүмкіндік береді), батарея зарядының деңгейі:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Қосылды (аудио бөлісуге мүмкіндік береді). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Қосылды (аудио бөлісуге мүмкіндік береді), сол жақ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Қосылды (аудио бөлісуге мүмкіндік береді), оң жақ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Істеп тұр (тек мультимедиа)."</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио бөлісуге мүмкіндік береді."</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Тек сол жақ істеп тұр (мультимедиа ғана)."</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Тек оң жақ істеп тұр (мультимедиа ғана)."</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Сол және оң жақ істеп тұр (мультимедиа ғана)."</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Mультимeдиа дыбысы"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефон қоңыраулары"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл жіберу"</string> - <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Кіріс құрылғысы"</string> + <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Енгізу құрылғысы"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернетке қосылу"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Контакт пен қоңырау тарихына рұқсат беру"</string> <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Ақпарат қоңырау туралы хабарландыру, т.б. үшін қолданылады."</string> @@ -208,7 +197,7 @@ <string name="tts_default_pitch_title" msgid="6988592215554485479">"Дауыс жиілігі"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"Синтезделген сөйлеу үніне әсер етеді"</string> <string name="tts_default_lang_title" msgid="4698933575028098940">"Тіл"</string> - <string name="tts_lang_use_system" msgid="6312945299804012406">"Жүйелік тілді пайдалану"</string> + <string name="tts_lang_use_system" msgid="6312945299804012406">"Жүйе тілін пайдалану"</string> <string name="tts_lang_not_selected" msgid="7927823081096056147">"Тіл таңдалған жоқ"</string> <string name="tts_default_lang_summary" msgid="9042620014800063470">"Сөйлеу мәтіні үшін тілге тән дауыс орнатады"</string> <string name="tts_play_example_title" msgid="1599468547216481684">"Үлгіні тыңдау"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 23bd55c16ec3..e016eb1f28c7 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្ម ខាងឆ្វេងតែប៉ុណ្ណោះ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"សកម្មខាងស្ដាំតែប៉ុណ្ណោះ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"សកម្មខាងឆ្វេង និងស្ដាំ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា) ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា) ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា) ឆ្វេង <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា) ស្ដាំ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"អាចប្រើការស្ដាប់សំឡេងរួមគ្នា"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងឆ្វេងប៉ុណ្ណោះ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងស្ដាំប៉ុណ្ណោះ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) ឆ្វេង និងស្ដាំ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"សំឡេងមេឌៀ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ការហៅទូរសព្ទ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ផ្ទេរឯកសារ"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index c636dd5dd01e..2ef70ec7068a 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ಎಡಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ಬಲಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ಎಡ ಮತ್ತು ಬಲಕಿವಿಯ ಸಾಧನಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ), ಎಡ ಭಾಗದ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ), ಬಲ ಭಾಗದ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಭಾಗದ ಮಾತ್ರ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಬಲ ಭಾಗದ ಮಾತ್ರ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಮತ್ತು ಬಲ ಭಾಗದ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ಮಾಧ್ಯಮ ಆಡಿಯೋ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ಫೋನ್ ಕರೆಗಳು"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string> @@ -333,7 +322,7 @@ <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ಬ್ಯಾಟರಿ ಹೆಚ್ಚು ಬಾಳಿಕೆ ಬರುವಂತೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನೆಟ್ವರ್ಕ್ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ಈ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, MAC ಯಾದೃಚ್ಛಿಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿದಾಗ ಈ ಸಾಧನದ MAC ವಿಳಾಸವು ಪ್ರತಿ ಬಾರಿಯೂ ಬದಲಾಗಬಹುದು."</string> - <string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ ಮಾಡಲಾಗಿದೆ"</string> + <string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ಡ್ ನೆಟ್ವರ್ಕ್"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"ಮೀಟರ್ ಮಾಡಲಾಗಿಲ್ಲ"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string> <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ ಲಾಗರ್ ಗಾತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> @@ -487,7 +476,7 @@ <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"ನಿಮ್ಮ ಬಳಕೆ ಆಧರಿಸಿ <xliff:g id="TIME">%1$s</xliff:g> ವರೆಗೆ ರನ್ ಆಗಲಿದೆ"</string> <string name="power_discharge_by" msgid="4113180890060388350">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ಸಮಯದವರೆಗೆ ರನ್ ಆಗಲಿದೆ"</string> <string name="power_discharge_by_only" msgid="92545648425937000">"<xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ರನ್ ಆಗಲಿದೆ"</string> - <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> ರವರೆಗೆ"</string> + <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> ವರೆಗೆ ಇರುತ್ತದೆ"</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> ಗಳಲ್ಲಿ ಬ್ಯಾಟರಿ ಮುಕ್ತಾಯವಾಗಬಹುದು"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ"</string> <string name="power_remaining_less_than_duration" msgid="318215464914990578">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> @@ -537,7 +526,7 @@ <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"ಸಿಸ್ಟಂ ಭಾಷೆಗಳನ್ನು ಬಳಸಿ"</string> <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ"</string> <string name="ime_security_warning" msgid="6547562217880551450">"ವೈಯಕ್ತಿಕ ಡೇಟಾಗಳಾದ ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನೀವು ಟೈಪ್ ಮಾಡುವ ಎಲ್ಲ ಪಠ್ಯವನ್ನು ಸಂಗ್ರಹಿಸಲು ಈ ಇನ್ಪುಟ್ ವಿಧಾನಕ್ಕೆ ಸಾಧ್ಯವಾಗಬಹುದು. ಇದು <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಬರುತ್ತದೆ. ಈ ಇನ್ಪುಟ್ ವಿಧಾನವನ್ನು ಬಳಸುವುದೇ?"</string> - <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ಗಮನಿಸಿ: ರೀಬೂಟ್ ನಂತರ, ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಅನ್ಲಾಕ್ ಮಾಡುವ ತನಕ ಈ ಆಪ್ ಪ್ರಾರಂಭಗೊಳ್ಳುವುದಿಲ್ಲ"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ಗಮನಿಸಿ: ರೀಬೂಟ್ ನಂತರ, ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಅನ್ಲಾಕ್ ಮಾಡುವ ತನಕ ಈ ಆ್ಯಪ್ ಪ್ರಾರಂಭಗೊಳ್ಳುವುದಿಲ್ಲ"</string> <string name="ims_reg_title" msgid="8197592958123671062">"IMS ನೋಂದಣಿ ಸ್ಥಿತಿ"</string> <string name="ims_reg_status_registered" msgid="884916398194885457">"ನೋಂದಾಯಿಸಲಾಗಿದೆ"</string> <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"ನೋಂದಾಯಿಸಲಾಗಿಲ್ಲ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index f193fef44220..881da4396378 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"활성, 왼쪽만"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"활성, 오른쪽만"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"활성, 왼쪽 및 오른쪽"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"사용 중(미디어 전용), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"사용 중(미디어 전용), 왼쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"연결됨(오디오 공유 지원), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"연결됨(오디오 공유 지원), 왼쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"연결됨(오디오 공유 지원), 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"연결됨(오디오 공유 지원), 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"사용 중(미디어 전용)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"오디오 공유 지원"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"사용 중(미디어 전용), 왼쪽만"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"사용 중(미디어 전용), 오른쪽만"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"사용 중(미디어 전용), 왼쪽 및 오른쪽"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"미디어 오디오"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"전화 통화"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"파일 전송"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 86426fa2350d..1863ed5e51cd 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Иштеп жатат, сол кулак гана"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Жигердүү, оң кулакчын гана"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Жигердүү, сол жана оң кулакчын"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Активдүү (медиа үчүн гана), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарея"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Активдүү (медиа үчүн гана), С: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батарея, О: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарея"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Туташкан (чогуу угуу колдоого алынат), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарея"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Туташкан (чогуу угуу колдоого алынат), С: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батарея, О: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарея"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Туташкан (чогуу угуу колдоого алынат), сол <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Туташкан (чогуу угуу колдоого алынат), оң <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активдүү (медиа үчүн гана)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Чогуу угуу колдоого алынат"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активдүү (медиа үчүн гана), сол кулакчын гана"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активдүү (медиа үчүн гана), оң кулакчын гана"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активдүү (медиа үчүн гана), сол жана оң кулакчын"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Аудио"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефон чалуулар"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл алмашуу"</string> @@ -339,7 +328,7 @@ <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Таржымалдын туруктуу диски тазалансынбы?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Туруктуу таржымалга көз салууну токтотсок, анын түзмөктө сакталган дайындарын жок кылууга аргасыз болобуз."</string> - <string name="select_logpersist_title" msgid="447071974007104196">"Журналдагы маалымат түзмөккө сакталсын"</string> + <string name="select_logpersist_title" msgid="447071974007104196">"Журналдагы нерселерди түзмөккө сактоо"</string> <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Түзмөккө туруктуу сактоо үчүн таржымал буферлерин тандаңыз"</string> <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB конфигурациясын тандоо"</string> <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB конфигурациясын тандоо"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index ad1529d2c6e8..d764123d4b64 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ນຳໃຊ້ຢູ່, ຊ້າຍເທົ່ານັ້ນ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ນຳໃຊ້ຢູ່, ຂວາເທົ່ານັ້ນ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ນຳໃຊ້ຢູ່, ຊ້າຍ ແລະ ຂວາ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ຂ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ), ຊ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ຂ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ), ຊ້າຍ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ), ຂວາ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ຮອງຮັບການແບ່ງປັນສຽງ"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍເທົ່ານັ້ນ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຂວາເທົ່ານັ້ນ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍ ແລະ ຂວາ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ສຽງ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ການໂທ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ການໂອນຍ້າຍໄຟລ໌"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 10ef2c46a360..b388d96402eb 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktyvus, tik kairysis"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktyvus, tik dešinysis"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktyvus, kairysis ir dešinysis"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktyvus (tik medija), akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktyvus (tik medija), kairė: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinė: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Prijungta (palaikomas garso įrašų bendrinimas), akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Prijungta (palaikomas garso įrašų bendrinimas), kairė: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinė: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Prijungta (palaikomas garso įrašų bendrinimas), kairė: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Prijungta (palaikomas garso įrašų bendrinimas), kairė: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktyvus (tik medija)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Palaikomas garso įrašų bendrinimas"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktyvus (tik medija), tik kairė"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktyvus (tik medija), tik dešinė"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktyvus (tik medija), kairė ir dešinė"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medijos garsas"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefono skambučiai"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failo perkėlimas"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signalai ir priminimai"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Leisti nustatyti signalus ir priminimus"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signalai ir priminimai"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leisti šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leiskite šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tvarkaraštis, signalas, priminimas, laikrodis"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Įjungti"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Netrukdymo režimo įjungimas"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index c52e9ddc861d..b28a2e9faf72 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ierīce aktīva, tikai kreisā auss"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ierīce aktīva, tikai labā auss"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ierīces aktīvas, kreisā un labā auss"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktīvs (tikai multividei), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktīvs (tikai multividei), labās austiņas akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, kreisās austiņas akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Izveidots savienojums (atbalsta audio kopīgošanu), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Izveidots savienojums (atbalsta audio kopīgošanu), labās austiņas akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, kreisās austiņas akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Izveidots savienojums (atbalsta audio kopīgošanu), kreisās austiņas akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Izveidots savienojums (atbalsta audio kopīgošanu), labās austiņas akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktīvs (tikai multividei)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Atbalsta audio kopīgošanu"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktīvs (tikai multivide), tikai kreisās puses aparāts"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktīvs (tikai multivide), tikai labās puses aparāts"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktīvs (tikai multivide), kreisās un labās puses aparāts"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Multivides audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Tālruņa zvani"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failu pārsūtīšana"</string> @@ -162,7 +151,7 @@ <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Izmantot ievadei"</string> <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Izmantot dzirdes aparātiem"</string> <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Izmantot LE_AUDIO profilam"</string> - <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Izveidot pāri"</string> + <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Savienot pārī"</string> <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SAVIENOT PĀRĪ"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Atcelt"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Veicot savienošanu pārī, šī ierīce savienojuma laikā varēs piekļūt jūsu kontaktpersonām un zvanu vēsturei."</string> @@ -487,7 +476,7 @@ <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Ņemot vērā lietojumu, darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharge_by" msgid="4113180890060388350">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_discharge_by_only" msgid="92545648425937000">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Līdz <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_discharge_by_only_short" msgid="5883041507426914446">"līdz <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Iespējams, akumulators izlādēsies līdz <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Atlicis: mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Atlicis: mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> @@ -514,7 +503,7 @@ <string name="disabled" msgid="8017887509554714950">"Atspējots"</string> <string name="external_source_trusted" msgid="1146522036773132905">"Atļauts"</string> <string name="external_source_untrusted" msgid="5037891688911672227">"Nav atļauts"</string> - <string name="install_other_apps" msgid="3232595082023199454">"Instalēt nez. lietotnes"</string> + <string name="install_other_apps" msgid="3232595082023199454">"Nezināmu lietotņu instalēšana"</string> <string name="home" msgid="973834627243661438">"Iestatījumu sākumekrāns"</string> <string-array name="battery_labels"> <item msgid="7878690469765357158">"0%"</item> @@ -541,7 +530,7 @@ <string name="ims_reg_title" msgid="8197592958123671062">"IMS reģistrācijas statuss"</string> <string name="ims_reg_status_registered" msgid="884916398194885457">"Reģistrēts"</string> <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Nav reģistrēts"</string> - <string name="status_unavailable" msgid="5279036186589861608">"Nepieejams"</string> + <string name="status_unavailable" msgid="5279036186589861608">"Nepieejama"</string> <string name="wifi_status_mac_randomized" msgid="466382542497832189">"MAC ir atlasīts nejaušā secībā"</string> <string name="wifi_tether_connected_summary" msgid="5100712926640492336">"{count,plural, =1{Pievienota 1 ierīce.}zero{Pievienotas # ierīces.}one{Pievienota # ierīce.}other{Pievienotas # ierīces.}}"</string> <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Vairāk laika."</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 554b92ec60d0..3b530062ff7a 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -96,7 +96,7 @@ <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон и аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Активен, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string> <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активен, Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија"</string> - <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string> + <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија"</string> <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Одлево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само лево"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, само десно"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, лево и десно"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Активно (само аудиовизуелни содржини), батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Активно (само аудиовизуелни содржини), батерија Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, батерија Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Поврзано (поддржува споделување аудио), батерија:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Поврзано (поддржува споделување аудио), батерија Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, батерија Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Поврзано (поддржува споделување аудио), лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Поврзано (поддржува споделување аудио), десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само аудиовизуелни содржини)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддржува споделување аудио"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само аудиовизуелни содржини), само лево"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (само аудиовизуелни содржини), само десно"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (само аудиовизуелни содржини), лево и десно"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Звук на аудио/видео"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонски повици"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос на датотека"</string> @@ -201,7 +190,7 @@ <string name="running_process_item_user_label" msgid="3988506293099805796">"Корисник: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> <string name="launch_defaults_some" msgid="3631650616557252926">"Поставени се некои стандардни вредности"</string> <string name="launch_defaults_none" msgid="8049374306261262709">"Нема поставено стандардни вредности"</string> - <string name="tts_settings" msgid="8130616705989351312">"Поставки на текст-во-говор"</string> + <string name="tts_settings" msgid="8130616705989351312">"Поставки за „Од текст во говор“"</string> <string name="tts_settings_title" msgid="7602210956640483039">"Претворање текст во говор"</string> <string name="tts_default_rate_title" msgid="3964187817364304022">"Брзина на говорот"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"Брзина со која се кажува текстот"</string> @@ -474,9 +463,9 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција на боите"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Корекцијата на боите може да биде корисна кога сакате:<br/> <ol> <li>&nbsp;да ги гледате боите попрецизно</li> <li>&nbsp;да ги отстраните боите за полесно да се концентрирате</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> - <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - полнењето е паузирано за да се заштити батеријата"</string> - <string name="power_incompatible_charging_settings_home_page" msgid="1322050766135126880">"<xliff:g id="LEVEL">%1$s</xliff:g> - Проверете го додатокот за полнење"</string> + <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – полнењето е паузирано за да се заштити батеријата"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1322050766135126880">"<xliff:g id="LEVEL">%1$s</xliff:g> – Проверете го додатокот за полнење"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> според вашето користење"</string> @@ -496,8 +485,8 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string> - <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е оптимизирано"</string> - <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ се полни"</string> + <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – полнењето е оптимизирано"</string> + <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – се полни"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 61bcc44feba0..06e7a239e8c7 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"സജീവമാണ്, ഇടത്തേത് മാത്രം"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"സജീവമാണ്, വലത്തേത് മാത്രം"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"സജീവമാണ്, ഇടത്തേതും വലത്തേതും"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"സജീവം (മീഡിയ മാത്രം), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു), ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു), ഇടതുവശത്ത് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു), വലതുവശത്ത് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"സജീവം (മീഡിയ മാത്രം)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്ത് മാത്രം"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"സജീവം (മീഡിയ മാത്രം), വലതുവശത്ത് മാത്രം"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്തെയും വലതുവശത്തെയും"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"മീഡിയ ഓഡിയോ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ഫോണ് കോളുകൾ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ഫയൽ കൈമാറൽ"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index c2c22e611870..0a23494569b1 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Идэвхтэй, зөвхөн зүүн тал"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Идэвхтэй, зөвхөн баруун тал"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Идэвхтэй, зүүн болон баруун тал"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Идэвхтэй (зөвхөн медиа), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Идэвхтэй (зөвхөн медиа), З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батарей, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Холбогдсон (аудио хуваалцахыг дэмждэг), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Холбогдсон (аудио хуваалцахыг дэмждэг), З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батарей, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Холбогдсон (аудио хуваалцахыг дэмждэг), зүүн <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Холбогдсон (аудио хуваалцахыг дэмждэг), баруун <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Идэвхтэй (зөвхөн медиа)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио хуваалцахыг дэмждэг"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Идэвхтэй (зөвхөн медиа), зөвхөн зүүн"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Идэвхтэй (зөвхөн медиа), зөвхөн баруун"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Идэвхтэй (зөвхөн медиа), зүүн болон баруун"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Медиа аудио"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Утасны дуудлага"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл дамжуулалт"</string> @@ -472,7 +461,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулга"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Өнгө тохируулга нь таныг дараахыг хийхийг хүсэх үед хэрэгтэй байж болно:<br/> <ol> <li>&nbsp;Өнгөнүүдийг илүү нарийвчилж харах</li> <li>&nbsp;Төвлөрөхийн тулд өнгөнүүдийг хасах</li> </ol>"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Өнгө засах нь таныг дараахыг хийхийг хүсэх үед хэрэгтэй байж болно:<br/> <ol> <li> Өнгөнүүдийг илүү нарийвчилж харах</li> <li> Төвлөрөхийн тулд өнгөнүүдийг хасах</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейг хамгаалахын тулд цэнэглэхийг хүлээлгэсэн"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 1e56118883a7..b40ba9e5b2fa 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"फक्त डावे अॅक्टिव्ह आहे"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"फक्त उजवे अॅक्टिव्ह आहे"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"डावे आणि उजवे अॅक्टिव्ह आहे"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"अॅक्टिव्ह आहे (फक्त मीडिया), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ॲक्टिव्ह आहे (फक्त मीडिया), डावे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, उजवे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते), डावे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, उजवे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते), डावे <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते), उजवे <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"अॅक्टिव्ह आहे (फक्त मीडिया)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडिओ शेअरिंगला सपोर्ट करते"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"अॅक्टिव्ह आहे (फक्त मीडिया), फक्त डावे"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"अॅक्टिव्ह आहे (फक्त मीडिया), फक्त उजवे"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"अॅक्टिव्ह आहे (फक्त मीडिया), डावे आणि उजवे"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मीडिया ऑडिओ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"फोन कॉल"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानांतरण"</string> @@ -537,7 +526,7 @@ <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिस्टम भाषा वापरा"</string> <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> साठी सेटिंग्ज उघडण्यात अयशस्वी"</string> <string name="ime_security_warning" msgid="6547562217880551450">"ही इनपुट पद्धत पासवर्ड आणि क्रेडिट कार्ड नंबर यासह, तुम्ही टाइप करता तो सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. ही <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ॲपवरून येते. ही इनपुट पद्धत वापरायची?"</string> - <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"टीप: रीबूट केल्यानंतर, तुम्ही तुमचा फोन अनलॉक करे पर्यंत हे अॅप सुरू होऊ शकत नाही"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"टीप: रीबूट केल्यानंतर, तुम्ही तुमचा फोन अनलॉक करेपर्यंत हे अॅप सुरू होऊ शकत नाही"</string> <string name="ims_reg_title" msgid="8197592958123671062">"IMS नोंदणी स्थिती"</string> <string name="ims_reg_status_registered" msgid="884916398194885457">"नोंदवलेले"</string> <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"नोंदवलेले नाही"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index a93c459d3650..2858ab2039a2 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, kiri sahaja"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, kanan sahaja"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktif (media sahaja), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktif (media sahaja), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Disambungkan (menyokong perkongsian audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Disambungkan (menyokong perkongsian audio), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Disambungkan (menyokong perkongsian audio), kiri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Disambungkan (menyokong perkongsian audio), kanan <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (media sahaja)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Menyokong perkongsian audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (media sahaja), kiri sahaja"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktif (media sahaja), kanan sahaja"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktif (media sahaja), kiri dan kanan"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio media"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Panggilan telefon"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Pemindahan fail"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Penggera dan peringatan"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Benarkan penetapan penggera dan peringatan"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Penggera & peringatan"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Hal ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadual, penggera, peringatan, jam"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Hidupkan"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Hidupkan Jangan Ganggu"</string> @@ -638,7 +627,7 @@ <string name="add_user_failed" msgid="4809887794313944872">"Gagal membuat pengguna baharu"</string> <string name="add_guest_failed" msgid="8074548434469843443">"Gagal membuat tetamu baharu"</string> <string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string> - <string name="edit_user_info_message" msgid="6677556031419002895">"Nama dan gambar yang anda pilih akan dipaparkan kepada sesiapa sahaja yang menggunakan peranti ini."</string> + <string name="edit_user_info_message" msgid="6677556031419002895">"Nama dan gambar yang anda pilih dapat dilihat oleh sesiapa sahaja yang menggunakan peranti ini."</string> <string name="user_add_user" msgid="7876449291500212468">"Tambah pengguna"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string> @@ -708,7 +697,7 @@ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Pilih susun atur papan kekunci"</string> <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Lalai"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"Hidupkan skrin"</string> - <string name="allow_turn_screen_on" msgid="6194845766392742639">"Benarkan menghidupkan skrin"</string> + <string name="allow_turn_screen_on" msgid="6194845766392742639">"Benarkan apl menghidupkan skrin"</string> <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Benarkan apl menghidupkan skrin. Jika dibenarkan, apl boleh menghidupkan skrin pada bila-bila masa tanpa niat eksplisit anda."</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jika anda siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau tukarkan output, siaran semasa anda akan berhenti"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 7880c37fb51c..3898f8dcf838 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ဖွင့်ထားသည်၊ ဘယ်သီးသန့်"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ဖွင့်ထားသည်၊ ညာသီးသန့်"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ဖွင့်ထားသည်၊ ဘယ်နှင့် ညာ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ဘက်ထရီ"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ဘက်ထရီ၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ဘက်ထရီ"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)၊ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ဘက်ထရီ"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)၊ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ဘက်ထရီ၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ဘက်ထရီ"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)၊ ဘယ် <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)၊ ညာ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"သုံးနေသည် (မီဒီယာသီးသန့်)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်သီးသန့်"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ညာသီးသန့်"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်နှင့် ညာ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"မီဒီယာ အသံ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ဖုန်းခေါ်ဆိုမှုများ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ဖိုင်လွဲပြောင်းခြင်း"</string> @@ -272,7 +261,7 @@ <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ချိတ်ဆက်ခြင်း မအောင်မြင်ပါ"</string> <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> သည် မှန်ကန်သည့် ကွန်ရက်သို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ"</string> <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"စက်ပစ္စည်းနှင့် အတူတွဲပါ"</string> - <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi အတူတွဲချိတ်ရန် ကုဒ်"</string> + <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi တွဲချိတ်ကုဒ်"</string> <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"တွဲချိတ်ခြင်း မအောင်မြင်ပါ"</string> <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"စက်ပစ္စည်းသည် ကွန်ရက်တစ်ခုတည်းသို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ။"</string> <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR ကုဒ် စကင်ဖတ်ခြင်းဖြင့် Wi-Fi ပေါ်တွင် စက်ပစ္စည်းကို အတူတွဲပါ"</string> @@ -471,7 +460,7 @@ <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteranomaly (အနီ-အစိမ်း)"</string> <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (အနီ-အစိမ်း)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (အပြာ-အဝါ)"</string> - <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင်ပြင်ခြင်း"</string> + <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင် အမှန်ပြင်ခြင်း"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"အရောင် အမှန်ပြင်ခြင်းသည် အောက်ပါတို့အတွက် အသုံးဝင်နိုင်သည်-<br/> <ol> <li>&nbsp;အရောင်များကို ပိုမိုမှန်ကန်စွာ ကြည့်ရှုခြင်း</li> <li>&nbsp;အာရုံစိုက်နိုင်ရန် အရောင်များ ဖယ်ရှားခြင်း</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"နှိုးစက်နှင့် သတိပေးချက်များ"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"နှိုးစက်နှင့် သတိပေးချက်များ သတ်မှတ်ခွင့်ပြုရန်"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"နှိုးစက်နှင့် သတိပေးချက်များ"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"နှိုးစက်သတ်မှတ်ရန်နှင့် အချိန်တိကျရန် လိုအပ်သည့် လုပ်ဆောင်ချက်များ အစီအစဉ်ဆွဲရန် ဤအက်ပ်ကို ခွင့်ပြုပါ။ ၎င်းက အက်ပ်ကို နောက်ခံတွင် လုပ်ဆောင်ခွင့်ပေးပြီး ဘက်ထရီပိုသုံးနိုင်သည်။\n\nဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်ဖြင့် အစီအစဉ်ဆွဲထားသော လက်ရှိနှိုးစက်နှင့် အချိန်သတ်မှတ်ထားသည့် အစီအစဉ်များ အလုပ်လုပ်တော့မည် မဟုတ်ပါ။"</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"နှိုးစက်သတ်မှတ်ရန်နှင့် အချိန်တိကျရန် လိုအပ်သည့် လုပ်ဆောင်ချက်များအတွက် အစီအစဉ်ဆွဲရန် ဤအက်ပ်ကို ခွင့်ပြုသည်။ ၎င်းက အက်ပ်ကို နောက်ခံတွင် လုပ်ဆောင်ခွင့်ပေးပြီး ဘက်ထရီပိုသုံးနိုင်သည်။\n\nဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်ဖြင့် အစီအစဉ်ဆွဲထားသော လက်ရှိနှိုးစက်နှင့် အချိန်သတ်မှတ်ထားသည့် အစီအစဉ်များ အလုပ်လုပ်တော့မည် မဟုတ်ပါ။"</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"အချိန်ဇယား၊ နှိုးစက်၊ သတိပေးချက်၊ နာရီ"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ဖွင့်ရန်"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'မနှောင့်ယှက်ရ\' ဖွင့်ခြင်း"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 0eacc5e6024f..7edaba733ec5 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bare venstre"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bare høyre"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og høyre"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiv (bare medieinnhold), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiv (bare medieinnhold), v: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, h: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Tilkoblet (støtter lyddeling), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Tilkoblet (støtter lyddeling), v: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, h: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Tilkoblet (støtter lyddeling), venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Tilkoblet (støtter lyddeling), høyre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (bare medieinnhold)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Støtter lyddeling"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (bare medieinnhold), bare venstre"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (bare medieinnhold), bare høyre"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (bare medieinnhold), høyre og venstre"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medielyd"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonsamtaler"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverføring"</string> diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml index 447cd8027b1a..d2c3729ea9c1 100644 --- a/packages/SettingsLib/res/values-ne/arrays.xml +++ b/packages/SettingsLib/res/values-ne/arrays.xml @@ -55,7 +55,7 @@ </string-array> <string-array name="hdcp_checking_summaries"> <item msgid="4045840870658484038">"HDCP परीक्षण कहिल्यै प्रयोग नगर्नुहोस्"</item> - <item msgid="8254225038262324761">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गरियोस्"</item> + <item msgid="8254225038262324761">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item> <item msgid="6421717003037072581">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item> </string-array> <string-array name="bt_hci_snoop_log_entries"> @@ -97,7 +97,7 @@ <item msgid="8147982633566548515">"map14"</item> </string-array> <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="2494959071796102843">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="2494959071796102843">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="4055460186095649420">"SBC"</item> <item msgid="720249083677397051">"AAC"</item> <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item> @@ -107,7 +107,7 @@ <item msgid="506175145534048710">"Opus"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="8868109554557331312">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="8868109554557331312">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="9024885861221697796">"SBC"</item> <item msgid="4688890470703790013">"AAC"</item> <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item> @@ -117,38 +117,38 @@ <item msgid="7940970833006181407">"Opus"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> - <item msgid="926809261293414607">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="926809261293414607">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="8003118270854840095">"४४.१ kHz"</item> <item msgid="3208896645474529394">"४८.० kHz"</item> <item msgid="8420261949134022577">"८८.२ kHz"</item> <item msgid="8887519571067543785">"९६.० kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_summaries"> - <item msgid="2284090879080331090">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="2284090879080331090">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="1872276250541651186">"४४.१ kHz"</item> <item msgid="8736780630001704004">"४८.० kHz"</item> <item msgid="7698585706868856888">"८८.२ kHz"</item> <item msgid="8946330945963372966">"९६.० kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> - <item msgid="2574107108483219051">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="2574107108483219051">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="4671992321419011165">"१६ बिट/नमूना"</item> <item msgid="1933898806184763940">"२४ बिट/नमूना"</item> <item msgid="1212577207279552119">"३२ बिट/नमूना"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> - <item msgid="9196208128729063711">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="9196208128729063711">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="1084497364516370912">"१६ बिट/नमूना"</item> <item msgid="2077889391457961734">"२४ बिट/नमूना"</item> <item msgid="3836844909491316925">"३२ बिट/नमूना"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> - <item msgid="3014194562841654656">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="3014194562841654656">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="5982952342181788248">"मोनो"</item> <item msgid="927546067692441494">"स्टेरियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_summaries"> - <item msgid="1997302811102880485">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item> + <item msgid="1997302811102880485">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item> <item msgid="8005696114958453588">"मोनो"</item> <item msgid="1333279807604675720">"स्टेरियो"</item> </string-array> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index e2236ccdec19..559278a9c935 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -106,41 +106,30 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"बायाँ मात्र अन छ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सक्रिय, दायाँ मात्र"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"सक्रिय, बायाँ र दायाँ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"सक्रिय छ (मिडिया मात्र), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"सक्रिय छ (मिडिया मात्र), बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ब्याट्री, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ), बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ब्याट्री, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ), बायाँ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ), दायाँ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"सक्रिय छ (मिडिया मात्र)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"अडियो सेयर गर्न मिल्छ"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"सक्रिय छ (मिडिया मात्र), बायाँ मात्र"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"सक्रिय छ (मिडिया मात्र), दायाँ मात्र"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"सक्रिय छ (मिडिया मात्र), बायाँ र दायाँ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मिडिया अडियो"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"फोन कलहरू"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानान्तरण"</string> - <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट उपकरण"</string> + <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट डिभाइस"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"इन्टरनेट एक्सेस"</string> - <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"कन्ट्याक्ट र कल हिस्ट्री एक्सेस गर्ने अनुमति दिइयोस्"</string> + <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"कन्ट्याक्ट र कल हिस्ट्री एक्सेस गर्ने अनुमति दिनुहोस्"</string> <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"यो जानकारीको प्रयोग कल आएको जानकारी दिने लगायतका कुराका लागि प्रयोग गरिने छ"</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इन्टरनेट जडान साझेदारी गर्दै"</string> <string name="bluetooth_profile_map" msgid="8907204701162107271">"टेक्स्ट म्यासेजहरू"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM एक्सेस"</string> <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD अडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD अडियो"</string> - <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"श्रवण यन्त्रहरू"</string> + <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"हियरिङ डिभाइसहरू"</string> <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE अडियो"</string> <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"श्रवण यन्त्रहरूमा जडान गरियो"</string> <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE अडियोमा कनेक्ट गरिएको छ"</string> @@ -176,7 +165,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"छवि सम्बन्धी"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"हेडफोन"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"इनपुट सम्बन्धी बाह्य यन्त्र"</string> - <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"श्रवण यन्त्रहरू"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"हियरिङ डिभाइसहरू"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ब्लुटुथ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi बन्द।"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi जडान विच्छेद भयो।"</string> @@ -256,14 +245,14 @@ <string name="enable_adb_summary" msgid="3711526030096574316">"USB कनेक्ट गरिएको बेलामा डिबग मोड"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"USB डिबग गर्ने अधिकार फिर्ता लिइयोस्"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"वायरलेस डिबगिङ"</string> - <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi मा कनेक्ट हुँदा डिबग मोड अन गरियोस्"</string> + <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi मा कनेक्ट हुँदा डिबग मोड अन गर्नुहोस्"</string> <string name="adb_wireless_error" msgid="721958772149779856">"त्रुटि"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"वायरलेस डिबगिङ"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"उपलब्ध डिभाइस हेर्न र प्रयोग गर्न वायरलेस डिबगिङ अन गर्नुहोस्"</string> - <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR कोड प्रयोग गरी डिभाइस कनेक्ट गरियोस्"</string> + <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR कोड प्रयोग गरी डिभाइस कनेक्ट गर्नुहोस्"</string> <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR कोड स्क्यानर प्रयोग गरी नयाँ डिभाइसहरूको जोडा बनाउनुहोस्"</string> - <string name="adb_pair_method_code_title" msgid="1122590300445142904">"पेयरिङ कोड प्रयोग गरी कनेक्ट गरियोस्"</string> - <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"छ अङ्कको कोड प्रयोग गरी नयाँ डिभाइसहरू कनेक्ट गरियोस्"</string> + <string name="adb_pair_method_code_title" msgid="1122590300445142904">"पेयरिङ कोड प्रयोग गरी कनेक्ट गर्नुहोस्"</string> + <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"छ अङ्कको कोड प्रयोग गरी नयाँ डिभाइसहरू कनेक्ट गर्नुहोस्"</string> <string name="adb_paired_devices_title" msgid="5268997341526217362">"कनेक्ट गरिएका डिभाइस"</string> <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"हाल जोडिएको छ"</string> <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"डिभाइसको विवरण"</string> @@ -284,7 +273,7 @@ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"कृपया कुनै Wi-Fi मा कनेक्ट गर्नुहोस्"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"बग रिपोर्टको सर्टकट"</string> - <string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट प्राप्त गर्न पावर मेनुमा बटन देखाइयोस्"</string> + <string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट प्राप्त गर्न पावर मेनुमा बटन देखाउनुहोस्"</string> <string name="keep_screen_on" msgid="1187161672348797558">"डिस्प्ले अफ नहोस्"</string> <string name="keep_screen_on_summary" msgid="1510731514101925829">"चार्ज गर्दा स्क्रिन कहिल्यै अफ हुँदैन।"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"ब्लुटुथ HCI snoop लग अन गर्नुहोस्"</string> @@ -298,14 +287,14 @@ <string name="mock_location_app_set" msgid="4706722469342913843">"नमूना स्थान एप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"नेटवर्किङ"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिस्प्ले प्रयोग गर्ने वा नगर्ने"</string> - <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi-Fi भर्बोज लग अन गरियोस्"</string> + <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi-Fi भर्बोज लग अन गर्नुहोस्"</string> <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi स्क्यान थ्रोटलिङ"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi-Fi नन-पर्सिस्टेन्ट MAC र्यान्डमाइजेसन"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"मोबाइल डेटा सधैँ अन होस्"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string> - <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नामकरण नगरिएका ब्लुटुथ डिभाइस देखाइयोस्"</string> - <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"निरपेक्ष भोल्युम अफ गरियोस्"</string> - <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche अन गरियोस्"</string> + <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नामकरण नगरिएका ब्लुटुथ डिभाइस देखाउनुहोस्"</string> + <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"निरपेक्ष भोल्युम अफ गर्नुहोस्"</string> + <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche अन गर्नुहोस्"</string> <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लुटुथको AVRCP संस्करण"</string> <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लुटुथको AVRCP संस्करण चयन गर्नुहोस्"</string> <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ब्लुटुथको MAP संस्करण"</string> @@ -329,8 +318,8 @@ <string name="private_dns_mode_provider" msgid="3619040641762557028">"निजी DNS प्रदायकको होस्टनेम"</string> <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"DNS प्रदायकको होस्टनेम हाल्नुहोस्"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"जडान गर्न सकिएन"</string> - <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्लेसम्बन्धी विकल्प देखाइयोस्"</string> - <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi-Fi लगिङ लेभल बढाइयोस्, Wi-Fi पिकरमा प्रति SSID RSSI देखाइयोस्"</string> + <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्लेसम्बन्धी विकल्प देखाउनुहोस्"</string> + <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi-Fi लगिङ लेभल बढाउनुहोस्, Wi-Fi पिकरमा प्रति SSID RSSI देखाउनुहोस्"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"यसले ब्याट्रीको खपत कम गर्छ र नेटवर्कको कार्यसम्पादनमा सुधार गर्दछ"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"यो मोड अन गरिएका बेला यो डिभाइस म्याक एड्रेस बदल्ने सुविधा अन गरिएको नेटवर्कमा जति पटक कनेक्ट हुन्छ त्यति नै पटक यस डिभाइसको म्याक एड्रेस पनि परिवर्तन हुन सक्छ।"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"सशुल्क वाइफाइ"</string> @@ -339,15 +328,15 @@ <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"लगरको निरन्तर भण्डारणलाई खाली गर्ने हो?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"हामी अब निरन्तर लगर मार्फत अनुगमन गरिरहेका छैनौँ, त्यसैले हामीले तपाईँको डिभाइसमा रहेको लगर सम्बन्धी डेटा मेटाउन आवश्यक छ।"</string> - <string name="select_logpersist_title" msgid="447071974007104196">"लगरसम्बन्धी डेटा निरन्तर डिभाइसमा भण्डारण गरियोस्"</string> + <string name="select_logpersist_title" msgid="447071974007104196">"लगरसम्बन्धी डेटा निरन्तर डिभाइसमा भण्डारण गर्नुहोस्"</string> <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"डिभाइसमा निरन्तर भण्डारण गरिने लग सम्बन्धी बफरहरूलाई चयन गर्नुहोस्"</string> <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB विन्यास चयन गर्नुहोस्"</string> <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB विन्यास चयन गर्नुहोस्"</string> <string name="allow_mock_location" msgid="2102650981552527884">"नक्कली स्थानहरूलाई अनुमति दिनुहोस्"</string> <string name="allow_mock_location_summary" msgid="179780881081354579">"नक्कली स्थानहरूलाई अनुमति दिनुहोस्"</string> - <string name="debug_view_attributes" msgid="3539609843984208216">"भ्युको एट्रिब्युट हेर्ने सुविधा अन गरियोस्"</string> + <string name="debug_view_attributes" msgid="3539609843984208216">"भ्युको एट्रिब्युट हेर्ने सुविधा अन गर्नुहोस्"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Wi-Fi अन हुँदा पनि मोबाइल डेटा सधैँ अन होस् (द्रुत रूपमा नेटवर्क बदल्न)।"</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध हुँदा टेदरिङ हार्डवेयर एक्सलरेसन प्रयोग गरियोस्"</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध हुँदा टेदरिङ हार्डवेयर एक्सलरेसन प्रयोग गर्नुहोस्"</string> <string name="adb_warning_title" msgid="7708653449506485728">"USB डिबग गर्न लागि अनुमति दिने हो?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"युएसबी डिबगिङ विकास प्रयोजनका लागि मात्र निर्मित हुन्छ। यसलाई तपाईँको कम्प्युटर र तपाईँको उपकरणका बीच डेटा कपी गर्न, बिना सूचना तपाईँको उपकरणमा एपहरू इन्स्टल गर्न र लग डेटा पढ्नका लागि प्रयोग गर्नुहोस्।"</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"वायरलेस डिबगिङ सेवा सक्षम पार्ने हो?"</string> @@ -355,11 +344,11 @@ <string name="adb_keys_warning_message" msgid="2968555274488101220">"तपाईं पहिले नै अधिकृत गर्नुभएका सबै कम्प्यूटरबाट USB डिबग गर्नको लागि पहुँच रद्द गर्ने हो?"</string> <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिङहरू अनुमति दिने हो?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र एपहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string> - <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB मा एपको पुष्टि गरियोस्"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक व्यवहार पत्ता लगाउन ADB/ADT बाट इन्स्टल गरिएका एपको जाँच गरियोस्"</string> + <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB मा एपको पुष्टि गर्नुहोस्"</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक व्यवहार पत्ता लगाउन ADB/ADT बाट इन्स्टल गरिएका एपको जाँच गर्नुहोस्"</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"नामकरण नगरिएका ब्लुटुथ डिभाइस (म्याक एड्रेस भएका मात्र) देखाइने छ"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"यसले रिमोट डिभाइसमा अत्यधिक ठूलो वा अनियन्त्रित भोल्युम बज्नेको जस्ता अवस्थामा ब्लुटुथको निरपेक्ष भोल्युम अफ गर्छ।"</string> - <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लुटुथ Gabeldorsche सुविधाको स्ट्याक अन गरियोस्।"</string> + <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लुटुथ Gabeldorsche सुविधाको स्ट्याक अन गर्नुहोस्।"</string> <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"यसले परिष्कृत जडानको सुविधा सक्षम पार्छ।"</string> <string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string> <string name="enable_terminal_summary" msgid="2481074834856064500">"स्थानीय सेल पहुँच प्रदान गर्ने टर्मिनल एप सक्षम गर्नुहोस्"</string> @@ -378,60 +367,60 @@ <string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयरले बढाएको रेन्डरिङ"</string> <string name="media_category" msgid="8122076702526144053">"मिडिया"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"अनुगमन गरिँदै छ"</string> - <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड अन गरियोस्"</string> - <string name="strict_mode_summary" msgid="1838248687233554654">"एपले मुख्य थ्रेडमा लामा गतिविधि गर्दा स्क्रिन फ्ल्यास गरियोस्"</string> + <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड अन गर्नुहोस्"</string> + <string name="strict_mode_summary" msgid="1838248687233554654">"एपले मुख्य थ्रेडमा लामा गतिविधि गर्दा स्क्रिन फ्ल्यास गर्नुहोस्"</string> <string name="pointer_location" msgid="7516929526199520173">"पोइन्टरको स्थान"</string> <string name="pointer_location_summary" msgid="957120116989798464">"स्क्रिन ओभरलेले हालको टच डेटा देखाउँदै छ"</string> - <string name="show_touches" msgid="8437666942161289025">"ट्याप देखाइयोस्"</string> - <string name="show_touches_summary" msgid="3692861665994502193">"ट्यापका लागि भिजुअल प्रतिक्रिया देखाइयोस्"</string> + <string name="show_touches" msgid="8437666942161289025">"ट्याप देखाउनुहोस्"</string> + <string name="show_touches_summary" msgid="3692861665994502193">"ट्यापका लागि भिजुअल प्रतिक्रिया देखाउनुहोस्"</string> <string name="show_key_presses" msgid="6360141722735900214">"थिचिएका कीहरू देखाइयून्"</string> - <string name="show_key_presses_summary" msgid="725387457373015024">"थिचिएका भौतिक कीसम्बन्धी भिजुअल प्रतिक्रिया देखाइयोस्"</string> - <string name="show_screen_updates" msgid="2078782895825535494">"सर्फेस अपडेट देखाइयोस्"</string> - <string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट हुँदा विन्डोका पूरै सतहमा देखाइयोस्"</string> - <string name="show_hw_screen_updates" msgid="2021286231267747506">"GPU भ्युको अपडेट देखाइयोस्"</string> - <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"GPU ले बनाएको भ्यु विन्डोमा फ्ल्यास गरियोस्"</string> - <string name="show_hw_layers_updates" msgid="5268370750002509767">"हार्डवेयर लेयरको अपडेट देखाइयोस्"</string> + <string name="show_key_presses_summary" msgid="725387457373015024">"थिचिएका भौतिक कीसम्बन्धी भिजुअल प्रतिक्रिया देखाउनुहोस्"</string> + <string name="show_screen_updates" msgid="2078782895825535494">"सर्फेस अपडेट देखाउनुहोस्"</string> + <string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट हुँदा विन्डोका पूरै सतहमा देखाउनुहोस्"</string> + <string name="show_hw_screen_updates" msgid="2021286231267747506">"GPU भ्युको अपडेट देखाउनुहोस्"</string> + <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"GPU ले बनाएको भ्यु विन्डोमा फ्ल्यास गर्नुहोस्"</string> + <string name="show_hw_layers_updates" msgid="5268370750002509767">"हार्डवेयर लेयरको अपडेट देखाउनुहोस्"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"हार्डवेयर लेयर अपडेट हुँदा ती लेयर हरिया देखिऊन्"</string> - <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU overdraw डिबग गरियोस्"</string> - <string name="disable_overlays" msgid="4206590799671557143">"HW ओभरले अफ गरियोस्"</string> - <string name="disable_overlays_summary" msgid="1954852414363338166">"स्क्रिन कोम्पजिट गर्न लागि सधैँ GPU प्रयोग गरियोस्"</string> - <string name="simulate_color_space" msgid="1206503300335835151">"कलर स्पेसको नक्कल गरियोस्"</string> + <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU overdraw डिबग गर्नुहोस्"</string> + <string name="disable_overlays" msgid="4206590799671557143">"HW ओभरले अफ गर्नुहोस्"</string> + <string name="disable_overlays_summary" msgid="1954852414363338166">"स्क्रिन कोम्पजिट गर्न लागि सधैँ GPU प्रयोग गर्नुहोस्"</string> + <string name="simulate_color_space" msgid="1206503300335835151">"कलर स्पेसको नक्कल गर्नुहोस्"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ट्रेसहरू सक्षम गर्नुहोस्"</string> - <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB अडियो राउटिङ अफ गरियोस्"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB अडियोमा स्वत: राउट नगरियोस्"</string> - <string name="debug_layout" msgid="1659216803043339741">"लेआउटका सीमाहरू देखाइयोस्"</string> - <string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमा, मार्जिन, इत्यादि देखाइयोस्।"</string> - <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL लेआउट बलपूर्वक प्रयोग गरियोस्"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सबै लोकेलमा RTLमा स्क्रिन लेआउट बलपूर्वक प्रयोग गरियोस्"</string> + <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB अडियो राउटिङ अफ गर्नुहोस्"</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB अडियोमा स्वत: राउट नगर्नुहोस्"</string> + <string name="debug_layout" msgid="1659216803043339741">"लेआउटका सीमाहरू देखाउनुहोस्"</string> + <string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमा, मार्जिन, इत्यादि देखाउनुहोस्।"</string> + <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL लेआउट बलपूर्वक प्रयोग गर्नुहोस्"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सबै लोकेलमा RTLमा स्क्रिन लेआउट बलपूर्वक प्रयोग गर्नुहोस्"</string> <string name="transparent_navigation_bar" msgid="1933192171384678484">"पारदर्शी नेभिगेसन बार"</string> <string name="transparent_navigation_bar_summary" msgid="5454359021817330722">"नेभिगेसन बारको ब्याकग्राउन्डको रङ स्वतः पारदर्शी बनाउनुहोस्"</string> - <string name="window_blurs" msgid="6831008984828425106">"विन्डो ब्लर गरियोस्"</string> - <string name="force_msaa" msgid="4081288296137775550">"बलपूर्वक 4x MSAA प्रयोग गरियोस्"</string> - <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES २.० एपमा ४x MSAA अन गरियोस्"</string> - <string name="show_non_rect_clip" msgid="7499758654867881817">"गैर आयातकर क्लिप रहेका कार्यहरू डिबग गरियोस्"</string> + <string name="window_blurs" msgid="6831008984828425106">"विन्डो ब्लर गर्नुहोस्"</string> + <string name="force_msaa" msgid="4081288296137775550">"बलपूर्वक 4x MSAA प्रयोग गर्नुहोस्"</string> + <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES २.० एपमा ४x MSAA अन गर्नुहोस्"</string> + <string name="show_non_rect_clip" msgid="7499758654867881817">"गैर आयातकर क्लिप रहेका कार्यहरू डिबग गर्नुहोस्"</string> <string name="track_frame_time" msgid="522674651937771106">"प्रोफाइलको HWUI रेन्डरिङ"</string> - <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU का डिबग लेयर अन गरियोस्"</string> - <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"डिबग एपका लागि GPU का डिबग लेयर लोड गरियोस्"</string> - <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"भर्बोज भेन्डर लगिङ अन गरियोस्"</string> - <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"बग रिपोर्टहरूमा डिभाइस विशेषका विक्रेताका अतिरिक्त लगहरू समावेश गरियोस्। यी लगमा निजी जानकारी समावेश हुन सक्छन्, यिनले ब्याट्रीको खपत बढाउन र/वा थप भण्डारण प्रयोग गर्न सक्छन्।"</string> + <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU का डिबग लेयर अन गर्नुहोस्"</string> + <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"डिबग एपका लागि GPU का डिबग लेयर लोड गर्नुहोस्"</string> + <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"भर्बोज भेन्डर लगिङ अन गर्नुहोस्"</string> + <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"बग रिपोर्टहरूमा डिभाइस विशेषका विक्रेताका अतिरिक्त लगहरू समावेश गर्नुहोस्। यी लगमा निजी जानकारी समावेश हुन सक्छन्, यिनले ब्याट्रीको खपत बढाउन र/वा थप भण्डारण प्रयोग गर्न सक्छन्।"</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"विन्डो एनिमेसन स्केल"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"संक्रमण एनिमेसन स्केल"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"एनिमेसनको अवधि मापन"</string> - <string name="overlay_display_devices_title" msgid="5411894622334469607">"सहायक डिस्प्लेको नक्कल गरियोस्"</string> + <string name="overlay_display_devices_title" msgid="5411894622334469607">"सहायक डिस्प्लेको नक्कल गर्नुहोस्"</string> <string name="debug_applications_category" msgid="5394089406638954196">"एपहरू"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"गतिविधि नराखियोस्"</string> - <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"प्रयोगकर्ता कुनै गतिविधिबाट बाहिरिने बित्तिकै उक्त गतिविधि अन्त्य गरियोस्"</string> + <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"प्रयोगकर्ता कुनै गतिविधिबाट बाहिरिने बित्तिकै उक्त गतिविधि अन्त्य गर्नुहोस्"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"ब्याकग्राउन्ड प्रक्रियाको सीमा"</string> - <string name="show_all_anrs" msgid="9160563836616468726">"ब्याकग्राउन्डमा ANR देखाइयोस्"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"ब्याकग्राउन्डका एपको हकमा \'नचलिरहेका एप\' सन्देश देखाइयोस्"</string> - <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना च्यानलसम्बन्धी चेतावनी देखाइयोस्"</string> - <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"एपले मान्य च्यानलबिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाइयोस्"</string> + <string name="show_all_anrs" msgid="9160563836616468726">"ब्याकग्राउन्डमा ANR देखाउनुहोस्"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"ब्याकग्राउन्डका एपको हकमा \'नचलिरहेका एप\' सन्देश देखाउनुहोस्"</string> + <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना च्यानलसम्बन्धी चेतावनी देखाउनुहोस्"</string> + <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"एपले मान्य च्यानलबिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाउनुहोस्"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"एपलाई बहिरी मेमोरीमा पनि चल्न दिइयोस्"</string> - <string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाइयोस्"</string> - <string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाइयोस्"</string> - <string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाइयोस्।"</string> - <string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गरियोस्"</string> - <string name="enable_freeform_support_summary" msgid="1822862728719276331">"प्रयोगात्मक फ्रिफर्म विन्डोहरू चल्ने बनाइयोस्"</string> + <string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाउनुहोस्"</string> + <string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाउनुहोस्"</string> + <string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाउनुहोस्।"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गर्नुहोस्"</string> + <string name="enable_freeform_support_summary" msgid="1822862728719276331">"प्रयोगात्मक फ्रिफर्म विन्डोहरू चल्ने बनाउनुहोस्"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटप ब्याकअप पासवर्ड"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"हाल डेस्कटपका सबै ब्याकअप पासवर्ड सुरक्षित छैनन्"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string> @@ -457,7 +446,7 @@ <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिङसम्बन्धी डिफल्ट सेटिङ परिवर्तन गर्नुहोस्"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिङ अन गर्नुहोस्"</string> <string name="transcode_default" msgid="3784803084573509491">"एपहरूमा आधुनिक फर्म्याट प्रयोग गर्न मिल्छ भनी मान्नुहोस्"</string> - <string name="transcode_notification" msgid="5560515979793436168">"ट्रान्सकोडिङसम्बन्धी सूचना देखाइयोस्"</string> + <string name="transcode_notification" msgid="5560515979793436168">"ट्रान्सकोडिङसम्बन्धी सूचना देखाउनुहोस्"</string> <string name="transcode_disable_cache" msgid="3160069309377467045">"ट्रान्सकोडिङको क्यास अफ गर्नुहोस्"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string> @@ -472,7 +461,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ट्रिटानोमेली (निलो-पंहेलो)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"कलर करेक्सन"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"तपाईं रङ सच्याउने सुविधाका सहायताले निम्न कार्य गर्न सक्नुहुन्छ:<br/> <ol> <li>&nbsp;अझ सटीक तरिकाले रङहरू हेर्न</li> <li>&nbsp;फोकस गर्नका लागि रङहरू हटाउन</li> </ol>"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"तपाईं कलर करेक्सनका सहायताले निम्न कार्य गर्न सक्नुहुन्छ:<br/> <ol> <li>&nbsp;अझ सटीक तरिकाले रङहरू हेर्न</li> <li>&nbsp;फोकस गर्नका लागि रङहरू हटाउन</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - ब्याट्री जोगाउन चार्जिङ होल्ड गरिएको छ"</string> @@ -534,7 +523,7 @@ <string name="retail_demo_reset_next" msgid="3688129033843885362">"अर्को"</string> <string name="retail_demo_reset_title" msgid="1866911701095959800">"पासवर्ड आवश्यक छ"</string> <string name="active_input_method_subtypes" msgid="4232680535471633046">"आगत विधिहरू अन गर्नुहोस्"</string> - <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिष्टममा भएका भाषा प्रयोग गरियोस्"</string> + <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिष्टममा भएका भाषा प्रयोग गर्नुहोस्"</string> <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>का लागि सेटिङहरू खोल्न विफल भयो।"</string> <string name="ime_security_warning" msgid="6547562217880551450">"यस इनपुट विधिले तपाईँले टाइप गर्नुहुने सम्पूर्ण पाठ बटु्ल्न सक्छ, व्यक्तिगत डेटा जस्तै पासवर्ड र क्रेडिट कार्ड नम्बर लगायतका। यो <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> अनुप्रयोगबाट आउँदछ। यो इनपुट विधि प्रयोग गर्ने हो?"</string> <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"नोट: रिबुट गरेपछि तपाईंले आफ्नो फोन अनलक नगरेसम्म यो एप सुरु हुँदैन"</string> @@ -708,8 +697,8 @@ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"किबोर्ड लेआउट छान्नुहोस्"</string> <string name="keyboard_layout_default_label" msgid="1997292217218546957">"डिफल्ट"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"स्क्रिन अन गर्नुहोस्"</string> - <string name="allow_turn_screen_on" msgid="6194845766392742639">"स्क्रिन अन गर्ने अनुमति दिइयोस्"</string> - <string name="allow_turn_screen_on_description" msgid="43834403291575164">"कुनै एपलाई स्क्रिन अन गर्ने अनुमति दिइयोस्। यो अनुमति दिइएका खण्डमा तपाईंले अन गर्न नखोजेका बेलामा पनि एपले जुनसुकै बेला स्क्रिन अन गर्न सक्छ।"</string> + <string name="allow_turn_screen_on" msgid="6194845766392742639">"स्क्रिन अन गर्ने अनुमति दिनुहोस्"</string> + <string name="allow_turn_screen_on_description" msgid="43834403291575164">"कुनै एपलाई स्क्रिन अन गर्ने अनुमति दिनुहोस्। यो अनुमति दिइएका खण्डमा तपाईंले अन गर्न नखोजेका बेलामा पनि एपले जुनसुकै बेला स्क्रिन अन गर्न सक्छ।"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ब्रोडकास्ट गर्न छाड्ने हो?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"तपाईंले <xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुभयो वा आउटपुट परिवर्तन गर्नुभयो भने तपाईंको हालको ब्रोडकास्ट रोकिने छ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुहोस्"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 801c73f8dff2..7007677c4079 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -106,35 +106,24 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actief, alleen links"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actief, alleen rechts"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actief, links en rechts"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Actief (alleen media), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterij"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Actief (alleen media), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batterij, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batterij"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Verbonden (ondersteunt audio delen), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterij"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Verbonden (ondersteunt audio delen), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batterij, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batterij"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Verbonden (ondersteunt audio delen), links <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Verbonden (ondersteunt audio delen), rechts <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actief (alleen media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ondersteunt audio delen"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actief (alleen media), alleen links"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actief (alleen media), alleen rechts"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actief (alleen media), links en rechts"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media-audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefoongesprekken"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Bestandsoverdracht"</string> <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Invoerapparaat"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internettoegang"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Toegang geven tot contacten en gespreksgeschiedenis"</string> - <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"De informatie wordt onder andere gebruikt voor gespreksaankondigingen"</string> + <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Deze informatie wordt o.a. gebruikt voor gespreksaankondigingen"</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetverbinding delen"</string> <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms-berichten"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Simtoegang"</string> @@ -472,7 +461,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Kleurcorrectie kan handig zijn in de volgende situaties:<br/> <ol> <li>&nbsp;Je wilt kleuren nauwkeuriger zien.</li> <li>&nbsp;Je wilt kleuren verwijderen zodat je je beter kunt focussen.</li> </ol>"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Kleurcorrectie kan handig zijn in de volgende situaties:<br/> <ol> <li>&nbsp;Je wilt kleuren nauwkeuriger zien.</li> <li>&nbsp;Je wilt kleuren verwijderen zodat je je beter kunt concentreren.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g>: opladen is in de wacht gezet om de batterij te beschermen"</string> @@ -553,7 +542,7 @@ <string name="okay" msgid="949938843324579502">"OK"</string> <string name="done" msgid="381184316122520313">"Klaar"</string> <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en herinneringen"</string> - <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Wekkers en herinneringen laten instellen"</string> + <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Instellen van wekkers en herinneringen toestaan"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en herinneringen"</string> <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Sta toe dat deze app wekkers zet en tijdgevoelige acties plant. De app kan hierdoor op de achtergrond worden uitgevoerd, waardoor je misschien meer batterijlading verbruikt.\n\nAls dit recht uitstaat, werken door deze app geplande bestaande wekkers en tijdgebaseerde afspraken niet."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plannen, schema, wekker, alarm, herinnering, klok"</string> @@ -709,7 +698,7 @@ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standaard"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"Scherm aanzetten"</string> <string name="allow_turn_screen_on" msgid="6194845766392742639">"Scherm aanzetten toestaan"</string> - <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Toestaan dat een app het scherm aanzet. Indien toegestaan, kan de app het scherm op elk moment aanzetten zonder jouw expliciete intentie."</string> + <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Sta toe dat een app het scherm aanzet. Indien toegestaan, kan de app het scherm op elk moment aanzetten zonder jouw expliciete intentie."</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Uitzending van <xliff:g id="APP_NAME">%1$s</xliff:g> stopzetten?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Als je <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzendt of de uitvoer wijzigt, wordt je huidige uitzending gestopt"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzenden"</string> diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml index c7c857b092a9..28a8db6da837 100644 --- a/packages/SettingsLib/res/values-or/arrays.xml +++ b/packages/SettingsLib/res/values-or/arrays.xml @@ -188,7 +188,7 @@ <item msgid="409235464399258501">"ବନ୍ଦ"</item> <item msgid="4195153527464162486">"64K ପିଛା ଲଗ୍ ବଫର୍"</item> <item msgid="7464037639415220106">"256K ଲଗ୍ ପ୍ରତି ବଫର୍"</item> - <item msgid="8539423820514360724">"1M ପ୍ରତି ଲଗ୍ ବଫର୍"</item> + <item msgid="8539423820514360724">"ପ୍ରତି ଲଗ ବଫର ପାଇଁ 1M"</item> <item msgid="1984761927103140651">"ଲଗ୍ ବଫର୍ ପ୍ରତି 4M"</item> <item msgid="2983219471251787208">"ଲଗ୍ ବଫର୍ ପ୍ରତି 8M"</item> </string-array> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 3cbbc054e863..360810a7de4d 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ସକ୍ରିୟ, କେବଳ ବାମ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ସକ୍ରିୟ, କେବଳ ଡାହାଣ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ସକ୍ରିୟ, ବାମ ଏବଂ ଡାହାଣ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ) <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ବେଟେରୀ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"କନେକ୍ଟ ହୋଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"କନେକ୍ଟ ହୋଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ବେଟେରୀ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"କନେକ୍ଟ ହୋଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ), ବାମ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"କନେକ୍ଟ ହୋଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ), ଡାହାଣ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ବାମ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ଡାହାଣ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), ବାମ ଏବଂ ଡାହାଣ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ମିଡିଆ ଅଡିଓ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ଫୋନ୍ କଲ୍ଗୁଡ଼ିକ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 2105852951c9..cbfef1e56a53 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਖੱਬਾ"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਸੱਜਾ"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ਕਿਰਿਆਸ਼ੀਲ, ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਖੱਬਾ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ਬੈਟਰੀ, ਸੱਜਾ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ), ਖੱਬਾ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ਬੈਟਰੀ, ਸੱਜਾ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ), ਖੱਬਾ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ), ਸੱਜਾ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਖੱਬਾ"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਸੱਜਾ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ਮੀਡੀਆ ਆਡੀਓ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ਫ਼ੋਨ ਕਾਲਾਂ"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string> @@ -506,7 +495,7 @@ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string> <string name="battery_info_status_not_charging" msgid="1103084691314264664">"ਕਨੈਕਟ ਹੋ ਗਿਆ, ਪਰ ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ ਹੈ"</string> - <string name="battery_info_status_full" msgid="1339002294876531312">"ਚਾਰਜ ਹੋ ਗਈ"</string> + <string name="battery_info_status_full" msgid="1339002294876531312">"ਬੈਟਰੀ ਚਾਰਜ ਹੋ ਗਈ"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ਪੂਰੀ ਚਾਰਜ ਹੋ ਗਈ ਹੈ"</string> <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਜਾਂ ਹੋਰ ਸਮਾਂ-ਸੰਵੇਦਨਸ਼ੀਲ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦਿਓ। ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਦੀ ਇਜਾਜ਼ਤ ਮਿਲਦੀ ਹੈ, ਜਿਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵੱਧ ਸਕਦੀ ਹੈ।\n\nਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੈ, ਤਾਂ ਮੌਜੂਦਾ ਅਲਾਰਮ ਅਤੇ ਇਸ ਐਪ ਰਾਹੀਂ ਨਿਯਤ ਕੀਤੇ ਸਮਾਂ-ਆਧਾਰਿਤ ਇਵੈਂਟ ਕੰਮ ਨਹੀਂ ਕਰਨਗੇ।"</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਜਾਂ ਹੋਰ ਸਮਾਂ-ਸੰਵੇਦਨਸ਼ੀਲ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦਿਓ। ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਦੀ ਇਜਾਜ਼ਤ ਮਿਲਦੀ ਹੈ, ਜਿਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵੱਧ ਸਕਦੀ ਹੈ।\n\nਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੈ, ਤਾਂ ਇਸ ਐਪ ਰਾਹੀਂ ਨਿਯਤ ਕੀਤੇ ਮੌਜੂਦਾ ਅਲਾਰਮ ਅਤੇ ਸਮਾਂ-ਆਧਾਰਿਤ ਇਵੈਂਟ ਕੰਮ ਨਹੀਂ ਕਰਨਗੇ।"</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ਸਮਾਂ-ਸੂਚੀ, ਅਲਾਰਮ, ਰਿਮਾਈਂਡਰ, ਘੜੀ"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ਚਾਲੂ ਕਰੋ"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਚਾਲੂ ਕਰੋ"</string> @@ -709,7 +698,7 @@ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string> <string name="turn_screen_on_title" msgid="3266937298097573424">"ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰੋ"</string> <string name="allow_turn_screen_on" msgid="6194845766392742639">"ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰਨ ਦਿਓ"</string> - <string name="allow_turn_screen_on_description" msgid="43834403291575164">"ਐਪ ਨੂੰ ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰਨ ਦਿਓ। ਜੇ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਐਪ ਕਿਸੇ ਵੀ ਸਮੇਂ ਸਕ੍ਰੀਨ ਨੂੰ ਚਾਲੂ ਕਰ ਸਕਦੀ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਨੂੰ ਇਸਦੀ ਲੋੜ ਨਾ ਹੋਵੇ।"</string> + <string name="allow_turn_screen_on_description" msgid="43834403291575164">"ਐਪ ਨੂੰ ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰਨ ਦਿਓ। ਇਜਾਜ਼ਤ ਦਿੱਤੇ ਜਾਣ \'ਤੇ, ਇਹ ਐਪ ਤੁਹਾਡੇ ਇਰਾਦੇ ਦੇ ਬਿਨਾਂ ਕਿਸੇ ਵੇਲੇ ਵੀ ਸਕ੍ਰੀਨ ਨੂੰ ਚਾਲੂ ਕਰ ਸਕਦੀ ਹੈ।"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਦੇ ਪ੍ਰਸਾਰਨ ਨੂੰ ਰੋਕਣਾ ਹੈ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ਜੇ ਤੁਸੀਂ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰਦੇ ਹੋ ਜਾਂ ਆਊਟਪੁੱਟ ਬਦਲਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਪ੍ਰਸਾਰਨ ਰੁਕ ਜਾਵੇਗਾ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰੋ"</string> diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml index 5358ed8f6061..9c25aaa41b63 100644 --- a/packages/SettingsLib/res/values-pl/arrays.xml +++ b/packages/SettingsLib/res/values-pl/arrays.xml @@ -186,10 +186,10 @@ </string-array> <string-array name="select_logd_size_summaries"> <item msgid="409235464399258501">"Wył."</item> - <item msgid="4195153527464162486">"64 KB/bufor dziennika"</item> - <item msgid="7464037639415220106">"256 KB/bufor dziennika"</item> - <item msgid="8539423820514360724">"1 MB/bufor dziennika"</item> - <item msgid="1984761927103140651">"4 MB/bufor dziennika"</item> + <item msgid="4195153527464162486">"64 KB / bufor dziennika"</item> + <item msgid="7464037639415220106">"256 KB / bufor dziennika"</item> + <item msgid="8539423820514360724">"1 MB / bufor dziennika"</item> + <item msgid="1984761927103140651">"4 MB / bufor dziennika"</item> <item msgid="2983219471251787208">"8 MB na bufor dziennika"</item> </string-array> <string-array name="select_logpersist_titles"> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 93e65afeb768..22015b363394 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -106,35 +106,24 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywne, tylko lewa strona"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywne, tylko prawa strona"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktywny, lewa i prawa strona"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktywne (tylko multimedia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktywne (tylko multimedia), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Połączone (obsługa udostępniania dźwięku), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Połączone (obsługa udostępniania dźwięku), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Połączone (obsługa udostępniania dźwięku), lewa <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Połączone (obsługa udostępniania dźwięku), prawa <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktywne (tylko multimedia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Obsługa udostępniania dźwięku"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktywne (tylko multimedia), tylko lewa"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktywne (tylko multimedia), tylko prawa"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktywne (tylko multimedia), lewa i prawa"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Dźwięk multimediów"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Połączenia telefoniczne"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Przesyłanie pliku"</string> <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Urządzenie wejściowe"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Dostęp do internetu"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Zezwól na dostęp do kontaktów i historii połączeń"</string> - <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Informacje zostaną wykorzystane do powiadomień i nie tylko"</string> + <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Informacje zostaną wykorzystane m.in. do powiadomień o połączeniach"</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Udostępnianie połączenia internetowego"</string> <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-y"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostęp do karty SIM"</string> @@ -336,7 +325,7 @@ <string name="wifi_metered_label" msgid="8737187690304098638">"Użycie danych jest mierzone"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Użycie danych nie jest mierzone"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Rozmiary bufora rejestratora"</string> - <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Wybierz rozmiary Rejestratora/bufor dziennika"</string> + <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Wybierz rozmiary Rejestratora na bufor dziennika"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Wyczyścić pamięć trwałych dzienników?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Po zakończeniu monitorowania przy użyciu trwale zapisywanych dzienników musimy usunąć ich dane zapisane na urządzeniu."</string> <string name="select_logpersist_title" msgid="447071974007104196">"Zapisuj trwale dane dzienników na urządzeniu"</string> @@ -505,7 +494,7 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ładowanie bezprzewodowe"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ładowanie"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nie podłączony"</string> - <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Podłączono, ale nie ładuje się"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Podłączono, brak ładowania"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Naładowana"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Bateria w pełni naładowana"</string> <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ładowanie wstrzymane"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 811c04a0a8fa..d1feae47aaa3 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Ativo (apenas mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Ativo (apenas mídia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Conectado (com suporte ao compartilhamento de áudio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Conectado (com suporte ao compartilhamento de áudio), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Conectado (com suporte ao compartilhamento de áudio), esquerdo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Conectado (com suporte ao compartilhamento de áudio), direito <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas mídia), somente direito"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas mídia), esquerdo e direito"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Áudio da mídia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefônicas"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 4c88683a6a7e..444ce6696d6c 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -106,35 +106,24 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas esquerdo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas direito"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Ativo (apenas para multimédia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Ativo (apenas para multimédia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Ligado (suporta partilha de áudio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Ligado (suporta partilha de áudio), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Ligado (suporta partilha de áudio), esquerdo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Ligado (suporta partilha de áudio), direito <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas para multimédia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Suporta partilha de áudio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas para multimédia), apenas esquerdo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas para multimédia), apenas direito"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas para multimédia), esquerdo e direito"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Áudio de multimédia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefónicas"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência do ficheiro"</string> <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à internet"</string> <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Acesso a contactos e histórico de chamadas"</string> - <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"As informações são usadas para anúncios de chamadas e outros"</string> + <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"As informações são usadas para anúncios por chamadas e outros"</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partilha da ligação à internet"</string> <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao SIM"</string> @@ -410,7 +399,7 @@ <string name="force_msaa_summary" msgid="9070437493586769500">"Ativar o 4x MSAA em aplicações OpenGL ES 2.0"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de clipe não retangulares"</string> <string name="track_frame_time" msgid="522674651937771106">"Renderização HWUI do perfil"</string> - <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar cam. depuração GPU"</string> + <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar camadas de depuração GPU"</string> <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite carregamento de camadas de depuração de GPU para apps de depuração"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Ativ. registo do fornecedor"</string> <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclua registos adicionais de fornecedores específicos de dispositivos em relatórios de erros, que podem conter informações privadas, utilizar mais bateria e/ou utilizar mais armazenamento."</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir alarmes e lembretes"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que esta app defina alarmes e agende outras ações com base no tempo. Esta ação permite que a app seja executada em segundo plano, o que pode utilizar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que a app defina alarmes e agende ações com um horário específico. Esta ação permite que a app seja executada em segundo plano, o que pode usar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o modo Não incomodar"</string> @@ -595,7 +584,7 @@ <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Altifalantes internos"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string> - <string name="help_label" msgid="3528360748637781274">"Ajuda e comentários"</string> + <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string> <string name="storage_category" msgid="2287342585424631813">"Armazenamento"</string> <string name="shared_data_title" msgid="1017034836800864953">"Dados partilhados"</string> <string name="shared_data_summary" msgid="5516326713822885652">"Ver e modificar dados partilhados"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 811c04a0a8fa..d1feae47aaa3 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Ativo (apenas mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Ativo (apenas mídia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Conectado (com suporte ao compartilhamento de áudio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Conectado (com suporte ao compartilhamento de áudio), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Conectado (com suporte ao compartilhamento de áudio), esquerdo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Conectado (com suporte ao compartilhamento de áudio), direito <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas mídia), somente direito"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas mídia), esquerdo e direito"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Áudio da mídia"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefônicas"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 1233afd7a897..06e61ca2d753 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activ, numai stânga"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activ, numai dreapta"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activ, stânga și dreapta"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Activ (numai pentru conținut media), nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Activ (numai pentru conținut media): nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Conectat (acceptă permiterea accesului la audio), nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Conectat (acceptă permiterea accesului la audio), nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Conectat (acceptă permiterea accesului la audio), nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Conectat (acceptă permiterea accesului la audio), nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activ (numai pentru conținut media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Acceptă permiterea accesului la audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activ (numai pentru conținut media), numai stânga"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activ (numai pentru conținut media), numai dreapta"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activ (numai pentru conținut media), stânga și dreapta"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Conținut media audio"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Apeluri telefonice"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer de fișiere"</string> @@ -553,7 +542,7 @@ <string name="okay" msgid="949938843324579502">"OK"</string> <string name="done" msgid="381184316122520313">"Gata"</string> <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string> - <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string> + <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea de alarme și mementouri"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string> <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 43645f411112..8bb5b19aa038 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активен, только левое ухо"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активен, только правое ухо"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активен, оба уха"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Подключено (поддерживается отправка аудио), заряд левого наушника: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Подключено (поддерживается отправка аудио), заряд правого наушника: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Используется (только для медиа)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддерживается отправка аудио"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Используется (только для медиа), левый наушник"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Используется (только для медиа), правый наушник"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Используется (только для медиа), левый и правый наушники"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Профиль A2DP"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Звонки"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Профиль OPP"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index d965b738a735..074028c0e57f 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"සක්රිය, වම පමණි"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"සක්රිය, දකුණ පමණි"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"සක්රිය, වම සහ දකුණ"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"සක්රිය (මාධ්ය පමණි), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> බැටරිය"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"සක්රිය (මාධ්ය පමණි), ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> බැටරිය, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> බැටරිය"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීම සහය දක්වයි), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> බැටරිය"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීම සහය දක්වයි), ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> බැටරිය, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> බැටරිය"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීම සහය දක්වයි), වම <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීම සහය දක්වයි), දකුණ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"සක්රිය (මාධ්ය පමණි)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ශ්රව්ය බෙදා ගැනීම සහය දක්වයි"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"සක්රිය (මාධ්ය පමණි), වම පමණි"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"සක්රිය (මාධ්ය පමණි), දකුණ පමණි"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"සක්රිය (මාධ්ය පමණි), වම සහ දකුණ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"මාධ්ය ශ්රව්ය"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"දුරකථන ඇමතුම්"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ගොනු හුවමාරුව"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 77c265e4136f..dab6e97a9fa5 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktívne, iba ľavá strana"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktívne, iba pravá strana"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktívne, ľavá aj pravá strana"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktívne (iba médiá), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktívne (iba médiá), Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Pripojené (podporuje zdieľanie zvuku), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Pripojené (podporuje zdieľanie zvuku), Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Pripojené (podporuje zdieľanie zvuku), ľavá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Pripojené (podporuje zdieľanie zvuku), pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktívne (iba médiá)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje zdieľanie zvuku"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktívne (iba médiá), iba ľavá strana"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktívne (iba médiá), iba pravá strana"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktívne (iba médiá), ľavá aj pravá strana"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk médií"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonické hovory"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos súborov"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciou nebudú fungovať."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index abca26f03cbf..b8422038b300 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo levo"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, levo in desno"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktivno (samo predstavnost), napolnjenost baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktivno (samo predstavnost), napolnjenost leve baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, napolnjenost desne baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Povezano (podpira deljenje zvoka), napolnjenost baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Povezano (podpira deljenje zvoka), napolnjenost leve baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, napolnjenost desne baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Povezano (podpira deljenje zvoka), napolnjenost leve baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Povezano (podpira deljenje zvoka), napolnjenost desne baterije: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo predstavnost)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podpira deljenje zvoka"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo predstavnost), samo levo"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo predstavnost), samo desno"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo predstavnost), levo in desno"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvok predstavnosti"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski klici"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 0f48e42c95e4..54ea2e7b46db 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktive, vetëm majtas"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktive, vetëm djathtas"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktive, majtas dhe djathtas"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiv (vetëm për media), bateria në <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiv (vetëm për media), majtas: bateria në <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, djathtas: bateria në <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Lidhur (mbështet ndarjen e audios), bateria në <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Lidhur (mbështet ndarjen e audios), majtas: bateria në <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, djathtas: bateria në <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Lidhur (mbështet ndarjen e audios), majtas <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Lidhur (mbështet ndarjen e audios), djathtas <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (vetëm për media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mbështet ndarjen e audios"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (vetëm për media), vetëm majtas"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (vetëm për media), vetëm djathtas"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (vetëm për media), majtas dhe djathtas"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audioja e medias"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonatat"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferimi i skedarëve"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index d309036cabdf..3df0824f0cf2 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само с леве стране"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, с десне стране"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, с леве и десне стране"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Активан (само за медије), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Активан (само за медије), лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерије, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Повезан (подржава дељење звука), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Повезан (подржава дељење звука), лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерије, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Повезан (подржава дељење звука), лево <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Повезан (подржава дељење звука), десно <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активан (само за медије)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Подржава дељење звука"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активан (само за медије), само лево"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активан (само за медије), само десно"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активан (само за медије), лево и десно"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Звук медија"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонски позиви"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос датотеке"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 363396a02c33..2a57893ceb43 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bara vänster"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bara höger"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, vänster och höger"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktiv (endast media), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktiv (endast media), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Ansluten (ljuddelning stöds), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Ansluten (ljuddelning stöds), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Ansluten (ljuddelning stöds), vänster <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Ansluten (ljuddelning stöds), höger <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (endast media)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ljuddelning stöds"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (endast media), endast vänster"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (endast media), endast höger"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (endast media), vänster och höger"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medialjud"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonsamtal"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filöverföring"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index ebff38bbd994..ab518d00b8b4 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Inatumika, kushoto pekee"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Inatumika, kulia pekee"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Inatumika, kushoto na kulia"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Inatumika (maudhui pekee), chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Inatumika (maudhui pekee), Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja), chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja), Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja), chaji ya betri ya kushoto imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja), chaji ya betri ya kulia imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Inatumika (maudhui pekee)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Inaweza kutumia kipengele cha kusikiliza pamoja"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Inatumika (maudhui pekee), kushoto pekee"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Inatumika (maudhui pekee), kulia pekee"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Inatumika (maudhui pekee), kushoto na kulia"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Sauti ya maudhui"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Simu"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Uhamishaji wa faili"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 1648de0dc03a..1462b7368ef7 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"இடது பக்கம் மட்டும் செயலில் உள்ளது"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"வலது பக்கம் மட்டும் செயலில் உள்ளது"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"வலது மற்றும் இடது பக்கம் செயலில் உள்ளது"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"செயலிலுள்ளது (மீடியா மட்டும்), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"செயலிலுள்ளது (மீடியா மட்டும்), இடது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> பேட்டரி, வலது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> பேட்டரி"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது), இடது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> பேட்டரி, வலது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> பேட்டரி"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது), இடது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது), வலது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"செயலிலுள்ளது (மீடியா மட்டும்)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ஆடியோ பகிர்வை ஆதரிக்கிறது"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மட்டும்"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"செயலிலுள்ளது (மீடியா மட்டும்), வலதுபுறம் மட்டும்"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மற்றும் வலதுபுறம்"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"மீடியா ஆடியோ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ஃபோன் அழைப்புகள்"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ஃபைல் இடமாற்றம்"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 7ee57cf95c75..718442c6ceac 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"యాక్టివ్గా ఉంది, ఎడమవైపు మాత్రమే యాక్టివ్గా ఉంది"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"యాక్టివ్గా ఉంది, కుడివైపు యాక్టివ్గా ఉంది"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"యాక్టివ్గా ఉంది, ఎడమవైపు, కుడివైపు యాక్టివ్గా ఉంది"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"యాక్టివ్ (మీడియా మాత్రమే), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది), ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది), ఎడమ వైపు <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది), కుడివైపు <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"యాక్టివ్ (మీడియా మాత్రమే)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ వైపు మాత్రమే"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"యాక్టివ్ (మీడియా మాత్రమే), కుడివైపు మాత్రమే"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ, కుడివైపు మాత్రమే"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"మీడియా ఆడియో"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ఫోన్ కాల్స్"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ఫైల్ బదిలీ"</string> @@ -162,8 +151,8 @@ <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ఇన్పుట్ కోసం ఉపయోగించండి"</string> <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"వినికిడి పరికరాల కోసం ఉపయోగించండి"</string> <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO కోసం ఉపయోగించండి"</string> - <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"జత చేయి"</string> - <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"జత చేయి"</string> + <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"పెయిర్ చేయండి"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"పెయిర్ చేయండి"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"రద్దు చేయండి"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"పెయిర్ చేయడం వలన కనెక్ట్ చేయబడినప్పుడు మీ కాంటాక్ట్లకు అలాగే కాల్ హిస్టరీకి యాక్సెస్ను మంజూరు చేస్తుంది."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string> @@ -201,7 +190,7 @@ <string name="running_process_item_user_label" msgid="3988506293099805796">"యూజర్: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> <string name="launch_defaults_some" msgid="3631650616557252926">"కొన్ని ఆటోమేటిక్ సెట్టింగ్లు సెట్ చేయబడ్డాయి"</string> <string name="launch_defaults_none" msgid="8049374306261262709">"ఆటోమేటిక్ ఆప్షన్లు ఏవీ సెట్ చేయలేదు"</string> - <string name="tts_settings" msgid="8130616705989351312">"వచనం నుండి ప్రసంగం సెట్టింగ్లు"</string> + <string name="tts_settings" msgid="8130616705989351312">"టెక్స్ట్-టు-స్పీచ్ సెట్టింగ్లు"</string> <string name="tts_settings_title" msgid="7602210956640483039">"టెక్స్ట్-టు-స్పీచ్ అవుట్పుట్"</string> <string name="tts_default_rate_title" msgid="3964187817364304022">"స్పీచ్ రేట్"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"వచనాన్ని చదివి వినిపించాల్సిన వేగం"</string> @@ -339,7 +328,7 @@ <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"లాగ్ బఫర్కి లాగర్ పరిమా. ఎంచుకోండి"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"లాగర్ నిరంతర నిల్వలోని డేటాను తీసివేయాలా?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"మేము నిరంతర లాగర్తో ఇక పర్యవేక్షించనప్పుడు, మీ పరికరంలోని లాగర్ డేటాను మేము తొలగించాల్సి ఉంటుంది."</string> - <string name="select_logpersist_title" msgid="447071974007104196">"పరికరంలో లాగర్ డేటా నిరంతరం స్టోర్ చేయి"</string> + <string name="select_logpersist_title" msgid="447071974007104196">"పరికరంలో లాగర్ డేటా నిరంతరం స్టోర్ చేయండి"</string> <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"పరికరంలో నిరంతరం స్టోరేజ్ చేయాల్సిన లాగ్ బఫర్లను ఎంచుకోండి"</string> <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB కాన్ఫిగరేషన్ని ఎంచుకోండి"</string> <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB కాన్ఫిగరేషన్ని ఎంచుకోండి"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"అలారాలు, రిమైండర్లు"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"అలారాలు, రిమైండర్లను సెట్ చేయడానికి అనుమతించండి"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"అలారాలు & రిమైండర్లు"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"అలారాలను సెట్ చేయడానికి, సమయ-సునిశిత చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. ఇది యాప్ను బ్యాక్గ్రౌండ్లో రన్ అవడానికి అనుమతిస్తుంది, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు.\n\nఈ అనుమతిని ఆఫ్ చేస్తే, ఈ యాప్ ద్వారా షెడ్యూల్ చేసిన ఇప్పటికే ఉన్న అలారాలు, సమయ-ఆధారిత ఈవెంట్లు పనిచేయవు."</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"అలారాలను సెట్ చేయడానికి, టైమ్-సెన్సిటివ్ చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. ఇది యాప్ను బ్యాక్గ్రౌండ్లో రన్ అవడానికి అనుమతిస్తుంది, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు.\n\nఈ అనుమతిని ఆఫ్ చేస్తే, ఈ యాప్ ద్వారా షెడ్యూల్ చేసినటువంటి ఇప్పటికే ఉన్న అలారాలు, టైమ్-ఆధారిత ఈవెంట్లు పనిచేయవు."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"షెడ్యూల్, అలారం, రిమైండర్, గడియారం"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ఆన్ చేయండి"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"అంతరాయం కలిగించవద్దును ఆన్ చేయండి"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 55b57db0a884..6cbed5a8e5fa 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ใช้งานอยู่ เฉพาะข้างซ้าย"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ใช้งานอยู่ เฉพาะข้างขวา"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ใช้งานอยู่ ข้างซ้ายและขวา"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"ใช้งานอยู่ (สื่อเท่านั้น), แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"ใช้งานอยู่ (สื่อเท่านั้น), L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง), แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง), L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง), ซ้าย <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง), ขวา <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ใช้งานอยู่ (สื่อเท่านั้น)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"รองรับการแชร์เสียง"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายเท่านั้น"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ใช้งานอยู่ (สื่อเท่านั้น), ขวาเท่านั้น"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายและขวา"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"เสียงของสื่อ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"โทรศัพท์"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"การถ่ายโอนไฟล์"</string> @@ -203,7 +192,7 @@ <string name="launch_defaults_none" msgid="8049374306261262709">"ไม่ได้ตั้งค่าเริ่มต้น"</string> <string name="tts_settings" msgid="8130616705989351312">"การตั้งค่าการอ่านออกเสียงข้อความ"</string> <string name="tts_settings_title" msgid="7602210956640483039">"เอาต์พุตการอ่านออกเสียงข้อความ"</string> - <string name="tts_default_rate_title" msgid="3964187817364304022">"ความเร็วของคำพูด"</string> + <string name="tts_default_rate_title" msgid="3964187817364304022">"ความเร็วในการพูด"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"ความเร็วในการพูดข้อความ"</string> <string name="tts_default_pitch_title" msgid="6988592215554485479">"ความสูง-ต่ำของเสียง"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"มีผลต่อโทนเสียงของข้อความสังเคราะห์"</string> @@ -487,7 +476,7 @@ <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> เมื่อดูจากการใช้งานของคุณ"</string> <string name="power_discharge_by" msgid="4113180890060388350">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_discharge_by_only" msgid="92545648425937000">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="power_discharge_by_only_short" msgid="5883041507426914446">"จนถึง <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_discharge_by_only_short" msgid="5883041507426914446">"จนถึง <xliff:g id="TIME">%1$s</xliff:g> น."</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"แบตเตอรี่อาจหมดภายใน <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"เหลือน้อยกว่า <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration" msgid="318215464914990578">"เหลือน้อยกว่า <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index c34588d4c49d..db07e7a21a4a 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, kaliwa lang"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, kanan lang"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, kaliwa at kanan"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Aktibo (media lang), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Aktibo (media lang), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterya, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Nakakonekta (sinusuportahan ang pag-share ng audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Nakakonekta (sinusuportahan ang pag-share ng audio), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterya, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Nakakonekta (sinusuportahan ang pag-share ng audio), kaliwa <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Nakakonekta (sinusuportahan ang pag-share ng audio), kanan <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (media lang)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Sinusuportahan ang pag-share ng audio"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (media lang), kaliwa lang"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktibo (media lang), kanan lang"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktibo (media lang), kaliwa at kanan"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio ng media"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Mga tawag sa telepono"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Paglilipat ng file"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 4315241763fa..4a6e90395873 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Yalnızca sol tarafta etkin"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Yalnızca sağ tarafta etkin"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Sol ve sağ tarafta etkin"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Etkin (yalnızca medya), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Etkin (yalnızca medya), Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pil seviyesi, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Bağlı (ses paylaşımını destekler), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Bağlı (ses paylaşımını destekler), Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pil seviyesi, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Bağlı (ses paylaşımını destekler), sol <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Bağlı (ses paylaşımını destekler), sağ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Etkin (yalnızca medya)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ses paylaşımını destekler"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Etkin (yalnızca medya), yalnızca sol"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Etkin (yalnızca medya), yalnızca sağ"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Etkin (yalnızca medya), sol ve sağ"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medya sesi"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefon aramaları"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dosya aktarımı"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index ac9edc58f057..ec1f7f54e2ed 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активовано, лише лівий"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активовано, лише правий"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активовано, лівий і правий"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Активно (лише для мультимедіа); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Активно (лише для мультимедіа); лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> заряду акумулятора, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Підключено (підтримує надсилання аудіо); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Підключено (підтримує надсилання аудіо); лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> заряду акумулятора, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Підключено (підтримує надсилання аудіо); лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Підключено (підтримує надсилання аудіо); правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (лише для мультимедіа)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Підтримує надсилання аудіо"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (лише для мультимедіа); лише лівий"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (лише для мультимедіа); лише правий"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (лише для мультимедіа); лівий і правий"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Звук медіафайлів"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонні дзвінки"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Передавання файлів"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index d2fc32a44c75..db8c42739f56 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، صرف بائیں طرف"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، صرف دائیں طرف"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، صرف بائیں اور دائیں طرف"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"فعال (صرف میڈیا)، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"فعال (صرف میڈیا)، L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> بیٹری، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)، L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> بیٹری، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)، بائیں <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)، دائیں <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (صرف میڈیا)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"آڈیو کے اشتراک کو سپورٹ کرتا ہے"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (صرف میڈیا)، صرف بائیں"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"فعال (صرف میڈیا)، صرف دائیں"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"فعال (صرف میڈیا)، بائیں اور دائیں"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"میڈيا آڈیو"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"فون کالز"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"فائل کی منتقلی"</string> @@ -487,7 +476,7 @@ <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string> <string name="power_discharge_by" msgid="4113180890060388350">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_discharge_by_only" msgid="92545648425937000">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string> - <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> تک"</string> + <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> تک"</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> تک بیٹری ختم ہو سکتی ہے"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string> <string name="power_remaining_less_than_duration" msgid="318215464914990578">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 3c8e249a1900..2355fc966acf 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Faol, faqat chap"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Faol, faqat oʻng"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Faol, chap va oʻng"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Faol (faqat media uchun), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Faol (faqat media uchun), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (chap)"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (oʻng)"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Faol (faqat media uchun)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio yuborishi mumkin"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Faol (faqat media uchun), faqat chap"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Faol (faqat media uchun), faqat oʻng"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Faol (faqat media uchun), chap va oʻng"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"A2DP profili"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefon chaqiruvlari"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl uzatish"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index b3d70cc66500..2427bea4a9fb 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Đang hoạt động, chỉ tai bên trái"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Đang hoạt động, chỉ tai phải"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Đang hoạt động, cả tai phải và tai trái"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Đang hoạt động (chỉ phát nội dung đa phương tiện), pin còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Đang hoạt động (chỉ phát nội dung đa phương tiện), L: pin còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: pin còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh), pin còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh), L: pin còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: pin còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh), tai nghe bên trái còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh), tai nghe bên phải còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Đang hoạt động (chỉ phát nội dung đa phương tiện)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Hỗ trợ tính năng chia sẻ âm thanh"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên trái"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên phải"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Đang hoạt động (chỉ phát nội dung đa phương tiện), đang dùng cả tai nghe bên trái và phải"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Âm thanh nội dung nghe nhìn"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Cuộc gọi điện thoại"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Chuyển tệp"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 6a9a18caeca4..c3e9e20826b4 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,仅左耳助听器"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,仅右耳助听器"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳助听器"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"使用中(仅限媒体),电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"使用中(仅限媒体),左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"已连接(支持音频分享),电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"已连接(支持音频分享),左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"已连接(支持音频分享),左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"已连接(支持音频分享),右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"使用中(仅限媒体)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支持音频分享"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"使用中(仅限媒体),仅左侧"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"使用中(仅限媒体),仅右侧"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"使用中(仅限媒体),左侧和右侧"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"媒体音频"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"通话"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"文件传输"</string> @@ -472,7 +461,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"“色彩校正”功能适用于以下情况:<br/> <ol> <li>您想更准确地查看颜色</li> <li>您想移除颜色以提高专注程度</li> </ol>"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"“色彩校正”功能适用于以下情况:<br/> <ol> <li>您想更准确地查看颜色</li> <li>您想移除颜色以提高专注度</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - 为保护电池,已暂停充电"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index ecdfa62b3acc..cc1dc11ddcb2 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"啟用 (只限媒體),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"啟用 (只限媒體),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"已連線 (支援音訊分享功能),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"已連線 (支援音訊分享功能),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"已連線 (支援音訊分享功能),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"已連線 (支援音訊分享功能),右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (只限媒體)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享功能"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (只限媒體)"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"右側啟用 (只限媒體)"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"右側同時啟用 (只限媒體)"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"媒體音效"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"通話"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 99fe41eebd99..26b79076aa1d 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"啟用 (僅限媒體),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 剩餘電力"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"啟用 (僅限媒體),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 剩餘電力,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 剩餘電力"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"已連線 (支援音訊分享),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 剩餘電力"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"已連線 (支援音訊分享),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 剩餘電力,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 剩餘電力"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"已連線 (支援音訊分享),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"已連線 (支援音訊分享),右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (僅限媒體)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (僅限媒體)"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"右側啟用 (僅限媒體)"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"左右側同時啟用 (僅限媒體)"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"媒體音訊"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"通話"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string> @@ -555,7 +544,7 @@ <string name="alarms_and_reminders_label" msgid="6918395649731424294">"鬧鐘與提醒"</string> <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"允許設定鬧鐘和提醒"</string> <string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string> - <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允許這個應用程式設定鬧鐘及安排有時效性的動作。這麼做會讓用程式在背景執行,可能比較耗電。\n\n如果關閉這項權限,這個應用程式設定的現有鬧鐘將不會響起,而且應用程式也無法在預定的時間發出活動提醒。"</string> + <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允許這個應用程式設定鬧鐘及安排有時效性的動作。之後應用程式可以在背景執行,並可能耗用較多電量。\n\n如果關閉這項權限,這個應用程式設定的現有鬧鐘將不會響起,系統也無法在預定的時間發出活動提醒。"</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"時間表, 鬧鐘, 提醒, 時鐘"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"開啟"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"開啟「零打擾」模式"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 6f06e1ffb391..d42202db2b73 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -106,28 +106,17 @@ <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Iyasebenza, ngakwesokunxele kuphela"</string> <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Iyasebenza, ngakwesokudla kuphela"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Iyasebenza, ngakwesokunxele nakwesokudla"</string> - <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) --> - <skip /> - <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) --> - <skip /> - <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) --> - <skip /> - <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) --> - <skip /> - <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) --> - <skip /> + <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Ibhethri (imidiya kuphela), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> liyasebenza"</string> + <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Liyasebenza (imidiya kuphela), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ibhethri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri"</string> + <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> webhethri"</string> + <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> webhethri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> webhethri"</string> + <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe), ngakwesokunxele ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe), ngakwesokudla ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Kuyasebenza (imidiya kuphela)"</string> + <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Isekela ukwabelana ngokuqoshiwe"</string> + <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Iyasebenza (imidiya kuphela), ngakwesokunxele kuphela"</string> + <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Kuyasebenza (imidiya kuphela), ngakwesokudla kuphela"</string> + <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Kuyasebenza (imidiya kuphela), ngakwesokunxele nakwesokudla"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Umsindo wemidiya"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Amakholi efoni"</string> <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dlulisa ifayela"</string> diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml index 2bd4d023cd72..ab049042b5f9 100644 --- a/packages/SettingsLib/res/values/dimens.xml +++ b/packages/SettingsLib/res/values/dimens.xml @@ -82,7 +82,6 @@ <dimen name="add_a_photo_circled_padding">6dp</dimen> <dimen name="user_photo_size_in_user_info_dialog">112dp</dimen> <dimen name="add_a_photo_icon_size_in_user_info_dialog">32dp</dimen> - <dimen name="user_name_height_in_user_info_dialog">48sp</dimen> <!-- Minimum increment between density scales. --> <fraction name="display_density_min_scale_interval">9%</fraction> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 7e6b004be9b8..fbbed921de1d 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1148,6 +1148,16 @@ <!-- [CHAR_LIMIT=80] Label for battery charging future pause --> <string name="power_charging_future_paused"><xliff:g id="level">%1$s</xliff:g> - Charging</string> + <!-- [CHAR_LIMIT=40] Label for battery level when fast charging with duration. --> + <string name="power_fast_charging_duration_v2"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="status">%2$s</xliff:g> - Full by <xliff:g id="time">%3$s</xliff:g></string> + <!-- [CHAR_LIMIT=40] Label for battery level when non-fast charging with duration. --> + <string name="power_charging_duration_v2"><xliff:g id="level">%1$s</xliff:g> - Fully charged by <xliff:g id="time">%2$s</xliff:g></string> + + <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging. --> + <string name="power_remaining_charging_duration_only_v2">Fully charged by <xliff:g id="time">%1$s</xliff:g></string> + <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging. --> + <string name="power_remaining_fast_charging_duration_only_v2">Full by <xliff:g id="time">%1$s</xliff:g></string> + <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed --> <string name="battery_info_status_unknown">Unknown</string> <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging from an unknown source. --> @@ -1171,6 +1181,11 @@ <!-- [CHAR_LIMIT=None] Battery Info screen. Value for a status item. A state which device charging on hold --> <string name="battery_info_status_charging_on_hold">Charging on hold</string> + <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging isn't fast. --> + <string name="battery_info_status_charging_v2">Charging</string> + <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging speed is fast. --> + <string name="battery_info_status_charging_fast_v2">Fast charging</string> + <!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] --> <string name="disabled_by_admin_summary_text">Controlled by admin</string> @@ -1658,6 +1673,8 @@ <string name="accessibility_phone_two_bars">Phone two bars.</string> <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_three_bars">Phone three bars.</string> + <!-- Content description of the phone signal when it is four bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_four_bars">Phone four bars.</string> <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_signal_full">Phone signal full.</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java index ce466dfbf19c..9073d281c4a9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java +++ b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java @@ -33,6 +33,59 @@ public class AccessibilityContentDescriptions { R.string.accessibility_phone_signal_full }; + /** + * @param level int in range [0-4] that describes the signal level + * @return the appropriate content description for that signal strength, or 0 if the param is + * invalid + */ + public static int getDescriptionForLevel(int level) { + if (level > 4 || level < 0) { + return 0; + } + + return PHONE_SIGNAL_STRENGTH[level]; + } + + public static final int[] PHONE_SIGNAL_STRENGTH_INFLATED = { + PHONE_SIGNAL_STRENGTH_NONE, + R.string.accessibility_phone_one_bar, + R.string.accessibility_phone_two_bars, + R.string.accessibility_phone_three_bars, + R.string.accessibility_phone_four_bars, + R.string.accessibility_phone_signal_full + }; + + /** + * @param level int in range [0-5] that describes the inflated signal level + * @return the appropriate content description for that signal strength, or 0 if the param is + * invalid + */ + public static int getDescriptionForInflatedLevel(int level) { + if (level > 5 || level < 0) { + return 0; + } + + return PHONE_SIGNAL_STRENGTH_INFLATED[level]; + } + + /** + * @param level int in range [0-5] that describes the inflated signal level + * @param numberOfLevels one of (4, 5) that describes the default number of levels, or the + * inflated number of levels. The level param should be relative to the + * number of levels. This won't do any inflation. + * @return the appropriate content description for that signal strength, or 0 if the param is + * invalid + */ + public static int getDescriptionForLevel(int level, int numberOfLevels) { + if (numberOfLevels == 5) { + return getDescriptionForLevel(level); + } else if (numberOfLevels == 6) { + return getDescriptionForInflatedLevel(level); + } else { + return 0; + } + } + public static final int[] DATA_CONNECTION_STRENGTH = { R.string.accessibility_no_data, R.string.accessibility_data_one_bar, diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index e95a506376fd..563f02d95f3c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -65,6 +65,7 @@ import com.android.launcher3.icons.IconFactory; import com.android.launcher3.util.UserIconInfo; import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.fuelgauge.BatteryStatus; +import com.android.settingslib.fuelgauge.BatteryUtils; import com.android.settingslib.utils.BuildCompatUtils; import java.util.List; @@ -246,25 +247,23 @@ public class Utils { } else { if (status == BatteryManager.BATTERY_STATUS_CHARGING) { if (compactStatus) { - statusString = res.getString(R.string.battery_info_status_charging); + statusString = getRegularChargingStatusString(res); } else if (batteryStatus.isPluggedInWired()) { switch (batteryStatus.getChargingSpeed(context)) { case BatteryStatus.CHARGING_FAST: - statusString = - res.getString(R.string.battery_info_status_charging_fast); + statusString = getFastChargingStatusString(res); break; case BatteryStatus.CHARGING_SLOWLY: - statusString = - res.getString(R.string.battery_info_status_charging_slow); + statusString = getSlowChargingStatusString(res); break; default: - statusString = res.getString(R.string.battery_info_status_charging); + statusString = getRegularChargingStatusString(res); break; } } else if (batteryStatus.isPluggedInDock()) { - statusString = res.getString(R.string.battery_info_status_charging_dock); + statusString = getDockChargingStatusString(res); } else { - statusString = res.getString(R.string.battery_info_status_charging_wireless); + statusString = getWirelessChargingStatusString(res); } } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) { statusString = res.getString(R.string.battery_info_status_discharging); @@ -276,6 +275,41 @@ public class Utils { return statusString; } + private static String getFastChargingStatusString(Resources res) { + return res.getString( + BatteryUtils.isChargingStringV2Enabled() + ? R.string.battery_info_status_charging_fast_v2 + : R.string.battery_info_status_charging_fast); + } + + private static String getSlowChargingStatusString(Resources res) { + return res.getString( + BatteryUtils.isChargingStringV2Enabled() + ? R.string.battery_info_status_charging_v2 + : R.string.battery_info_status_charging_slow); + } + + private static String getRegularChargingStatusString(Resources res) { + return res.getString( + BatteryUtils.isChargingStringV2Enabled() + ? R.string.battery_info_status_charging_v2 + : R.string.battery_info_status_charging); + } + + private static String getWirelessChargingStatusString(Resources res) { + return res.getString( + BatteryUtils.isChargingStringV2Enabled() + ? R.string.battery_info_status_charging_v2 + : R.string.battery_info_status_charging_wireless); + } + + private static String getDockChargingStatusString(Resources res) { + return res.getString( + BatteryUtils.isChargingStringV2Enabled() + ? R.string.battery_info_status_charging_v2 + : R.string.battery_info_status_charging_dock); + } + public static ColorStateList getColorAccent(Context context) { return getColorAttr(context, android.R.attr.colorAccent); } diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 56118dae3f96..06c41cb7cbc7 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -1993,6 +1993,40 @@ public class ApplicationsState { }; /** + * Displays a combined list with "downloaded" and "visible in launcher" apps which belong to a + * user which is either not in quiet mode or allows showing apps even when in quiet mode. + */ + public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET = new AppFilter() { + @Override + public void init() { + } + + @Override + public boolean filterApp(@NonNull AppEntry entry) { + if (entry.hideInQuietMode) { + return false; + } + if (AppUtils.isInstant(entry.info)) { + return false; + } else if (hasFlag(entry.info.flags, ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) { + return true; + } else if (!hasFlag(entry.info.flags, ApplicationInfo.FLAG_SYSTEM)) { + return true; + } else if (entry.hasLauncherEntry) { + return true; + } else if (hasFlag(entry.info.flags, ApplicationInfo.FLAG_SYSTEM) && entry.isHomeApp) { + return true; + } + return false; + } + + @Override + public void refreshAppEntryOnRebuild(@NonNull AppEntry appEntry, boolean hideInQuietMode) { + appEntry.hideInQuietMode = hideInQuietMode; + } + }; + + /** * Displays a combined list with "downloaded" and "visible in launcher" apps only. */ public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT = new AppFilter() { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index 0996d52b0e30..e926b1684348 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -57,6 +57,7 @@ public class BluetoothEventManager { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final LocalBluetoothAdapter mLocalAdapter; + private final LocalBluetoothManager mBtManager; private final CachedBluetoothDeviceManager mDeviceManager; private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter; private final Map<String, Handler> mHandlerMap; @@ -80,10 +81,15 @@ public class BluetoothEventManager { * userHandle passed in is {@code null}, we register event receiver for the * {@code context.getUser()} handle. */ - BluetoothEventManager(LocalBluetoothAdapter adapter, - CachedBluetoothDeviceManager deviceManager, Context context, - android.os.Handler handler, @Nullable UserHandle userHandle) { + BluetoothEventManager( + LocalBluetoothAdapter adapter, + LocalBluetoothManager btManager, + CachedBluetoothDeviceManager deviceManager, + Context context, + android.os.Handler handler, + @Nullable UserHandle userHandle) { mLocalAdapter = adapter; + mBtManager = btManager; mDeviceManager = deviceManager; mAdapterIntentFilter = new IntentFilter(); mProfileIntentFilter = new IntentFilter(); @@ -210,11 +216,27 @@ public class BluetoothEventManager { } } - void dispatchProfileConnectionStateChanged(@NonNull CachedBluetoothDevice device, int state, - int bluetoothProfile) { + void dispatchProfileConnectionStateChanged( + @NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) { for (BluetoothCallback callback : mCallbacks) { callback.onProfileConnectionStateChanged(device, state, bluetoothProfile); } + + // Trigger updateFallbackActiveDeviceIfNeeded when ASSISTANT profile disconnected when + // audio sharing is enabled. + if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT + && state == BluetoothAdapter.STATE_DISCONNECTED + && BluetoothUtils.isAudioSharingEnabled()) { + LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); + if (profileManager != null + && profileManager.getLeAudioBroadcastProfile() != null + && profileManager.getLeAudioBroadcastProfile().isProfileReady() + && profileManager.getLeAudioBroadcastAssistantProfile() != null + && profileManager.getLeAudioBroadcastAssistantProfile().isProfileReady()) { + Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, ASSISTANT profile disconnected"); + profileManager.getLeAudioBroadcastProfile().updateFallbackActiveDeviceIfNeeded(); + } + } } private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { @@ -536,7 +558,6 @@ public class BluetoothEventManager { default: Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action); return; - } dispatchAclStateChanged(activeDevice, state); } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 4777b0de0732..04516eba250e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -16,6 +16,8 @@ package com.android.settingslib.bluetooth; +import static com.android.settingslib.flags.Flags.enableSetPreferredTransportForLeAudioDevice; + import android.annotation.CallbackExecutor; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; @@ -288,6 +290,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mLocalNapRoleConnected = true; } } + if (enableSetPreferredTransportForLeAudioDevice() + && profile instanceof HidProfile) { + updatePreferredTransport(); + } } else if (profile instanceof MapProfile && newProfileState == BluetoothProfile.STATE_DISCONNECTED) { profile.setEnabled(mDevice, false); @@ -300,12 +306,34 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mLocalNapRoleConnected = false; } + if (enableSetPreferredTransportForLeAudioDevice() + && profile instanceof LeAudioProfile) { + updatePreferredTransport(); + } + HearingAidStatsLogUtils.updateHistoryIfNeeded(mContext, this, profile, newProfileState); } fetchActiveDevices(); } + private void updatePreferredTransport() { + if (mProfiles.stream().noneMatch(p -> p instanceof LeAudioProfile) + || mProfiles.stream().noneMatch(p -> p instanceof HidProfile)) { + return; + } + // Both LeAudioProfile and HidProfile are connectable. + if (!mProfileManager + .getHidProfile() + .setPreferredTransport( + mDevice, + mProfileManager.getLeAudioProfile().isEnabled(mDevice) + ? BluetoothDevice.TRANSPORT_LE + : BluetoothDevice.TRANSPORT_BREDR)) { + Log.w(TAG, "Fail to set preferred transport"); + } + } + @VisibleForTesting void setProfileConnectedStatus(int profileId, boolean isFailed) { switch (profileId) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java index 5b91ac9d3dab..b849d44622b2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java @@ -27,6 +27,8 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.settingslib.R; import java.util.List; @@ -187,6 +189,14 @@ public class HidProfile implements LocalBluetoothProfile { } } + /** Set preferred transport for the device */ + public boolean setPreferredTransport(@NonNull BluetoothDevice device, int transport) { + if (mService != null) { + mService.setPreferredTransport(device, transport); + } + return false; + } + protected void finalize() { Log.d(TAG, "finalize()"); if (mService != null) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java index 64cf5c640143..9df23aa2fe29 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java @@ -42,6 +42,7 @@ import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; +import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -78,6 +79,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { public static final String ACTION_LE_AUDIO_SHARING_STATE_CHANGE = "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_STATE_CHANGE"; public static final String EXTRA_LE_AUDIO_SHARING_STATE = "BLUETOOTH_LE_AUDIO_SHARING_STATE"; + public static final String EXTRA_BLUETOOTH_DEVICE = "BLUETOOTH_DEVICE"; public static final int BROADCAST_STATE_UNKNOWN = 0; public static final int BROADCAST_STATE_ON = 1; public static final int BROADCAST_STATE_OFF = 2; @@ -335,7 +337,6 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { + ", sourceId = " + sourceId); } - updateFallbackActiveDeviceIfNeeded(); } @Override @@ -467,6 +468,15 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { mServiceBroadcast.startBroadcast(settings); } + /** Checks if the broadcast is playing. */ + public boolean isPlaying(int broadcastId) { + if (mServiceBroadcast == null) { + Log.d(TAG, "check isPlaying failed, the BluetoothLeBroadcast is null."); + return false; + } + return mServiceBroadcast.isPlaying(broadcastId); + } + private BluetoothLeBroadcastSettings buildBroadcastSettings( boolean isPublic, @Nullable String broadcastName, @@ -1024,6 +1034,16 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { /** Update fallback active device if needed. */ public void updateFallbackActiveDeviceIfNeeded() { + if (mServiceBroadcast == null) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to broadcast profile is null"); + return; + } + List<BluetoothLeBroadcastMetadata> sources = mServiceBroadcast.getAllBroadcastMetadata(); + if (sources.stream() + .noneMatch(source -> mServiceBroadcast.isPlaying(source.getBroadcastId()))) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to no broadcast ongoing"); + return; + } if (mServiceBroadcastAssistant == null) { Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to assistant profile is null"); return; @@ -1116,10 +1136,19 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { Log.d(TAG, "Skip notifyBroadcastStateChange, not triggered by Settings."); return; } + if (isWorkProfile(mContext)) { + Log.d(TAG, "Skip notifyBroadcastStateChange, not triggered for work profile."); + return; + } Intent intent = new Intent(ACTION_LE_AUDIO_SHARING_STATE_CHANGE); intent.putExtra(EXTRA_LE_AUDIO_SHARING_STATE, state); intent.setPackage(mContext.getPackageName()); Log.e(TAG, "notifyBroadcastStateChange for state = " + state); mContext.sendBroadcast(intent); } + + private boolean isWorkProfile(Context context) { + UserManager userManager = context.getSystemService(UserManager.class); + return userManager != null && userManager.isManagedProfile(); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java index 34c60a1b9f34..9faebe2036d6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java @@ -381,6 +381,14 @@ public class LocalBluetoothLeBroadcastAssistant implements LocalBluetoothProfile }); } + /** Gets devices with matched connection states. */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[] states) { + if (mService == null) { + return new ArrayList<BluetoothDevice>(0); + } + return mService.getDevicesMatchingConnectionStates(states); + } + public boolean isEnabled(BluetoothDevice device) { if (mService == null || device == null) { return false; diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java index 53c6075ccff4..c4300d214c0c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java @@ -21,11 +21,11 @@ import android.os.Handler; import android.os.UserHandle; import android.util.Log; -import java.lang.ref.WeakReference; - import androidx.annotation.Nullable; import androidx.annotation.RequiresPermission; +import java.lang.ref.WeakReference; + /** * LocalBluetoothManager provides a simplified interface on top of a subset of * the Bluetooth API. Note that {@link #getInstance} will return null @@ -111,10 +111,17 @@ public class LocalBluetoothManager { mContext = context.getApplicationContext(); mLocalAdapter = adapter; mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, this); - mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext, - handler, userHandle); - mProfileManager = new LocalBluetoothProfileManager(mContext, - mLocalAdapter, mCachedDeviceManager, mEventManager); + mEventManager = + new BluetoothEventManager( + mLocalAdapter, + this, + mCachedDeviceManager, + mContext, + handler, + userHandle); + mProfileManager = + new LocalBluetoothProfileManager( + mContext, mLocalAdapter, mCachedDeviceManager, mEventManager); mProfileManager.updateLocalProfiles(); mEventManager.readPairedDevices(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 79e4c374667e..4055986e8a57 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -572,8 +572,7 @@ public class LocalBluetoothProfileManager { return mSapProfile; } - @VisibleForTesting - HidProfile getHidProfile() { + public HidProfile getHidProfile() { return mHidProfile; } diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java index 92db50878a70..327e470e7d22 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java @@ -21,11 +21,14 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.provider.Settings; +import android.os.SystemProperties; import android.os.UserManager; +import android.provider.Settings; import android.util.ArraySet; import android.view.accessibility.AccessibilityManager; +import androidx.annotation.VisibleForTesting; + import java.util.List; public final class BatteryUtils { @@ -33,6 +36,9 @@ public final class BatteryUtils { /** The key to get the time to full from Settings.Global */ public static final String GLOBAL_TIME_TO_FULL_MILLIS = "time_to_full_millis"; + /** The system property key to check whether the charging string v2 is enabled or not. */ + public static final String PROPERTY_CHARGING_STRING_V2_KEY = "charging_string.apply_v2"; + /** Gets the latest sticky battery intent from the Android system. */ public static Intent getBatteryIntent(Context context) { return context.registerReceiver( @@ -75,4 +81,25 @@ public final class BatteryUtils { final UserManager userManager = context.getSystemService(UserManager.class); return userManager.isManagedProfile() && !userManager.isSystemUser(); } + + private static Boolean sChargingStringV2Enabled = null; + + /** Returns {@code true} if the charging string v2 is enabled. */ + public static boolean isChargingStringV2Enabled() { + if (sChargingStringV2Enabled == null) { + sChargingStringV2Enabled = + SystemProperties.getBoolean(PROPERTY_CHARGING_STRING_V2_KEY, false); + } + return sChargingStringV2Enabled; + } + + + /** Used to override the system property to enable or reset for charging string V2. */ + @VisibleForTesting + public static void setChargingStringV2Enabled(Boolean enabled) { + SystemProperties.set( + BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY, + enabled == null ? "" : String.valueOf(enabled)); + BatteryUtils.sChargingStringV2Enabled = enabled; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java index 6fb01797fbf4..e91c0bcab8f7 100644 --- a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java +++ b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java @@ -168,17 +168,16 @@ public class SettingsInjector { /** * Gets a list of preferences that other apps have injected. * - * @param profileId Identifier of the user/profile to obtain the injected settings for or - * UserHandle.USER_CURRENT for all profiles associated with current user. + * @param profiles UserHandles of the users/profiles for which to obtain the injected settings. */ public Map<Integer, List<Preference>> getInjectedSettings(Context prefContext, - final int profileId) { + final Set<UserHandle> profiles) { final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - final List<UserHandle> profiles = um.getUserProfiles(); + final List<UserHandle> allProfilesForUser = um.getUserProfiles(); final ArrayMap<Integer, List<Preference>> result = new ArrayMap<>(); mSettings.clear(); - for (UserHandle userHandle : profiles) { - if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) { + for (UserHandle userHandle : allProfilesForUser) { + if (profiles.contains(userHandle)) { final List<Preference> prefs = new ArrayList<>(); Iterable<InjectedSetting> settings = getSettings(userHandle); for (InjectedSetting setting : settings) { diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index 9b1e4b7a633b..3e2987208444 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -52,6 +52,7 @@ import android.media.MediaRoute2Info; import android.media.RouteListingPreference; import android.media.RoutingSessionInfo; import android.os.Build; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -131,6 +132,7 @@ public abstract class InfoMediaManager { protected final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); @NonNull protected final Context mContext; @NonNull protected final String mPackageName; + @NonNull protected final UserHandle mUserHandle; private final Collection<MediaDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>(); private MediaDevice mCurrentConnectedDevice; private final LocalBluetoothManager mBluetoothManager; @@ -140,16 +142,19 @@ public abstract class InfoMediaManager { /* package */ InfoMediaManager( @NonNull Context context, @NonNull String packageName, + @NonNull UserHandle userHandle, @NonNull LocalBluetoothManager localBluetoothManager) { mContext = context; mBluetoothManager = localBluetoothManager; mPackageName = packageName; + mUserHandle = userHandle; } /** Creates an instance of InfoMediaManager. */ public static InfoMediaManager createInstance( Context context, @Nullable String packageName, + @Nullable UserHandle userHandle, LocalBluetoothManager localBluetoothManager) { // The caller is only interested in system routes (headsets, built-in speakers, etc), and is @@ -159,16 +164,23 @@ public abstract class InfoMediaManager { packageName = context.getPackageName(); } + if (userHandle == null) { + userHandle = android.os.Process.myUserHandle(); + } + if (Flags.useMediaRouter2ForInfoMediaManager()) { try { - return new RouterInfoMediaManager(context, packageName, localBluetoothManager); + return new RouterInfoMediaManager( + context, packageName, userHandle, localBluetoothManager); } catch (PackageNotAvailableException ex) { // TODO: b/293578081 - Propagate this exception to callers for proper handling. Log.w(TAG, "Returning a no-op InfoMediaManager for package " + packageName); - return new NoOpInfoMediaManager(context, packageName, localBluetoothManager); + return new NoOpInfoMediaManager( + context, packageName, userHandle, localBluetoothManager); } } else { - return new ManagerInfoMediaManager(context, packageName, localBluetoothManager); + return new ManagerInfoMediaManager( + context, packageName, userHandle, localBluetoothManager); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index 63056b6dc8c3..0c2414c6a7a8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -138,7 +138,10 @@ public class LocalMediaManager implements BluetoothCallback { } mInfoMediaManager = - InfoMediaManager.createInstance(context, packageName, mLocalBluetoothManager); + // TODO: b/321969740 - Take the userHandle as a parameter and pass it through. The + // package name is not sufficient to unambiguously identify an app. + InfoMediaManager.createInstance( + context, packageName, /* userHandle */ null, mLocalBluetoothManager); } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java index 23063da747af..d621751a2c29 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java @@ -21,6 +21,7 @@ import android.media.MediaRoute2Info; import android.media.MediaRouter2Manager; import android.media.RouteListingPreference; import android.media.RoutingSessionInfo; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -53,8 +54,9 @@ public class ManagerInfoMediaManager extends InfoMediaManager { /* package */ ManagerInfoMediaManager( Context context, @NonNull String packageName, + @NonNull UserHandle userHandle, LocalBluetoothManager localBluetoothManager) { - super(context, packageName, localBluetoothManager); + super(context, packageName, userHandle, localBluetoothManager); mRouterManager = MediaRouter2Manager.getInstance(context); } @@ -87,8 +89,7 @@ public class ManagerInfoMediaManager extends InfoMediaManager { @Override protected void transferToRoute(@NonNull MediaRoute2Info route) { - // TODO: b/279555229 - provide real user handle of a caller. - mRouterManager.transfer(mPackageName, route, android.os.Process.myUserHandle()); + mRouterManager.transfer(mPackageName, route, mUserHandle); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java index cf11c6da737f..d2b018cd2299 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java @@ -20,6 +20,7 @@ import android.content.Context; import android.media.MediaRoute2Info; import android.media.RouteListingPreference; import android.media.RoutingSessionInfo; +import android.os.UserHandle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -58,8 +59,9 @@ import java.util.List; NoOpInfoMediaManager( Context context, @NonNull String packageName, + @NonNull UserHandle userHandle, LocalBluetoothManager localBluetoothManager) { - super(context, packageName, localBluetoothManager); + super(context, packageName, userHandle, localBluetoothManager); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java index 0dceebab13f8..045c60dd1514 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java @@ -25,7 +25,7 @@ import android.media.MediaRouter2Manager; import android.media.RouteDiscoveryPreference; import android.media.RouteListingPreference; import android.media.RoutingSessionInfo; -import android.os.Process; +import android.os.UserHandle; import android.text.TextUtils; import androidx.annotation.NonNull; @@ -70,15 +70,16 @@ public final class RouterInfoMediaManager extends InfoMediaManager { /* package */ RouterInfoMediaManager( Context context, @NonNull String packageName, + @NonNull UserHandle userHandle, LocalBluetoothManager localBluetoothManager) throws PackageNotAvailableException { - super(context, packageName, localBluetoothManager); + super(context, packageName, userHandle, localBluetoothManager); MediaRouter2 router = null; if (Flags.enableCrossUserRoutingInMediaRouter2()) { try { - router = MediaRouter2.getInstance(context, packageName, Process.myUserHandle()); + router = MediaRouter2.getInstance(context, packageName, userHandle); } catch (IllegalArgumentException ex) { // Do nothing } diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java index b015b2bce60a..46f229035839 100644 --- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java +++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java @@ -184,7 +184,7 @@ public class EditUserInfoController { dialogHelper .setTitle(R.string.user_info_settings_title) .addCustomView(content) - .setPositiveButton(android.R.string.ok, view -> { + .setPositiveButton(R.string.okay, view -> { Drawable newUserIcon = mEditUserPhotoController != null ? mEditUserPhotoController.getNewUserPhotoDrawable() : null; @@ -201,7 +201,7 @@ public class EditUserInfoController { } dialogHelper.getDialog().dismiss(); }) - .setBackButton(android.R.string.cancel, view -> { + .setBackButton(R.string.cancel, view -> { clear(); if (cancelCallback != null) { cancelCallback.run(); diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java index 22726549ce05..5ed59996bee3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java +++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java @@ -33,7 +33,7 @@ import java.util.Date; import java.util.Locale; import java.util.concurrent.TimeUnit; -/** Utility class for keeping power related strings consistent**/ +/** Utility class for keeping power related strings consistent. **/ public class PowerUtil { private static final long SEVEN_MINUTES_MILLIS = TimeUnit.MINUTES.toMillis(7); @@ -221,4 +221,19 @@ public class PowerUtil { return time - remainder + multiple; } } + + /** Gets the rounded target time string in a short format. */ + public static String getTargetTimeShortString( + Context context, long targetTimeOffsetMs, long currentTimeMs) { + final long roundedTimeOfDayMs = + roundTimeToNearestThreshold( + currentTimeMs + targetTimeOffsetMs, FIFTEEN_MINUTES_MILLIS); + + // convert the time to a properly formatted string. + String skeleton = android.text.format.DateFormat.getTimeFormatString(context); + DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton); + Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs)); + return fmt.format(date); + } } + diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java index b9748883b25d..fef05612a8cb 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java @@ -240,6 +240,56 @@ public class ApplicationsStateTest { } @Test + public void testDownloadAndLauncherNotInQuietAcceptsCorrectApps() { + mEntry.isHomeApp = false; + mEntry.hasLauncherEntry = false; + + // should include updated system apps + when(mEntry.info.isInstantApp()).thenReturn(false); + mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isTrue(); + + // should not include system apps other than the home app + mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM; + mEntry.isHomeApp = false; + mEntry.hasLauncherEntry = false; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isFalse(); + + // should include the home app + mEntry.isHomeApp = true; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isTrue(); + + // should include any System app with a launcher entry + mEntry.isHomeApp = false; + mEntry.hasLauncherEntry = true; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isTrue(); + + // should not include updated system apps when in quiet mode + when(mEntry.info.isInstantApp()).thenReturn(false); + mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + mEntry.hideInQuietMode = true; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isFalse(); + + // should not include the home app when in quiet mode + mEntry.isHomeApp = true; + mEntry.hideInQuietMode = true; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isFalse(); + + // should not include any System app with a launcher entry when in quiet mode + mEntry.isHomeApp = false; + mEntry.hasLauncherEntry = true; + mEntry.hideInQuietMode = true; + assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry)) + .isFalse(); + } + + @Test public void testOtherAppsRejectsLegacyGame() { mEntry.info.flags = ApplicationInfo.FLAG_IS_GAME; diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java index 50f5b9d81000..69f6305fa1b2 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; +import static java.util.concurrent.TimeUnit.SECONDS; + import android.app.ActivityManager; import android.content.Context; import android.content.Intent; @@ -37,13 +39,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import static java.util.concurrent.TimeUnit.SECONDS; - import java.util.concurrent.CountDownLatch; /** - * Test that verifies that BluetoothEventManager can receive broadcasts for non-current - * users for all bluetooth events. + * Test that verifies that BluetoothEventManager can receive broadcasts for non-current users for + * all bluetooth events. * * <p>Creation and deletion of users takes a long time, so marking this as a LargeTest. */ @@ -64,9 +64,14 @@ public class BluetoothEventManagerIntegTest { mContext = InstrumentationRegistry.getTargetContext(); mUserManager = UserManager.get(mContext); - mBluetoothEventManager = new BluetoothEventManager( - mock(LocalBluetoothAdapter.class), mock(CachedBluetoothDeviceManager.class), - mContext, /* handler= */ null, UserHandle.ALL); + mBluetoothEventManager = + new BluetoothEventManager( + mock(LocalBluetoothAdapter.class), + mock(LocalBluetoothManager.class), + mock(CachedBluetoothDeviceManager.class), + mContext, + /* handler= */ null, + UserHandle.ALL); // Create and start another user in the background. mOtherUser = mUserManager.createUser("TestUser", /* flags= */ 0); diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java index f0185b95e8f4..3bd37a2c59bf 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java @@ -64,21 +64,23 @@ public class InfoMediaManagerIntegTest { @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) public void createInstance_withMR2FlagOn_returnsRouterInfoMediaManager() { InfoMediaManager manager = - InfoMediaManager.createInstance(mContext, mContext.getPackageName(), null); + InfoMediaManager.createInstance( + mContext, mContext.getPackageName(), mContext.getUser(), null); assertThat(manager).isInstanceOf(RouterInfoMediaManager.class); } @Test @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) public void createInstance_withMR2FlagOn_withFakePackage_returnsNoOpInfoMediaManager() { - InfoMediaManager manager = InfoMediaManager.createInstance(mContext, FAKE_PACKAGE, null); + InfoMediaManager manager = + InfoMediaManager.createInstance(mContext, FAKE_PACKAGE, null, null); assertThat(manager).isInstanceOf(NoOpInfoMediaManager.class); } @Test @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) public void createInstance_withMR2FlagOn_withNullPackage_returnsRouterInfoMediaManager() { - InfoMediaManager manager = InfoMediaManager.createInstance(mContext, null, null); + InfoMediaManager manager = InfoMediaManager.createInstance(mContext, null, null, null); assertThat(manager).isInstanceOf(RouterInfoMediaManager.class); } @@ -86,7 +88,8 @@ public class InfoMediaManagerIntegTest { @RequiresFlagsDisabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) public void createInstance_withMR2FlagOff_returnsManagerInfoMediaManager() { InfoMediaManager manager = - InfoMediaManager.createInstance(mContext, mContext.getPackageName(), null); + InfoMediaManager.createInstance( + mContext, mContext.getPackageName(), mContext.getUser(), null); assertThat(manager).isInstanceOf(ManagerInfoMediaManager.class); } } diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/OWNERS b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/OWNERS new file mode 100644 index 000000000000..384fd9beaa9d --- /dev/null +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/OWNERS @@ -0,0 +1,3 @@ +#Android Media Better Together +ivanbuper@google.com +aquilescanta@google.com diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java index 48bbf4ea6a65..b1489be943e6 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,35 +30,47 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothStatusCodes; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.UserHandle; +import android.platform.test.flag.junit.SetFlagsRule; import android.telephony.TelephonyManager; import com.android.settingslib.R; +import com.android.settingslib.flags.Flags; +import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import java.util.ArrayList; import java.util.Collections; import java.util.List; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowBluetoothAdapter.class}) public class BluetoothEventManagerTest { + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final String DEVICE_NAME = "test_device_name"; @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock + private LocalBluetoothManager mBtManager; + @Mock private CachedBluetoothDeviceManager mCachedDeviceManager; @Mock private BluetoothCallback mBluetoothCallback; @@ -96,8 +109,15 @@ public class BluetoothEventManagerTest { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - mBluetoothEventManager = new BluetoothEventManager(mLocalAdapter, - mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null); + mBluetoothEventManager = + new BluetoothEventManager( + mLocalAdapter, + mBtManager, + mCachedDeviceManager, + mContext, + /* handler= */ null, + /* userHandle= */ null); + when(mBtManager.getProfileManager()).thenReturn(mLocalProfileManager); when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); when(mHfpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true); @@ -113,8 +133,13 @@ public class BluetoothEventManagerTest { public void ifUserHandleIsNull_registerReceiverIsCalled() { Context mockContext = mock(Context.class); BluetoothEventManager eventManager = - new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext, - /* handler= */ null, /* userHandle= */ null); + new BluetoothEventManager( + mLocalAdapter, + mBtManager, + mCachedDeviceManager, + mockContext, + /* handler= */ null, + /* userHandle= */ null); verify(mockContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED)); @@ -124,8 +149,13 @@ public class BluetoothEventManagerTest { public void ifUserHandleSpecified_registerReceiverAsUserIsCalled() { Context mockContext = mock(Context.class); BluetoothEventManager eventManager = - new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext, - /* handler= */ null, UserHandle.ALL); + new BluetoothEventManager( + mLocalAdapter, + mBtManager, + mCachedDeviceManager, + mockContext, + /* handler= */ null, + UserHandle.ALL); verify(mockContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq(UserHandle.ALL), any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED)); @@ -172,6 +202,160 @@ public class BluetoothEventManagerTest { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); } + /** + * dispatchProfileConnectionStateChanged should not call {@link + * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing flag is off. + */ + @Test + public void dispatchProfileConnectionStateChanged_flagOff_noUpdateFallbackDevice() { + ShadowBluetoothAdapter shadowBluetoothAdapter = + Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); + when(broadcast.isProfileReady()).thenReturn(true); + LocalBluetoothLeBroadcastAssistant assistant = + mock(LocalBluetoothLeBroadcastAssistant.class); + when(assistant.isProfileReady()).thenReturn(true); + LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); + when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); + when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); + when(mBtManager.getProfileManager()).thenReturn(profileManager); + mBluetoothEventManager.dispatchProfileConnectionStateChanged( + mCachedBluetoothDevice, + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); + + verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); + } + + /** + * dispatchProfileConnectionStateChanged should not call {@link + * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when the device does not + * support audio sharing. + */ + @Test + public void dispatchProfileConnectionStateChanged_notSupport_noUpdateFallbackDevice() { + ShadowBluetoothAdapter shadowBluetoothAdapter = + Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); + when(broadcast.isProfileReady()).thenReturn(true); + LocalBluetoothLeBroadcastAssistant assistant = + mock(LocalBluetoothLeBroadcastAssistant.class); + when(assistant.isProfileReady()).thenReturn(true); + LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); + when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); + when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); + when(mBtManager.getProfileManager()).thenReturn(profileManager); + mBluetoothEventManager.dispatchProfileConnectionStateChanged( + mCachedBluetoothDevice, + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); + + verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); + } + + /** + * dispatchProfileConnectionStateChanged should not call {@link + * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing profile is + * not ready. + */ + @Test + public void dispatchProfileConnectionStateChanged_profileNotReady_noUpdateFallbackDevice() { + ShadowBluetoothAdapter shadowBluetoothAdapter = + Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); + when(broadcast.isProfileReady()).thenReturn(false); + LocalBluetoothLeBroadcastAssistant assistant = + mock(LocalBluetoothLeBroadcastAssistant.class); + when(assistant.isProfileReady()).thenReturn(true); + LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); + when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); + when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); + when(mBtManager.getProfileManager()).thenReturn(profileManager); + mBluetoothEventManager.dispatchProfileConnectionStateChanged( + mCachedBluetoothDevice, + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); + + verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); + } + + /** + * dispatchProfileConnectionStateChanged should not call {@link + * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when triggered for profile + * other than LE_AUDIO_BROADCAST_ASSISTANT or state other than STATE_DISCONNECTED. + */ + @Test + public void dispatchProfileConnectionStateChanged_notAssistantProfile_noUpdateFallbackDevice() { + ShadowBluetoothAdapter shadowBluetoothAdapter = + Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); + when(broadcast.isProfileReady()).thenReturn(true); + LocalBluetoothLeBroadcastAssistant assistant = + mock(LocalBluetoothLeBroadcastAssistant.class); + when(assistant.isProfileReady()).thenReturn(true); + LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); + when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); + when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); + when(mBtManager.getProfileManager()).thenReturn(profileManager); + mBluetoothEventManager.dispatchProfileConnectionStateChanged( + mCachedBluetoothDevice, + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.LE_AUDIO); + + verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); + } + + /** + * dispatchProfileConnectionStateChanged should call {@link + * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when assistant profile is + * disconnected and audio sharing is enabled. + */ + @Test + public void dispatchProfileConnectionStateChanged_audioSharing_updateFallbackDevice() { + ShadowBluetoothAdapter shadowBluetoothAdapter = + Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); + when(broadcast.isProfileReady()).thenReturn(true); + LocalBluetoothLeBroadcastAssistant assistant = + mock(LocalBluetoothLeBroadcastAssistant.class); + when(assistant.isProfileReady()).thenReturn(true); + LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); + when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); + when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); + when(mBtManager.getProfileManager()).thenReturn(profileManager); + mBluetoothEventManager.dispatchProfileConnectionStateChanged( + mCachedBluetoothDevice, + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); + + verify(broadcast).updateFallbackActiveDeviceIfNeeded(); + } + @Test public void dispatchAclConnectionStateChanged_aclDisconnected_shouldDispatchCallback() { mBluetoothEventManager.registerCallback(mBluetoothCallback); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 5996dbb322fc..646e9ebd4f09 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -15,6 +15,8 @@ */ package com.android.settingslib.bluetooth; +import static com.android.settingslib.flags.Flags.FLAG_ENABLE_SET_PREFERRED_TRANSPORT_FOR_LE_AUDIO_DEVICE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -86,6 +88,9 @@ public class CachedBluetoothDeviceTest { private HapClientProfile mHapClientProfile; @Mock private LeAudioProfile mLeAudioProfile; + + @Mock + private HidProfile mHidProfile; @Mock private BluetoothDevice mDevice; @Mock @@ -104,6 +109,7 @@ public class CachedBluetoothDeviceTest { public void setUp() { MockitoAnnotations.initMocks(this); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TV_MEDIA_OUTPUT_DIALOG); + mSetFlagsRule.enableFlags(FLAG_ENABLE_SET_PREFERRED_TRANSPORT_FOR_LE_AUDIO_DEVICE); mContext = RuntimeEnvironment.application; mAudioManager = mContext.getSystemService(AudioManager.class); mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); @@ -118,6 +124,8 @@ public class CachedBluetoothDeviceTest { when(mHearingAidProfile.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID); when(mLeAudioProfile.isProfileReady()).thenReturn(true); when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO); + when(mHidProfile.isProfileReady()).thenReturn(true); + when(mHidProfile.getProfileId()).thenReturn(BluetoothProfile.HID_HOST); mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice)); mSubCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mSubDevice)); doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel(); @@ -1819,6 +1827,32 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse(); } + @Test + public void leAudioHidDevice_leAudioEnabled_setPreferredTransportToLE() { + + when(mProfileManager.getHidProfile()).thenReturn(mHidProfile); + when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); + when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(true); + + updateProfileStatus(mHidProfile, BluetoothProfile.STATE_CONNECTED); + updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED); + + verify(mHidProfile).setPreferredTransport(mDevice, BluetoothDevice.TRANSPORT_LE); + } + + @Test + public void leAudioHidDevice_leAudioDisabled_setPreferredTransportToBredr() { + when(mProfileManager.getHidProfile()).thenReturn(mHidProfile); + when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); + when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(false); + + updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED); + updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_DISCONNECTED); + updateProfileStatus(mHidProfile, BluetoothProfile.STATE_CONNECTED); + + verify(mHidProfile).setPreferredTransport(mDevice, BluetoothDevice.TRANSPORT_BREDR); + } + private HearingAidInfo getLeftAshaHearingAidInfo() { return new HearingAidInfo.Builder() .setAshaDeviceSide(HearingAidProfile.DeviceSide.SIDE_LEFT) diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java index 4f8fa2fdb96e..cef083584744 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java @@ -56,7 +56,8 @@ import java.util.List; @Config(shadows = {ShadowBluetoothAdapter.class}) public class LocalBluetoothProfileManagerTest { private final static long HISYNCID = 10; - + @Mock + private LocalBluetoothManager mBtManager; @Mock private CachedBluetoothDeviceManager mDeviceManager; @Mock @@ -77,13 +78,21 @@ public class LocalBluetoothProfileManagerTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); mLocalBluetoothAdapter = LocalBluetoothAdapter.getInstance(); - mEventManager = spy(new BluetoothEventManager(mLocalBluetoothAdapter, mDeviceManager, - mContext, /* handler= */ null, /* userHandle= */ null)); + mEventManager = + spy( + new BluetoothEventManager( + mLocalBluetoothAdapter, + mBtManager, + mDeviceManager, + mContext, + /* handler= */ null, + /* userHandle= */ null)); mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice); when(mCachedBluetoothDevice.getDevice()).thenReturn(mDevice); - mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter, - mDeviceManager, mEventManager); + mProfileManager = + new LocalBluetoothProfileManager( + mContext, mLocalBluetoothAdapter, mDeviceManager, mEventManager); } /** diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java index d7938670c598..a4b87da9f7f6 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java @@ -144,7 +144,8 @@ public class InfoMediaManagerTest { doReturn(mMediaSessionManager).when(mContext).getSystemService( Context.MEDIA_SESSION_SERVICE); mInfoMediaManager = - new ManagerInfoMediaManager(mContext, TEST_PACKAGE_NAME, mLocalBluetoothManager); + new ManagerInfoMediaManager( + mContext, TEST_PACKAGE_NAME, mContext.getUser(), mLocalBluetoothManager); mShadowRouter2Manager = ShadowRouter2Manager.getShadow(); mInfoMediaManager.mRouterManager = MediaRouter2Manager.getInstance(mContext); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java index d630301a083b..908f50deea78 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java @@ -46,6 +46,7 @@ public class NoOpInfoMediaManagerTest { new NoOpInfoMediaManager( mContext, /* packageName */ "FAKE_PACKAGE_NAME", + mContext.getUser(), /* localBluetoothManager */ null); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java index 2e7905f2e1e4..cbc382b6b920 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java @@ -20,30 +20,24 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; +import android.app.AlarmManager; import android.content.Context; +import androidx.test.core.app.ApplicationProvider; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; import java.time.Duration; +import java.time.Instant; +import java.util.Locale; import java.util.regex.Pattern; @RunWith(RobolectricTestRunner.class) public class PowerUtilTest { - private static final String TEST_BATTERY_LEVEL_10 = "10%"; - private static final long TEN_SEC_MILLIS = Duration.ofSeconds(10).toMillis(); - private static final long SEVENTEEN_MIN_MILLIS = Duration.ofMinutes(17).toMillis(); - private static final long FIVE_MINUTES_MILLIS = Duration.ofMinutes(5).toMillis(); - private static final long TEN_MINUTES_MILLIS = Duration.ofMinutes(10).toMillis(); - private static final long THREE_DAYS_MILLIS = Duration.ofDays(3).toMillis(); - private static final long TEN_HOURS_MILLIS = Duration.ofHours(10).toMillis(); - private static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis(); - private static final String NORMAL_CASE_EXPECTED_PREFIX = "Should last until about"; - private static final String ENHANCED_SUFFIX = " based on your usage"; private static final String BATTERY_RUN_OUT_PREFIX = "Battery may run out by"; // matches a time (ex: '1:15 PM', '2 AM', '23:00') private static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* ((AM)*)|((PM)*)"; @@ -55,29 +49,31 @@ public class PowerUtilTest { @Before public void setup() { MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); + mContext = spy(ApplicationProvider.getApplicationContext()); } @Test public void getBatteryTipStringFormatted_moreThanOneDay_usesCorrectString() { - String info = PowerUtil.getBatteryTipStringFormatted(mContext, - THREE_DAYS_MILLIS); + var threeDayMillis = Duration.ofDays(3).toMillis(); + + String batteryTipString = PowerUtil.getBatteryTipStringFormatted(mContext, threeDayMillis); - assertThat(info).isEqualTo("More than 3 days left"); + assertThat(batteryTipString).isEqualTo("More than 3 days left"); } @Test public void getBatteryTipStringFormatted_lessThanOneDay_usesCorrectString() { - String info = PowerUtil.getBatteryTipStringFormatted(mContext, - SEVENTEEN_MIN_MILLIS); + var drainTimeMs = Duration.ofMinutes(17).toMillis(); + + String batteryTipString = PowerUtil.getBatteryTipStringFormatted(mContext, drainTimeMs); // ex: Battery may run out by 1:15 PM - assertThat(info).containsMatch(Pattern.compile( - BATTERY_RUN_OUT_PREFIX + TIME_OF_DAY_REGEX)); + assertThat(batteryTipString) + .containsMatch(Pattern.compile(BATTERY_RUN_OUT_PREFIX + TIME_OF_DAY_REGEX)); } @Test - public void testRoundToNearestThreshold_roundsCorrectly() { + public void roundTimeToNearestThreshold_roundsCorrectly() { // test some pretty normal values assertThat(PowerUtil.roundTimeToNearestThreshold(1200, 1000)).isEqualTo(1000); assertThat(PowerUtil.roundTimeToNearestThreshold(800, 1000)).isEqualTo(1000); @@ -89,4 +85,17 @@ public class PowerUtilTest { assertThat(PowerUtil.roundTimeToNearestThreshold(-120, 100)).isEqualTo(100); assertThat(PowerUtil.roundTimeToNearestThreshold(-200, -75)).isEqualTo(225); } + + @Test + public void getTargetTimeShortString_returnsTimeShortString() { + mContext.getSystemService(AlarmManager.class).setTimeZone("UTC"); + mContext.getResources().getConfiguration().setLocale(Locale.US); + var currentTimeMs = Instant.parse("2024-06-06T15:00:00Z").toEpochMilli(); + var remainingTimeMs = Duration.ofMinutes(30).toMillis(); + + var actualTimeString = + PowerUtil.getTargetTimeShortString(mContext, remainingTimeMs, currentTimeMs); + + assertThat(actualTimeString).isEqualTo("3:30 PM"); + } } diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java index c7e96bcdb856..00e47729a796 100644 --- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java +++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java @@ -38,6 +38,8 @@ public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBlueto private List<BluetoothDevice> mMostRecentlyConnectedDevices; private BluetoothProfile.ServiceListener mServiceListener; private ParcelUuid[] mParcelUuids; + private int mIsLeAudioBroadcastSourceSupported; + private int mIsLeAudioBroadcastAssistantSupported; @Implementation protected boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, @@ -97,4 +99,22 @@ public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBlueto public void setUuids(ParcelUuid[] uuids) { mParcelUuids = uuids; } + + @Implementation + protected int isLeAudioBroadcastSourceSupported() { + return mIsLeAudioBroadcastSourceSupported; + } + + public void setIsLeAudioBroadcastSourceSupported(int isSupported) { + mIsLeAudioBroadcastSourceSupported = isSupported; + } + + @Implementation + protected int isLeAudioBroadcastAssistantSupported() { + return mIsLeAudioBroadcastAssistantSupported; + } + + public void setIsLeAudioBroadcastAssistantSupported(int isSupported) { + mIsLeAudioBroadcastAssistantSupported = isSupported; + } } diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 17d9f1b87fac..097840ead0d3 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -338,4 +338,7 @@ <!-- Value to use as default scale for fonts --> <item name="def_device_font_scale" format="float" type="dimen">1.0</item> + + <!-- The default ringer mode. See `AudioManager` for list of valid values. --> + <integer name="def_ringer_mode">2</integer> </resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java index ad3eb92b0519..e77cf2fa6543 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java @@ -531,13 +531,22 @@ public final class DeviceConfigService extends Binder { pw.println(" put NAMESPACE KEY VALUE [default]"); pw.println(" Change the contents of KEY to VALUE for the given NAMESPACE."); pw.println(" {default} to set as the default value."); + pw.println(" override NAMESPACE KEY VALUE"); + pw.println(" Set flag NAMESPACE/KEY to the given VALUE, and ignores " + + "server-updates for"); + pw.println(" this flag. This can still be called even if there is no underlying " + + "value set."); pw.println(" delete NAMESPACE KEY"); pw.println(" Delete the entry for KEY for the given NAMESPACE."); + pw.println(" clear_override NAMESPACE KEY"); + pw.println(" Clear local sticky flag override for KEY in the given NAMESPACE."); pw.println(" list_namespaces [--public]"); pw.println(" Prints the name of all (or just the public) namespaces."); pw.println(" list [NAMESPACE]"); pw.println(" Print all keys and values defined, optionally for the given " + "NAMESPACE."); + pw.println(" list_local_overrides"); + pw.println(" Print all flags that have been overridden."); pw.println(" reset RESET_MODE [NAMESPACE]"); pw.println(" Reset all flag values, optionally for a NAMESPACE, according to " + "RESET_MODE."); @@ -547,8 +556,9 @@ public final class DeviceConfigService extends Binder { + "flags are reset"); pw.println(" set_sync_disabled_for_tests SYNC_DISABLED_MODE"); pw.println(" Modifies bulk property setting behavior for tests. When in one of the" - + " disabled modes this ensures that config isn't overwritten."); - pw.println(" SYNC_DISABLED_MODE is one of:"); + + " disabled modes"); + pw.println(" this ensures that config isn't overwritten. SYNC_DISABLED_MODE is " + + "one of:"); pw.println(" none: Sync is not disabled. A reboot may be required to restart" + " syncing."); pw.println(" persistent: Sync is disabled, this state will survive a reboot."); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 1ead14ab6f4c..096cccc1f94a 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -3943,8 +3943,10 @@ public class SettingsProvider extends ContentProvider { globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE, Integer.toString(Settings.Global.ZEN_MODE_OFF), null, true, SettingsState.SYSTEM_PACKAGE_NAME); + final int defaultRingerMode = + getContext().getResources().getInteger(R.integer.def_ringer_mode); globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER, - Integer.toString(AudioManager.RINGER_MODE_NORMAL), null, + Integer.toString(defaultRingerMode), null, true, SettingsState.SYSTEM_PACKAGE_NAME); } currentVersion = 119; diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml index b52a83c2fd54..90f0962867f7 100644 --- a/packages/Shell/res/values-af/strings.xml +++ b/packages/Shell/res/values-af/strings.xml @@ -35,7 +35,7 @@ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Kon nie foutverslagbesonderhede by ZIP-lêer voeg nie"</string> <string name="bugreport_unnamed" msgid="2800582406842092709">"naamloos"</string> <string name="bugreport_info_action" msgid="2158204228510576227">"Besonderhede"</string> - <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skermkiekie"</string> + <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skermskoot"</string> <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Skermkiekie is suksesvol geneem."</string> <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kon nie skermkiekie neem nie."</string> <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Foutverslag <xliff:g id="ID">#%d</xliff:g> se besonderhede"</string> diff --git a/packages/SimAppDialog/res/values-pt-rBR/strings.xml b/packages/SimAppDialog/res/values-pt-rBR/strings.xml index abf8dbd27ecc..fe31aa0d8b37 100644 --- a/packages/SimAppDialog/res/values-pt-rBR/strings.xml +++ b/packages/SimAppDialog/res/values-pt-rBR/strings.xml @@ -22,5 +22,5 @@ <string name="install_carrier_app_description" msgid="4014303558674923797">"Para que o novo chip funcione corretamente, instale o app <xliff:g id="ID_1">%1$s</xliff:g>"</string> <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Para que o novo chip funcione corretamente, instale o app da operadora"</string> <string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Agora não"</string> - <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Fazer o download do app"</string> + <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Baixar o app"</string> </resources> diff --git a/packages/SimAppDialog/res/values-pt/strings.xml b/packages/SimAppDialog/res/values-pt/strings.xml index abf8dbd27ecc..fe31aa0d8b37 100644 --- a/packages/SimAppDialog/res/values-pt/strings.xml +++ b/packages/SimAppDialog/res/values-pt/strings.xml @@ -22,5 +22,5 @@ <string name="install_carrier_app_description" msgid="4014303558674923797">"Para que o novo chip funcione corretamente, instale o app <xliff:g id="ID_1">%1$s</xliff:g>"</string> <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Para que o novo chip funcione corretamente, instale o app da operadora"</string> <string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Agora não"</string> - <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Fazer o download do app"</string> + <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Baixar o app"</string> </resources> diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 40db52eec81b..c88c3731aa10 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -117,6 +117,7 @@ android_library { "SystemUILogLib", "SystemUIPluginLib", "SystemUISharedLib", + "SystemUI-shared-utils", "SystemUI-statsd", "SettingsLib", "com_android_systemui_flags_lib", @@ -263,6 +264,7 @@ android_library { "SystemUISharedLib", "SystemUICustomizationLib", "SystemUICustomizationTestUtils", + "SystemUI-shared-utils", "SystemUI-statsd", "SettingsLib", "com_android_systemui_flags_lib", diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml index cbb5ad732b2b..56fd06c71366 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml @@ -12,7 +12,7 @@ <string name="lockscreen_label" msgid="648347953557887087">"Sluitskerm"</string> <string name="quick_settings_label" msgid="2999117381487601865">"Kitsinstellings"</string> <string name="notifications_label" msgid="6829741046963013567">"Kennisgewings"</string> - <string name="screenshot_label" msgid="863978141223970162">"Skermkiekie"</string> + <string name="screenshot_label" msgid="863978141223970162">"Skermskoot"</string> <string name="screenshot_utterance" msgid="1430760563401895074">"Neem skermkiekie"</string> <string name="volume_up_label" msgid="8592766918780362870">"Volume harder"</string> <string name="volume_down_label" msgid="8574981863656447346">"Volume sagter"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml index 5e317394cb31..8f2abaccbdd7 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml @@ -21,7 +21,7 @@ <string name="previous_button_content_description" msgid="840869171117765966">"Siirry edelliselle näytöllä"</string> <string name="next_button_content_description" msgid="6810058269847364406">"Siirry seuraavalle näytölle"</string> <string name="accessibility_menu_description" msgid="4458354794093858297">"Saavutettavuusvalikko on suuri näyttövalikko, josta voit ohjata laitettasi. Voit esimerkiksi lukita laitteen, säätää äänenvoimakkuutta ja kirkkautta sekä ottaa kuvakaappauksia."</string> - <string name="accessibility_menu_summary" msgid="340071398148208130">"Ohjaa laitetta suurella valikolla"</string> + <string name="accessibility_menu_summary" msgid="340071398148208130">"Ohjaa laitetta suuren valikon avulla"</string> <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Saavutettavuusvalikon asetukset"</string> <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Suuret painikkeet"</string> <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Suurenna saavutettavuusvalikon painikkeita"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml index 1cb9b5e3a73d..3d59c0b62ac4 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml @@ -2,7 +2,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="accessibility_menu_service_name" msgid="730136711554740131">"सुलभता मेन्यू"</string> - <string name="accessibility_menu_intro" msgid="3164193281544042394">"सुलभता मेन्यू, स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इसकी मदद से, अपने डिवाइस को कंट्रोल किया जा सकता है. इस मेन्यू में जाकर, अपना डिवाइस लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ कंट्रोल करने जैसे कई दूसरे काम किए जा सकते हैं."</string> + <string name="accessibility_menu_intro" msgid="3164193281544042394">"सुलभता मेन्यू, डिवाइस की स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इस मेन्यू में जाकर, डिवाइस को लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ को कंट्रोल करने जैसे कई काम किए जा सकते हैं."</string> <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string> <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string> <string name="a11y_settings_label" msgid="3977714687248445050">"सुलभता सेटिंग"</string> @@ -20,7 +20,7 @@ <string name="brightness_down_label" msgid="7115662941913272072">"स्क्रीन की रोशनी कम करें"</string> <string name="previous_button_content_description" msgid="840869171117765966">"पिछली स्क्रीन पर जाएं"</string> <string name="next_button_content_description" msgid="6810058269847364406">"अगली स्क्रीन पर जाएं"</string> - <string name="accessibility_menu_description" msgid="4458354794093858297">"सुलभता मेन्यू, स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इसकी मदद से, अपने डिवाइस को कंट्रोल किया जा सकता है. इस मेन्यू में जाकर, अपना डिवाइस लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ कंट्रोल करने जैसे कई दूसरे काम किए जा सकते हैं."</string> + <string name="accessibility_menu_description" msgid="4458354794093858297">"सुलभता मेन्यू, डिवाइस की स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इस मेन्यू में जाकर, डिवाइस को लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ को कंट्रोल करने जैसे कई काम किए जा सकते हैं."</string> <string name="accessibility_menu_summary" msgid="340071398148208130">"बड़े मेन्यू की मदद से डिवाइस को कंट्रोल करें"</string> <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"सुलभता मेन्यू सेटिंग"</string> <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"बड़े बटन"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml index fa8b587e62c7..98c91ed65056 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml @@ -21,7 +21,7 @@ <string name="previous_button_content_description" msgid="840869171117765966">"Мурунку экранга өтүү"</string> <string name="next_button_content_description" msgid="6810058269847364406">"Кийинки экранга өтүү"</string> <string name="accessibility_menu_description" msgid="4458354794093858297">"Атайын мүмкүнчүлүктөр менюсу — бул түзмөгүңүздү көзөмөлдөөнү жеңилдетүүгө ылайыкташтырылган экрандагы чоң меню. Түзмөгүңүздү кулпулап, үнүнүн катуулугун жана экрандын жарыктыгын көзөмөлдөп, скриншотторду тартып жана башка аракеттерди аткара аласыз."</string> - <string name="accessibility_menu_summary" msgid="340071398148208130">"Түзмөктү чоң менюдан башкаруу"</string> + <string name="accessibility_menu_summary" msgid="340071398148208130">"Түзмөктү чоң менюдан башкарасыз"</string> <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Атайын мүмкүнчүлүктөр менюсунун параметрлери"</string> <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Чоң баскычтар"</string> <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Атайын мүмкүнчүлүктөр менюсундагы баскычтардын өлчөмүн чоңойтот"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml index 9c1ea75d90f3..fd347324d05b 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml @@ -2,14 +2,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menu Kebolehaksesan"</string> - <string name="accessibility_menu_intro" msgid="3164193281544042394">"Menu Kebolehaksesan menyediakan menu pada skrin yang besar untuk mengawal peranti anda. Anda boleh mengunci peranti anda, mengawal kelantangan dan kecerahan, mengambil tangkapan skrin dan banyak lagi."</string> + <string name="accessibility_menu_intro" msgid="3164193281544042394">"Menu Kebolehaksesan menyediakan menu yang besar pada skrin untuk mengawal peranti anda. Anda boleh mengunci peranti, mengawal kelantangan dan kecerahan, mengambil tangkapan skrin dan banyak lagi."</string> <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string> <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string> <string name="a11y_settings_label" msgid="3977714687248445050">"Tetapan Kebolehaksesan"</string> <string name="power_label" msgid="7699720321491287839">"Kuasa"</string> <string name="power_utterance" msgid="7444296686402104807">"Pilihan kuasa"</string> <string name="recent_apps_label" msgid="6583276995616385847">"Apl terbaharu"</string> - <string name="lockscreen_label" msgid="648347953557887087">"Kunci skrin"</string> + <string name="lockscreen_label" msgid="648347953557887087">"Skrin kunci"</string> <string name="quick_settings_label" msgid="2999117381487601865">"Tetapan Pantas"</string> <string name="notifications_label" msgid="6829741046963013567">"Pemberitahuan"</string> <string name="screenshot_label" msgid="863978141223970162">"Tangkapan skrin"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml index a8d6a0bc090c..3f72d955cc99 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml @@ -2,7 +2,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="accessibility_menu_service_name" msgid="730136711554740131">"Toegankelijkheidsmenu"</string> - <string name="accessibility_menu_intro" msgid="3164193281544042394">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid beheren en screenshots maken."</string> + <string name="accessibility_menu_intro" msgid="3164193281544042394">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid aanpassen en screenshots maken."</string> <string name="assistant_label" msgid="6796392082252272356">"Assistent"</string> <string name="assistant_utterance" msgid="65509599221141377">"Assistent"</string> <string name="a11y_settings_label" msgid="3977714687248445050">"Instellingen voor toegankelijkheid"</string> @@ -21,7 +21,7 @@ <string name="previous_button_content_description" msgid="840869171117765966">"Ga naar vorig scherm"</string> <string name="next_button_content_description" msgid="6810058269847364406">"Ga naar volgend scherm"</string> <string name="accessibility_menu_description" msgid="4458354794093858297">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid aanpassen en screenshots maken."</string> - <string name="accessibility_menu_summary" msgid="340071398148208130">"Bedien apparaat via groot menu"</string> + <string name="accessibility_menu_summary" msgid="340071398148208130">"Bedien het apparaat via een groot menu"</string> <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Instellingen toegankelijkheidsmenu"</string> <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Grote knoppen"</string> <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Vergroot knoppen in het toegankelijkheidsmenu"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml index 44aff75d1021..0cc2f58e13b5 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml @@ -21,7 +21,7 @@ <string name="previous_button_content_description" msgid="840869171117765966">"Ir para o ecrã anterior"</string> <string name="next_button_content_description" msgid="6810058269847364406">"Ir para o ecrã seguinte"</string> <string name="accessibility_menu_description" msgid="4458354794093858297">"O menu Acessibilidade disponibiliza um menu grande no ecrã para controlar o dispositivo. Pode bloquear o dispositivo, controlar o volume e o brilho, fazer capturas de ecrã e muito mais."</string> - <string name="accessibility_menu_summary" msgid="340071398148208130">"Controle o dispositivo através do menu grande"</string> + <string name="accessibility_menu_summary" msgid="340071398148208130">"Controlar dispositivo através do menu grande"</string> <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Definições do menu Acessibilidade"</string> <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Botões grandes"</string> <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Aumentar o tamanho dos botões do menu Acessibilidade"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml index 264749814e6c..62f63a8739d4 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml @@ -2,7 +2,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="accessibility_menu_service_name" msgid="730136711554740131">"Ponuka Dostupnosť"</string> - <string name="accessibility_menu_intro" msgid="3164193281544042394">"Ponukou dostupnosti sa rozumie veľká ponuka na obrazovke, pomocou ktorej môžete ovládať zariadenie. Môžete ho uzamknúť, ovládať hlasitosť a jas, vytvárať snímky obrazovky a mnoho ďalšieho."</string> + <string name="accessibility_menu_intro" msgid="3164193281544042394">"Ponukou Dostupnosť sa rozumie veľká ponuka na obrazovke, pomocou ktorej môžete ovládať zariadenie. Môžete ho uzamknúť, ovládať hlasitosť a jas, vytvárať snímky obrazovky a mnoho ďalšieho."</string> <string name="assistant_label" msgid="6796392082252272356">"Asistent"</string> <string name="assistant_utterance" msgid="65509599221141377">"Asistent"</string> <string name="a11y_settings_label" msgid="3977714687248445050">"Nastavenia dostupnosti"</string> @@ -21,7 +21,7 @@ <string name="previous_button_content_description" msgid="840869171117765966">"Prejsť na predchádzajúcu obrazovku"</string> <string name="next_button_content_description" msgid="6810058269847364406">"Prejsť na ďalšiu obrazovku"</string> <string name="accessibility_menu_description" msgid="4458354794093858297">"Ponuka dostupnosti spustí na obrazovke telefónu veľkú ponuku, pomocou ktorej môžete ovládať svoje zariadenie. Môžete ho uzamknúť, ovládať hlasitosť a jas, vytvárať snímky obrazovky a mnoho ďalšieho."</string> - <string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládať zariadenie pomocou veľkej ponuky"</string> + <string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládanie zariadenia pomocou veľkej ponuky"</string> <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Nastavenia ponuky dostupnosti"</string> <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Veľké tlačidlá"</string> <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Zväčšiť tlačidlá ponuky dostupnosti"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java index 5f3d1eafb4fb..0ab99fac9ba3 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java @@ -30,8 +30,6 @@ import static com.android.systemui.accessibility.accessibilitymenu.Accessibility import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_TOGGLE_MENU; import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.PACKAGE_NAME; -import static com.google.common.truth.Truth.assertThat; - import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Instrumentation; import android.app.KeyguardManager; @@ -449,7 +447,10 @@ public class AccessibilityMenuServiceTest { closeScreen(); wakeUpScreen(); - assertThat(isMenuVisible()).isFalse(); + TestUtils.waitUntil("Menu did not close.", + TIMEOUT_UI_CHANGE_S, + () -> !isMenuVisible() + ); } @Test diff --git a/packages/SystemUI/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig index 8137e408ba39..14ebc3907c04 100644 --- a/packages/SystemUI/aconfig/accessibility.aconfig +++ b/packages/SystemUI/aconfig/accessibility.aconfig @@ -32,6 +32,16 @@ flag { } flag { + name: "floating_menu_narrow_target_content_observer" + namespace: "accessibility" + description: "stops the FAB from monitoring enabled services to trigger target content changes." + bug: "331740049" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "floating_menu_overlaps_nav_bars_flag" namespace: "accessibility" description: "Adjusts bounds to allow the floating menu to render on top of navigation bars." diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 6810aac92925..c979d053617a 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -148,6 +148,16 @@ flag { } flag { + name: "pss_app_selector_recents_split_screen" + namespace: "systemui" + description: "Allows recent apps selected for partial screenshare to be launched in split screen mode" + bug: "320449039" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "notifications_background_icons" namespace: "systemui" description: "Moves part of the notification icon updates to the background." @@ -328,6 +338,16 @@ flag { } flag { + name: "status_bar_monochrome_icons_fix" + namespace: "systemui" + description: "Fixes the status bar icon size when drawing InsetDrawables (ie. monochrome icons)" + bug: "329091967" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "compose_bouncer" namespace: "systemui" description: "Use the new compose bouncer in SystemUI" @@ -457,10 +477,13 @@ flag { } flag { - name: "screenshot_private_profile" + name: "screenshot_private_profile_behavior_fix" namespace: "systemui" description: "Private profile support for screenshots" bug: "327613051" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { @@ -726,8 +749,38 @@ flag { } flag { + name: "remove_dream_overlay_hide_on_touch" + namespace: "systemui" + description: "Removes logic to hide the dream overlay on user interaction, as it conflicts with various transitions" + bug: "329091030" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "keyboard_docking_indicator" namespace: "systemui" description: "Glow bar indicator reveals upon keyboard docking." bug: "324600132" } + +flag { + name: "dream_overlay_bouncer_swipe_direction_filtering" + namespace: "systemui" + description: "do not initiate bouncer swipe when the direction is opposite of the expansion" + bug: "333632464" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "dream_input_session_pilfer_once" + namespace: "systemui" + description: "Pilfer at most once per input session" + bug: "324600132" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java index e20425d4b98c..94f884673fbd 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java @@ -36,6 +36,7 @@ import android.view.WindowManager; import android.view.WindowManager.TransitionOldType; import android.window.IRemoteTransition; import android.window.IRemoteTransitionFinishedCallback; +import android.window.RemoteTransitionStub; import android.window.TransitionInfo; import com.android.wm.shell.shared.CounterRotator; @@ -69,8 +70,8 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner } /** Wraps a remote animation runner in a remote-transition. */ - public static IRemoteTransition.Stub wrap(IRemoteAnimationRunner runner) { - return new IRemoteTransition.Stub() { + public static RemoteTransitionStub wrap(IRemoteAnimationRunner runner) { + return new RemoteTransitionStub() { final ArrayMap<IBinder, Runnable> mFinishRunnables = new ArrayMap<>(); @Override @@ -233,11 +234,6 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner runner.onAnimationCancelled(); finishRunnable.run(); } - - @Override - public void onTransitionConsumed(IBinder iBinder, boolean aborted) - throws RemoteException { - } }; } } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt index 4d327e1d8beb..6c982a045084 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt @@ -41,9 +41,9 @@ fun BackAnimationSpec.Companion.createFloatingSurfaceAnimationSpec( maxMarginXdp: Float, maxMarginYdp: Float, minScale: Float, - translateXEasing: Interpolator = Interpolators.STANDARD_DECELERATE, + translateXEasing: Interpolator = Interpolators.BACK_GESTURE, translateYEasing: Interpolator = Interpolators.LINEAR, - scaleEasing: Interpolator = Interpolators.STANDARD_DECELERATE, + scaleEasing: Interpolator = Interpolators.BACK_GESTURE, ): BackAnimationSpec { return BackAnimationSpec { backEvent, progressY, result -> val displayMetrics = displayMetricsProvider() diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt new file mode 100644 index 000000000000..d50979ccd01d --- /dev/null +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.surfaceeffects + +import android.graphics.Paint +import android.graphics.RenderEffect + +/** + * A callback with a [Paint] object that contains shader info, which is triggered every frame while + * animation is playing. Note that the [Paint] object here is always the same instance. + * + * This approach is more performant than other ones because [RenderEffect] forces an intermediate + * render pass of the View to a texture to feed into it. + * + * The usage of this callback is as follows: + * <pre>{@code + * private var paint: Paint? = null + * // Override [View.onDraw]. + * override fun onDraw(canvas: Canvas) { + * // RuntimeShader requires hardwareAcceleration. + * if (!canvas.isHardwareAccelerated) return + * + * paint?.let { canvas.drawPaint(it) } + * } + * + * // Given that this is called [PaintDrawCallback.onDraw] + * fun draw(paint: Paint) { + * this.paint = paint + * + * // Must call invalidate to trigger View#onDraw + * invalidate() + * } + * }</pre> + * + * Please refer to [RenderEffectDrawCallback] for alternative approach. + */ +interface PaintDrawCallback { + fun onDraw(paint: Paint) +} diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt new file mode 100644 index 000000000000..db7ee58090a9 --- /dev/null +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.surfaceeffects + +import android.graphics.RenderEffect + +/** + * A callback with a [RenderEffect] object that contains shader info, which is triggered every frame + * while animation is playing. Note that the [RenderEffect] instance is different each time to + * update shader uniforms. + * + * The usage of this callback is as follows: + * <pre>{@code + * private val xEffectDrawingCallback = RenderEffectDrawCallback() { + * val myOtherRenderEffect = createOtherRenderEffect() + * val chainEffect = RenderEffect.createChainEffect(renderEffect, myOtherRenderEffect) + * myView.setRenderEffect(chainEffect) + * } + * + * private val xEffect = XEffect(config, xEffectDrawingCallback) + * }</pre> + */ +interface RenderEffectDrawCallback { + fun onDraw(renderEffect: RenderEffect) +} diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt index 1c763e8c6108..211b84f25369 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt @@ -22,6 +22,8 @@ import android.animation.ValueAnimator import android.graphics.Paint import android.graphics.RenderEffect import android.view.View +import com.android.systemui.surfaceeffects.PaintDrawCallback +import com.android.systemui.surfaceeffects.RenderEffectDrawCallback import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader @@ -334,52 +336,31 @@ private constructor( ) } - companion object { + /** + * States of the loading effect animation. + * + * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN], + * [AnimationState.MAIN], [AnimationState.EASE_OUT]. Note that ease in and out don't necessarily + * mean the acceleration and deceleration in the animation curve. They simply mean each stage of + * the animation. (i.e. Intro, core, and rest) + */ + enum class AnimationState { + EASE_IN, + MAIN, + EASE_OUT, + NOT_PLAYING + } + + /** Optional callback that is triggered when the animation state changes. */ + interface AnimationStateChangedCallback { /** - * States of the loading effect animation. - * - * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN], - * [AnimationState.MAIN], [AnimationState.EASE_OUT]. Note that ease in and out don't - * necessarily mean the acceleration and deceleration in the animation curve. They simply - * mean each stage of the animation. (i.e. Intro, core, and rest) + * A callback that's triggered when the [AnimationState] changes. Example usage is + * performing a cleanup when [AnimationState] becomes [NOT_PLAYING]. */ - enum class AnimationState { - EASE_IN, - MAIN, - EASE_OUT, - NOT_PLAYING - } - - /** Client must implement one of the draw callbacks. */ - interface PaintDrawCallback { - /** - * A callback with a [Paint] object that contains shader info, which is triggered every - * frame while animation is playing. Note that the [Paint] object here is always the - * same instance. - */ - fun onDraw(loadingPaint: Paint) - } - - interface RenderEffectDrawCallback { - /** - * A callback with a [RenderEffect] object that contains shader info, which is triggered - * every frame while animation is playing. Note that the [RenderEffect] instance is - * different each time to update shader uniforms. - */ - fun onDraw(loadingRenderEffect: RenderEffect) - } - - /** Optional callback that is triggered when the animation state changes. */ - interface AnimationStateChangedCallback { - /** - * A callback that's triggered when the [AnimationState] changes. Example usage is - * performing a cleanup when [AnimationState] becomes [NOT_PLAYING]. - */ - fun onStateChanged(oldState: AnimationState, newState: AnimationState) {} - } + fun onStateChanged(oldState: AnimationState, newState: AnimationState) {} + } + private companion object { private const val MS_TO_SEC = 0.001f - - private val TAG = LoadingEffect::class.java.simpleName } } diff --git a/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt b/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt index 4a89e31bcea8..36e6909a15cf 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt @@ -25,7 +25,6 @@ import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.interaction.DragInteraction import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -63,7 +62,6 @@ import androidx.compose.ui.layout.Placeable import androidx.compose.ui.layout.layoutId import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.colorResource import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset @@ -458,40 +456,19 @@ object PlatformSliderDefaults { @Composable fun defaultPlatformSliderColors(): PlatformSliderColors = - if (isSystemInDarkTheme()) darkThemePlatformSliderColors() - else lightThemePlatformSliderColors() + PlatformSliderColors( + trackColor = MaterialTheme.colorScheme.secondaryContainer, + indicatorColor = MaterialTheme.colorScheme.primary, + iconColor = MaterialTheme.colorScheme.onPrimary, + labelColorOnIndicator = MaterialTheme.colorScheme.onPrimary, + labelColorOnTrack = MaterialTheme.colorScheme.onSecondaryContainer, + disabledTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest, + disabledIndicatorColor = MaterialTheme.colorScheme.surfaceContainerHighest, + disabledIconColor = MaterialTheme.colorScheme.outline, + disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant, + ) } -/** [PlatformSliderColors] for the light theme */ -@Composable -private fun lightThemePlatformSliderColors() = - PlatformSliderColors( - trackColor = colorResource(android.R.color.system_accent3_200), - indicatorColor = MaterialTheme.colorScheme.tertiary, - iconColor = MaterialTheme.colorScheme.onTertiary, - labelColorOnIndicator = MaterialTheme.colorScheme.onTertiary, - labelColorOnTrack = MaterialTheme.colorScheme.onTertiaryContainer, - disabledTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest, - disabledIndicatorColor = MaterialTheme.colorScheme.surfaceContainerHighest, - disabledIconColor = MaterialTheme.colorScheme.outline, - disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant, - ) - -/** [PlatformSliderColors] for the dark theme */ -@Composable -private fun darkThemePlatformSliderColors() = - PlatformSliderColors( - trackColor = colorResource(android.R.color.system_accent3_600), - indicatorColor = MaterialTheme.colorScheme.tertiary, - iconColor = MaterialTheme.colorScheme.onTertiary, - labelColorOnIndicator = MaterialTheme.colorScheme.onTertiary, - labelColorOnTrack = colorResource(android.R.color.system_accent3_900), - disabledTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest, - disabledIndicatorColor = MaterialTheme.colorScheme.surfaceContainerHighest, - disabledIconColor = MaterialTheme.colorScheme.outline, - disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant, - ) - private fun PlatformSliderColors.getTrackColor(isEnabled: Boolean): Color = if (isEnabled) trackColor else disabledTrackColor diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt index 0f3d3dc2847f..d55d4e494980 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt @@ -160,7 +160,9 @@ private fun StandardLayout( FoldAware( modifier = modifier.padding( + start = 32.dp, top = 92.dp, + end = 32.dp, bottom = 48.dp, ), viewModel = viewModel, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt index 3ec5508c81b3..d59f1f5bbe25 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt @@ -22,11 +22,8 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.android.compose.animation.scene.Back import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope -import com.android.compose.animation.scene.Swipe -import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.bouncer.ui.BouncerDialogFactory @@ -35,9 +32,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene import javax.inject.Inject -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow object Bouncer { object Elements { @@ -57,13 +52,7 @@ constructor( override val key = Scenes.Bouncer override val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> = - MutableStateFlow( - mapOf( - Back to UserActionResult(Scenes.Lockscreen), - Swipe(SwipeDirection.Down) to UserActionResult(Scenes.Lockscreen), - ) - ) - .asStateFlow() + viewModel.destinationScenes @Composable override fun SceneScope.Content( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt index a78c2c0d16c6..07c2d3c95e01 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt @@ -432,12 +432,12 @@ private fun offset( } } -private const val DOT_DIAMETER_DP = 16 -private const val SELECTED_DOT_DIAMETER_DP = 24 +private const val DOT_DIAMETER_DP = 14 +private const val SELECTED_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 1.5).toInt() private const val SELECTED_DOT_REACTION_ANIMATION_DURATION_MS = 83 private const val SELECTED_DOT_RETRACT_ANIMATION_DURATION_MS = 750 -private const val LINE_STROKE_WIDTH_DP = 16 -private const val FAILURE_ANIMATION_DOT_DIAMETER_DP = 13 +private const val LINE_STROKE_WIDTH_DP = DOT_DIAMETER_DP +private const val FAILURE_ANIMATION_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 0.81f).toInt() private const val FAILURE_ANIMATION_DOT_SHRINK_ANIMATION_DURATION_MS = 50 private const val FAILURE_ANIMATION_DOT_SHRINK_STAGGER_DELAY_MS = 33 private const val FAILURE_ANIMATION_DOT_REVERT_ANIMATION_DURATION = 617 diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt index bdd888f45182..4533f58c1c37 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt @@ -26,6 +26,7 @@ import com.android.compose.animation.scene.observableTransitionState import com.android.compose.animation.scene.transitions import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.res.R @@ -41,6 +42,11 @@ object Communal { } val sceneTransitions = transitions { + to(CommunalScenes.Communal, key = CommunalTransitionKeys.SimpleFade) { + spec = tween(durationMillis = 250) + fade(Communal.Elements.Scrim) + fade(Communal.Elements.Content) + } to(CommunalScenes.Communal) { spec = tween(durationMillis = 1000) translate(Communal.Elements.Content, Edge.Right) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/UnfoldModifiers.kt b/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/UnfoldModifiers.kt new file mode 100644 index 000000000000..c2a2696777e5 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/UnfoldModifiers.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.fold.ui.composable + +import androidx.annotation.FloatRange +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.LayoutDirection +import com.android.compose.modifiers.padding +import kotlin.math.roundToInt + +/** + * Applies a translation that feeds off of the unfold transition that's active while the device is + * being folded or unfolded, effectively shifting the element towards the fold hinge. + * + * @param startSide `true` if the affected element is on the start side (left-hand side in + * left-to-right layouts), `false` otherwise. + * @param fullTranslation The maximum translation to apply when the element is the most shifted. The + * modifier will never apply more than this much translation on the element. + * @param unfoldProgress A provider for the amount of progress of the unfold transition. This should + * be sourced from the `UnfoldTransitionInteractor`, ideally through a view-model. + */ +@Composable +fun Modifier.unfoldTranslation( + startSide: Boolean, + fullTranslation: Dp, + @FloatRange(from = 0.0, to = 1.0) unfoldProgress: () -> Float, +): Modifier { + val translateToTheRight = startSide && LocalLayoutDirection.current == LayoutDirection.Ltr + return this.graphicsLayer { + translationX = + fullTranslation.toPx() * + if (translateToTheRight) { + 1 - unfoldProgress() + } else { + unfoldProgress() - 1 + } + } +} + +/** + * Applies horizontal padding that feeds off of the unfold transition that's active while the device + * is being folded or unfolded, effectively "squishing" the element on both sides. + * + * This is horizontal padding so it's applied on both the start and end sides of the element. + * + * @param fullPadding The maximum padding to apply when the element is the most padded. The modifier + * will never apply more than this much horizontal padding on the element. + * @param unfoldProgress A provider for the amount of progress of the unfold transition. This should + * be sourced from the `UnfoldTransitionInteractor`, ideally through a view-model. + */ +@Composable +fun Modifier.unfoldHorizontalPadding( + fullPadding: Dp, + @FloatRange(from = 0.0, to = 1.0) unfoldProgress: () -> Float, +): Modifier { + return this.padding( + horizontal = { (fullPadding.toPx() * (1 - unfoldProgress())).roundToInt() }, + ) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt index 55f7f69a08d6..52cbffbc0177 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt @@ -19,8 +19,6 @@ package com.android.systemui.keyguard.ui.composable import com.android.systemui.keyguard.ui.composable.blueprint.CommunalBlueprintModule import com.android.systemui.keyguard.ui.composable.blueprint.DefaultBlueprintModule import com.android.systemui.keyguard.ui.composable.blueprint.ShortcutsBesideUdfpsBlueprintModule -import com.android.systemui.keyguard.ui.composable.blueprint.SplitShadeWeatherClockBlueprintModule -import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockBlueprintModule import com.android.systemui.keyguard.ui.composable.section.OptionalSectionModule import dagger.Module @@ -31,8 +29,6 @@ import dagger.Module DefaultBlueprintModule::class, OptionalSectionModule::class, ShortcutsBesideUdfpsBlueprintModule::class, - SplitShadeWeatherClockBlueprintModule::class, - WeatherClockBlueprintModule::class, ], ) interface LockscreenSceneBlueprintModule diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt index acd9e3dc83cb..c6fe81af59b7 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt @@ -25,6 +25,9 @@ import com.android.compose.animation.scene.transitions import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.largeClockElementKey import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.smallClockElementKey import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.smartspaceElementKey +import com.android.systemui.keyguard.ui.composable.blueprint.ClockTransition.transitioningToLargeClock +import com.android.systemui.keyguard.ui.composable.blueprint.ClockTransition.transitioningToSmallClock +import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys.largeWeatherClockElementKeyList import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.ClockFaceInTransition.Companion.CLOCK_IN_MILLIS import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.ClockFaceInTransition.Companion.CLOCK_IN_START_DELAY_MILLIS import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.ClockFaceOutTransition.Companion.CLOCK_OUT_MILLIS @@ -34,30 +37,45 @@ import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSi object ClockTransition { val defaultClockTransitions = transitions { from(ClockScenes.smallClockScene, to = ClockScenes.largeClockScene) { - transitioningToLargeClock() + transitioningToLargeClock(largeClockElements = listOf(largeClockElementKey)) } from(ClockScenes.largeClockScene, to = ClockScenes.smallClockScene) { - transitioningToSmallClock() + transitioningToSmallClock(largeClockElements = listOf(largeClockElementKey)) } from(ClockScenes.splitShadeLargeClockScene, to = ClockScenes.largeClockScene) { - spec = tween(1000, easing = LinearEasing) + spec = tween(300, easing = LinearEasing) + } + + from(WeatherClockScenes.largeClockScene, to = ClockScenes.smallClockScene) { + transitioningToSmallClock(largeClockElements = largeWeatherClockElementKeyList) + } + + from(ClockScenes.smallClockScene, to = WeatherClockScenes.largeClockScene) { + transitioningToLargeClock(largeClockElements = largeWeatherClockElementKeyList) + } + + from( + WeatherClockScenes.largeClockScene, + to = WeatherClockScenes.splitShadeLargeClockScene + ) { + spec = tween(300, easing = LinearEasing) } } - private fun TransitionBuilder.transitioningToLargeClock() { + private fun TransitionBuilder.transitioningToLargeClock(largeClockElements: List<ElementKey>) { spec = tween(durationMillis = STATUS_AREA_MOVE_UP_MILLIS.toInt()) timestampRange( startMillis = CLOCK_IN_START_DELAY_MILLIS.toInt(), endMillis = (CLOCK_IN_START_DELAY_MILLIS + CLOCK_IN_MILLIS).toInt() ) { - fade(largeClockElementKey) + largeClockElements.forEach { fade(it) } } timestampRange(endMillis = CLOCK_OUT_MILLIS.toInt()) { fade(smallClockElementKey) } anchoredTranslate(smallClockElementKey, smartspaceElementKey) } - private fun TransitionBuilder.transitioningToSmallClock() { + private fun TransitionBuilder.transitioningToSmallClock(largeClockElements: List<ElementKey>) { spec = tween(durationMillis = STATUS_AREA_MOVE_DOWN_MILLIS.toInt()) timestampRange( startMillis = CLOCK_IN_START_DELAY_MILLIS.toInt(), @@ -66,7 +84,9 @@ object ClockTransition { fade(smallClockElementKey) } - timestampRange(endMillis = CLOCK_OUT_MILLIS.toInt()) { fade(largeClockElementKey) } + timestampRange(endMillis = CLOCK_OUT_MILLIS.toInt()) { + largeClockElements.forEach { fade(it) } + } anchoredTranslate(smallClockElementKey, smartspaceElementKey) } } @@ -81,14 +101,26 @@ object ClockScenes { object ClockElementKeys { val largeClockElementKey = ElementKey("large-clock") val smallClockElementKey = ElementKey("small-clock") - val weatherSmallClockElementKey = ElementKey("weather-small-clock") val smartspaceElementKey = ElementKey("smart-space") } +object WeatherClockScenes { + val largeClockScene = SceneKey("large-weather-clock-scene") + val splitShadeLargeClockScene = SceneKey("split-shade-large-weather-clock-scene") +} + object WeatherClockElementKeys { val timeElementKey = ElementKey("weather-large-clock-time") val dateElementKey = ElementKey("weather-large-clock-date") val weatherIconElementKey = ElementKey("weather-large-clock-weather-icon") val temperatureElementKey = ElementKey("weather-large-clock-temperature") val dndAlarmElementKey = ElementKey("weather-large-clock-dnd-alarm") + val largeWeatherClockElementKeyList = + listOf( + timeElementKey, + dateElementKey, + weatherIconElementKey, + temperatureElementKey, + dndAlarmElementKey + ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt deleted file mode 100644 index cba54531713b..000000000000 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.keyguard.ui.composable.blueprint - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.Layout -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.IntRect -import androidx.compose.ui.unit.dp -import com.android.compose.animation.scene.SceneScope -import com.android.compose.modifiers.padding -import com.android.keyguard.KeyguardClockSwitch.LARGE -import com.android.systemui.Flags -import com.android.systemui.customization.R as customizationR -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID -import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.ui.composable.LockscreenLongPress -import com.android.systemui.keyguard.ui.composable.modifier.onTopPlacementChanged -import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection -import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection -import com.android.systemui.keyguard.ui.composable.section.LockSection -import com.android.systemui.keyguard.ui.composable.section.MediaCarouselSection -import com.android.systemui.keyguard.ui.composable.section.NotificationSection -import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection -import com.android.systemui.keyguard.ui.composable.section.SmartSpaceSection -import com.android.systemui.keyguard.ui.composable.section.StatusBarSection -import com.android.systemui.keyguard.ui.composable.section.WeatherClockSection -import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel -import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel -import com.android.systemui.res.R -import com.android.systemui.shade.LargeScreenHeaderHelper -import dagger.Binds -import dagger.Module -import dagger.multibindings.IntoSet -import java.util.Optional -import javax.inject.Inject - -class WeatherClockBlueprint -@Inject -constructor( - private val viewModel: LockscreenContentViewModel, - private val statusBarSection: StatusBarSection, - private val weatherClockSection: WeatherClockSection, - private val smartSpaceSection: SmartSpaceSection, - private val notificationSection: NotificationSection, - private val lockSection: LockSection, - private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>, - private val bottomAreaSection: BottomAreaSection, - private val settingsMenuSection: SettingsMenuSection, - private val clockInteractor: KeyguardClockInteractor, - private val mediaCarouselSection: MediaCarouselSection, - private val clockViewModel: KeyguardClockViewModel, -) : ComposableLockscreenSceneBlueprint { - - override val id: String = WEATHER_CLOCK_BLUEPRINT_ID - @Composable - override fun SceneScope.Content(modifier: Modifier) { - val isUdfpsVisible = viewModel.isUdfpsVisible - val burnIn = rememberBurnIn(clockInteractor) - val resources = LocalContext.current.resources - val currentClockState = clockViewModel.currentClock.collectAsState() - val areNotificationsVisible by viewModel.areNotificationsVisible.collectAsState() - LockscreenLongPress( - viewModel = viewModel.longPress, - modifier = modifier, - ) { onSettingsMenuPlaced -> - Layout( - content = { - // Constrained to above the lock icon. - Column( - modifier = Modifier.fillMaxWidth(), - ) { - with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) } - val currentClock = currentClockState.value - val clockSize by clockViewModel.clockSize.collectAsState() - with(weatherClockSection) { - if (currentClock == null) { - return@with - } - - if (clockSize == LARGE) { - Time( - clock = currentClock, - modifier = - Modifier.padding( - start = - dimensionResource( - customizationR.dimen.clock_padding_start - ) - ) - ) - } else { - SmallClock( - burnInParams = burnIn.parameters, - modifier = - Modifier.align(Alignment.Start) - .onTopPlacementChanged(burnIn.onSmallClockTopChanged), - clock = currentClock - ) - } - } - with(smartSpaceSection) { - SmartSpace( - burnInParams = burnIn.parameters, - onTopChanged = burnIn.onSmartspaceTopChanged, - modifier = - Modifier.fillMaxWidth() - .padding( - top = { viewModel.getSmartSpacePaddingTop(resources) }, - ) - .padding( - bottom = - dimensionResource( - R.dimen.keyguard_status_view_bottom_margin - ), - ), - ) - } - - with(mediaCarouselSection) { MediaCarousel() } - - if (areNotificationsVisible) { - with(notificationSection) { - Notifications( - burnInParams = burnIn.parameters, - modifier = Modifier.fillMaxWidth().weight(weight = 1f) - ) - } - } - with(weatherClockSection) { - if (currentClock == null || clockSize != LARGE) { - return@with - } - LargeClockSectionBelowSmartspace(clock = currentClock) - } - - if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { - with(ambientIndicationSectionOptional.get()) { - AmbientIndication(modifier = Modifier.fillMaxWidth()) - } - } - } - - with(lockSection) { LockIcon() } - - // Aligned to bottom and constrained to below the lock icon. - Column(modifier = Modifier.fillMaxWidth()) { - if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { - with(ambientIndicationSectionOptional.get()) { - AmbientIndication(modifier = Modifier.fillMaxWidth()) - } - } - - with(bottomAreaSection) { - IndicationArea(modifier = Modifier.fillMaxWidth()) - } - } - - // Aligned to bottom and NOT constrained by the lock icon. - with(bottomAreaSection) { - Shortcut(isStart = true, applyPadding = true) - Shortcut(isStart = false, applyPadding = true) - } - with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) } - }, - modifier = Modifier.fillMaxSize(), - ) { measurables, constraints -> - check(measurables.size == 6) - val aboveLockIconMeasurable = measurables[0] - val lockIconMeasurable = measurables[1] - val belowLockIconMeasurable = measurables[2] - val startShortcutMeasurable = measurables[3] - val endShortcutMeasurable = measurables[4] - val settingsMenuMeasurable = measurables[5] - - val noMinConstraints = - constraints.copy( - minWidth = 0, - minHeight = 0, - ) - val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints) - val lockIconBounds = - IntRect( - left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left], - top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top], - right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right], - bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom], - ) - - val aboveLockIconPlaceable = - aboveLockIconMeasurable.measure( - noMinConstraints.copy(maxHeight = lockIconBounds.top) - ) - val belowLockIconPlaceable = - belowLockIconMeasurable.measure( - noMinConstraints.copy( - maxHeight = - (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) - ) - ) - val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints) - val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints) - val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints) - - layout(constraints.maxWidth, constraints.maxHeight) { - aboveLockIconPlaceable.place( - x = 0, - y = 0, - ) - lockIconPlaceable.place( - x = lockIconBounds.left, - y = lockIconBounds.top, - ) - belowLockIconPlaceable.place( - x = 0, - y = constraints.maxHeight - belowLockIconPlaceable.height, - ) - startShortcutPleaceable.place( - x = 0, - y = constraints.maxHeight - startShortcutPleaceable.height, - ) - endShortcutPleaceable.place( - x = constraints.maxWidth - endShortcutPleaceable.width, - y = constraints.maxHeight - endShortcutPleaceable.height, - ) - settingsMenuPlaceable.place( - x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2, - y = constraints.maxHeight - settingsMenuPlaceable.height, - ) - } - } - } - } -} - -class SplitShadeWeatherClockBlueprint -@Inject -constructor( - private val viewModel: LockscreenContentViewModel, - private val statusBarSection: StatusBarSection, - private val smartSpaceSection: SmartSpaceSection, - private val notificationSection: NotificationSection, - private val lockSection: LockSection, - private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>, - private val bottomAreaSection: BottomAreaSection, - private val settingsMenuSection: SettingsMenuSection, - private val clockInteractor: KeyguardClockInteractor, - private val largeScreenHeaderHelper: LargeScreenHeaderHelper, - private val weatherClockSection: WeatherClockSection, - private val mediaCarouselSection: MediaCarouselSection, - private val clockViewModel: KeyguardClockViewModel, -) : ComposableLockscreenSceneBlueprint { - override val id: String = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID - - @Composable - override fun SceneScope.Content(modifier: Modifier) { - val isUdfpsVisible = viewModel.isUdfpsVisible - val burnIn = rememberBurnIn(clockInteractor) - val resources = LocalContext.current.resources - val currentClockState = clockViewModel.currentClock.collectAsState() - LockscreenLongPress( - viewModel = viewModel.longPress, - modifier = modifier, - ) { onSettingsMenuPlaced -> - Layout( - content = { - // Constrained to above the lock icon. - Column( - modifier = Modifier.fillMaxSize(), - ) { - with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) } - Row( - modifier = Modifier.fillMaxSize(), - ) { - Column( - modifier = Modifier.fillMaxHeight().weight(weight = 1f), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - val currentClock = currentClockState.value - val clockSize by clockViewModel.clockSize.collectAsState() - with(weatherClockSection) { - if (currentClock == null) { - return@with - } - - if (clockSize == LARGE) { - Time( - clock = currentClock, - modifier = - Modifier.align(Alignment.Start) - .padding( - start = - dimensionResource( - customizationR.dimen - .clock_padding_start - ) - ) - ) - } else { - SmallClock( - burnInParams = burnIn.parameters, - modifier = - Modifier.align(Alignment.Start) - .onTopPlacementChanged( - burnIn.onSmallClockTopChanged - ), - clock = currentClock, - ) - } - } - with(smartSpaceSection) { - SmartSpace( - burnInParams = burnIn.parameters, - onTopChanged = burnIn.onSmartspaceTopChanged, - modifier = - Modifier.fillMaxWidth() - .padding( - top = { - viewModel.getSmartSpacePaddingTop(resources) - }, - ) - .padding( - bottom = - dimensionResource( - R.dimen - .keyguard_status_view_bottom_margin - ) - ), - ) - } - - with(mediaCarouselSection) { MediaCarousel() } - - with(weatherClockSection) { - if (currentClock == null || clockSize != LARGE) { - return@with - } - - LargeClockSectionBelowSmartspace(currentClock) - } - } - with(notificationSection) { - val splitShadeTopMargin: Dp = - if (Flags.centralizedStatusBarHeightFix()) { - largeScreenHeaderHelper.getLargeScreenHeaderHeight().dp - } else { - dimensionResource( - id = R.dimen.large_screen_shade_header_height - ) - } - Notifications( - burnInParams = burnIn.parameters, - modifier = - Modifier.fillMaxHeight() - .weight(weight = 1f) - .padding(top = splitShadeTopMargin) - ) - } - } - - if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { - with(ambientIndicationSectionOptional.get()) { - AmbientIndication(modifier = Modifier.fillMaxWidth()) - } - } - } - - with(lockSection) { LockIcon() } - - // Aligned to bottom and constrained to below the lock icon. - Column(modifier = Modifier.fillMaxWidth()) { - if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) { - with(ambientIndicationSectionOptional.get()) { - AmbientIndication(modifier = Modifier.fillMaxWidth()) - } - } - - with(bottomAreaSection) { - IndicationArea(modifier = Modifier.fillMaxWidth()) - } - } - - // Aligned to bottom and NOT constrained by the lock icon. - with(bottomAreaSection) { - Shortcut(isStart = true, applyPadding = true) - Shortcut(isStart = false, applyPadding = true) - } - with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) } - }, - modifier = Modifier.fillMaxSize(), - ) { measurables, constraints -> - check(measurables.size == 6) - val aboveLockIconMeasurable = measurables[0] - val lockIconMeasurable = measurables[1] - val belowLockIconMeasurable = measurables[2] - val startShortcutMeasurable = measurables[3] - val endShortcutMeasurable = measurables[4] - val settingsMenuMeasurable = measurables[5] - - val noMinConstraints = - constraints.copy( - minWidth = 0, - minHeight = 0, - ) - val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints) - val lockIconBounds = - IntRect( - left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left], - top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top], - right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right], - bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom], - ) - - val aboveLockIconPlaceable = - aboveLockIconMeasurable.measure( - noMinConstraints.copy(maxHeight = lockIconBounds.top) - ) - val belowLockIconPlaceable = - belowLockIconMeasurable.measure( - noMinConstraints.copy( - maxHeight = - (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) - ) - ) - val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints) - val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints) - val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints) - - layout(constraints.maxWidth, constraints.maxHeight) { - aboveLockIconPlaceable.place( - x = 0, - y = 0, - ) - lockIconPlaceable.place( - x = lockIconBounds.left, - y = lockIconBounds.top, - ) - belowLockIconPlaceable.place( - x = 0, - y = constraints.maxHeight - belowLockIconPlaceable.height, - ) - startShortcutPleaceable.place( - x = 0, - y = constraints.maxHeight - startShortcutPleaceable.height, - ) - endShortcutPleaceable.place( - x = constraints.maxWidth - endShortcutPleaceable.width, - y = constraints.maxHeight - endShortcutPleaceable.height, - ) - settingsMenuPlaceable.place( - x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2, - y = constraints.maxHeight - settingsMenuPlaceable.height, - ) - } - } - } - } -} - -@Module -interface WeatherClockBlueprintModule { - @Binds - @IntoSet - fun blueprint(blueprint: WeatherClockBlueprint): ComposableLockscreenSceneBlueprint -} - -@Module -interface SplitShadeWeatherClockBlueprintModule { - @Binds - @IntoSet - fun blueprint(blueprint: SplitShadeWeatherClockBlueprint): ComposableLockscreenSceneBlueprint -} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt index 467dbca759c8..97d5b41000de 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt @@ -32,7 +32,6 @@ import androidx.core.content.res.ResourcesCompat import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope import com.android.systemui.animation.view.LaunchableImageView -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea @@ -44,7 +43,6 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.flow.Flow @@ -56,7 +54,6 @@ constructor( private val vibratorHelper: VibratorHelper, private val indicationController: KeyguardIndicationController, private val indicationAreaViewModel: KeyguardIndicationAreaViewModel, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) { /** * Renders a single lockscreen shortcut. @@ -164,7 +161,6 @@ constructor( transitionAlpha, falsingManager, vibratorHelper, - mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt index 48684a02bd19..9f02201f1d81 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt @@ -34,7 +34,6 @@ import com.android.keyguard.LockIconView import com.android.keyguard.LockIconViewController import com.android.systemui.biometrics.AuthController import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags @@ -51,14 +50,12 @@ import com.android.systemui.shade.NotificationPanelView import com.android.systemui.statusbar.VibratorHelper import dagger.Lazy import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope class LockSection @Inject constructor( @Application private val applicationScope: CoroutineScope, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, private val windowManager: WindowManager, private val authController: AuthController, private val featureFlags: FeatureFlagsClassic, @@ -96,7 +93,6 @@ constructor( deviceEntryBackgroundViewModel.get(), falsingManager.get(), vibratorHelper.get(), - mainImmediateDispatcher, ) } } else { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt index f8e63411ed52..0934b20562b4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt @@ -16,9 +16,11 @@ package com.android.systemui.keyguard.ui.composable.section +import android.content.Context import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable @@ -26,6 +28,10 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.SceneTransitionLayout @@ -36,6 +42,7 @@ import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.smallCl import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeLargeClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeSmallClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockTransition +import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockScenes import com.android.systemui.keyguard.ui.composable.blueprint.rememberBurnIn import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import javax.inject.Inject @@ -47,6 +54,7 @@ constructor( private val smartSpaceSection: SmartSpaceSection, private val mediaCarouselSection: MediaCarouselSection, private val clockSection: DefaultClockSection, + private val weatherClockSection: WeatherClockSection, private val clockInteractor: KeyguardClockInteractor, ) { @Composable @@ -64,6 +72,10 @@ constructor( splitShadeSmallClockScene KeyguardClockViewModel.ClockLayout.LARGE_CLOCK -> largeClockScene KeyguardClockViewModel.ClockLayout.SMALL_CLOCK -> smallClockScene + KeyguardClockViewModel.ClockLayout.WEATHER_LARGE_CLOCK -> + WeatherClockScenes.largeClockScene + KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_WEATHER_LARGE_CLOCK -> + WeatherClockScenes.splitShadeLargeClockScene } SceneTransitionLayout( @@ -86,6 +98,12 @@ constructor( scene(smallClockScene) { SmallClockWithSmartSpace() } scene(largeClockScene) { LargeClockWithSmartSpace() } + + scene(WeatherClockScenes.largeClockScene) { WeatherLargeClockWithSmartSpace() } + + scene(WeatherClockScenes.splitShadeLargeClockScene) { + WeatherLargeClockWithSmartSpace(modifier = Modifier.fillMaxWidth(0.5f)) + } } } @@ -146,4 +164,50 @@ constructor( } } } + + @Composable + private fun SceneScope.WeatherLargeClockWithSmartSpace(modifier: Modifier = Modifier) { + val burnIn = rememberBurnIn(clockInteractor) + val isLargeClockVisible by clockViewModel.isLargeClockVisible.collectAsState() + val currentClockState = clockViewModel.currentClock.collectAsState() + + LaunchedEffect(isLargeClockVisible) { + if (isLargeClockVisible) { + burnIn.onSmallClockTopChanged(null) + } + } + + Column(modifier = modifier) { + val currentClock = currentClockState.value ?: return@Column + with(weatherClockSection) { Time(clock = currentClock, modifier = Modifier) } + val density = LocalDensity.current + val context = LocalContext.current + + with(smartSpaceSection) { + SmartSpace( + burnInParams = burnIn.parameters, + onTopChanged = burnIn.onSmartspaceTopChanged, + modifier = + Modifier.heightIn( + min = getDimen(context, "enhanced_smartspace_height", density) + ) + ) + } + with(weatherClockSection) { LargeClockSectionBelowSmartspace(clock = currentClock) } + } + } + + /* + * Use this function to access dimen which cannot be access by R.dimen directly + * Currently use to access dimen from BcSmartspace + * @param name Name of resources + * @param density Density required to convert dimen from Int To Dp + */ + private fun getDimen(context: Context, name: String, density: Density): Dp { + val res = context.packageManager.getResourcesForApplication(context.packageName) + val id = res.getIdentifier(name, "dimen", context.packageName) + var dimen: Dp + with(density) { dimen = (if (id == 0) 0 else res.getDimensionPixelSize(id)).toDp() } + return dimen + } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt index d3584539b3fa..a7bb308ada5c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.composable.section +import android.view.View import android.view.ViewGroup import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.IntrinsicSize @@ -27,18 +28,14 @@ import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.viewinterop.AndroidView import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope import com.android.compose.modifiers.padding -import com.android.systemui.customization.R -import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.weatherSmallClockElementKey +import com.android.systemui.customization.R as customizationR import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys -import com.android.systemui.keyguard.ui.composable.modifier.burnInAware import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel -import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.plugins.clocks.ClockController import javax.inject.Inject @@ -55,12 +52,19 @@ constructor( clock: ClockController, modifier: Modifier = Modifier, ) { - WeatherElement( - weatherClockElementViewId = R.id.weather_clock_time, - clock = clock, - elementKey = WeatherClockElementKeys.timeElementKey, - modifier = modifier.wrapContentSize(), - ) + Row( + modifier = + Modifier.padding( + horizontal = dimensionResource(customizationR.dimen.clock_padding_start) + ) + ) { + WeatherElement( + weatherClockElementViewId = customizationR.id.weather_clock_time, + clock = clock, + elementKey = WeatherClockElementKeys.timeElementKey, + modifier = modifier, + ) + } } @Composable @@ -69,7 +73,7 @@ constructor( modifier: Modifier = Modifier, ) { WeatherElement( - weatherClockElementViewId = R.id.weather_clock_date, + weatherClockElementViewId = customizationR.id.weather_clock_date, clock = clock, elementKey = WeatherClockElementKeys.dateElementKey, modifier = modifier, @@ -82,7 +86,7 @@ constructor( modifier: Modifier = Modifier, ) { WeatherElement( - weatherClockElementViewId = R.id.weather_clock_weather_icon, + weatherClockElementViewId = customizationR.id.weather_clock_weather_icon, clock = clock, elementKey = WeatherClockElementKeys.weatherIconElementKey, modifier = modifier.wrapContentSize(), @@ -95,7 +99,7 @@ constructor( modifier: Modifier = Modifier, ) { WeatherElement( - weatherClockElementViewId = R.id.weather_clock_alarm_dnd, + weatherClockElementViewId = customizationR.id.weather_clock_alarm_dnd, clock = clock, elementKey = WeatherClockElementKeys.dndAlarmElementKey, modifier = modifier.wrapContentSize(), @@ -108,7 +112,7 @@ constructor( modifier: Modifier = Modifier, ) { WeatherElement( - weatherClockElementViewId = R.id.weather_clock_temperature, + weatherClockElementViewId = customizationR.id.weather_clock_temperature, clock = clock, elementKey = WeatherClockElementKeys.temperatureElementKey, modifier = modifier.wrapContentSize(), @@ -126,12 +130,16 @@ constructor( content { AndroidView( factory = { - val view = - clock.largeClock.layout.views.first { - it.id == weatherClockElementViewId - } - (view.parent as? ViewGroup)?.removeView(view) - view + try { + val view = + clock.largeClock.layout.views.first { + it.id == weatherClockElementViewId + } + (view.parent as? ViewGroup)?.removeView(view) + view + } catch (e: NoSuchElementException) { + View(it) + } }, update = {}, modifier = modifier @@ -147,46 +155,22 @@ constructor( Row( modifier = Modifier.height(IntrinsicSize.Max) - .padding(horizontal = dimensionResource(R.dimen.clock_padding_start)) + .padding( + horizontal = dimensionResource(customizationR.dimen.clock_padding_start) + ) ) { Date(clock = clock, modifier = Modifier.wrapContentSize()) - Box(modifier = Modifier.fillMaxSize()) { + Box( + modifier = + Modifier.fillMaxSize() + .padding( + start = dimensionResource(customizationR.dimen.clock_padding_start) + ) + ) { Weather(clock = clock, modifier = Modifier.align(Alignment.TopStart)) Temperature(clock = clock, modifier = Modifier.align(Alignment.BottomEnd)) DndAlarmStatus(clock = clock, modifier = Modifier.align(Alignment.TopEnd)) } } } - - @Composable - fun SceneScope.SmallClock( - burnInParams: BurnInParameters, - modifier: Modifier = Modifier, - clock: ClockController, - ) { - val localContext = LocalContext.current - MovableElement(key = weatherSmallClockElementKey, modifier) { - content { - AndroidView( - factory = { - val view = clock.smallClock.view - if (view.parent != null) { - (view.parent as? ViewGroup)?.removeView(view) - } - view - }, - modifier = - modifier - .height(dimensionResource(R.dimen.small_clock_height)) - .padding(start = dimensionResource(R.dimen.clock_padding_start)) - .padding(top = { viewModel.getSmallClockTopMargin(localContext) }) - .burnInAware( - viewModel = aodBurnInViewModel, - params = burnInParams, - ), - update = {}, - ) - } - } - } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt index 02a12e4e0814..c6c6f5773101 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt @@ -407,15 +407,16 @@ private fun ShadeCarrierGroup( AndroidView( factory = { context -> ModernShadeCarrierGroupMobileView.constructAndBind( - context = context, - logger = viewModel.mobileIconsViewModel.logger, - slot = "mobile_carrier_shade_group", - viewModel = - (viewModel.mobileIconsViewModel.viewModelForSub( - subId, - StatusBarLocation.SHADE_CARRIER_GROUP - ) as ShadeCarrierGroupMobileIconViewModel), - ) + context = context, + logger = viewModel.mobileIconsViewModel.logger, + slot = "mobile_carrier_shade_group", + viewModel = + (viewModel.mobileIconsViewModel.viewModelForSub( + subId, + StatusBarLocation.SHADE_CARRIER_GROUP + ) as ShadeCarrierGroupMobileIconViewModel), + ) + .also { it.setOnClickListener { viewModel.onShadeCarrierGroupClicked() } } }, ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index 9bd6f817cff3..01c27a4dcc2a 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -65,6 +65,8 @@ import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.modifiers.thenIf import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.fold.ui.composable.unfoldHorizontalPadding +import com.android.systemui.fold.ui.composable.unfoldTranslation import com.android.systemui.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager @@ -289,6 +291,7 @@ private fun SceneScope.SplitShade( remember(lifecycleOwner, viewModel) { viewModel.getFooterActionsViewModel(lifecycleOwner) } val tileSquishiness by animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness) + val unfoldTransitionProgress by viewModel.unfoldTransitionProgress.collectAsState() val navBarBottomHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() val density = LocalDensity.current @@ -337,10 +340,23 @@ private fun SceneScope.SplitShade( modifier = Modifier.padding(horizontal = Shade.Dimensions.HorizontalPadding) .then(brightnessMirrorShowingModifier) + .unfoldHorizontalPadding( + fullPadding = dimensionResource(R.dimen.notification_side_paddings), + ) { + unfoldTransitionProgress + } ) Row(modifier = Modifier.fillMaxWidth().weight(1f)) { - Box(modifier = Modifier.weight(1f)) { + Box( + modifier = + Modifier.weight(1f).unfoldTranslation( + startSide = true, + fullTranslation = dimensionResource(R.dimen.notification_side_paddings), + ) { + unfoldTransitionProgress + }, + ) { BrightnessMirror( viewModel = viewModel.brightnessMirrorViewModel, qsSceneAdapter = viewModel.qsSceneAdapter, @@ -407,7 +423,16 @@ private fun SceneScope.SplitShade( Modifier.weight(1f) .fillMaxHeight() .padding(bottom = navBarBottomHeight) - .then(brightnessMirrorShowingModifier), + .then(brightnessMirrorShowingModifier) + .unfoldTranslation( + startSide = false, + fullTranslation = + dimensionResource( + R.dimen.notification_side_paddings, + ), + ) { + unfoldTransitionProgress + }, ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt index ccb5d367c357..fa052e8e3035 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt @@ -17,15 +17,12 @@ package com.android.systemui.volume.panel.component.anc import com.android.systemui.volume.panel.component.anc.domain.AncAvailabilityCriteria -import com.android.systemui.volume.panel.component.anc.ui.composable.AncPopup -import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel -import com.android.systemui.volume.panel.component.button.ui.composable.ButtonComponent +import com.android.systemui.volume.panel.component.anc.ui.composable.AncButtonComponent import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent import dagger.Binds import dagger.Module -import dagger.Provides import dagger.multibindings.IntoMap import dagger.multibindings.StringKey @@ -40,14 +37,8 @@ interface AncModule { criteria: AncAvailabilityCriteria ): ComponentAvailabilityCriteria - companion object { - - @Provides - @IntoMap - @StringKey(VolumePanelComponents.ANC) - fun provideVolumePanelUiComponent( - viewModel: AncViewModel, - popup: AncPopup, - ): VolumePanelUiComponent = ButtonComponent(viewModel.button, popup::show) - } + @Binds + @IntoMap + @StringKey(VolumePanelComponents.ANC) + fun bindVolumePanelUiComponent(component: AncButtonComponent): VolumePanelUiComponent } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt new file mode 100644 index 000000000000..00225fc3577a --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.anc.ui.composable + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.android.systemui.res.R +import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel +import com.android.systemui.volume.panel.ui.composable.ComposeVolumePanelUiComponent +import com.android.systemui.volume.panel.ui.composable.VolumePanelComposeScope +import javax.inject.Inject + +class AncButtonComponent +@Inject +constructor( + private val viewModel: AncViewModel, + private val ancPopup: AncPopup, +) : ComposeVolumePanelUiComponent { + + @Composable + override fun VolumePanelComposeScope.Content(modifier: Modifier) { + val slice by viewModel.buttonSlice.collectAsState() + val label = stringResource(R.string.volume_panel_noise_control_title) + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + SliceAndroidView( + modifier = + Modifier.height(64.dp) + .fillMaxWidth() + .semantics { + role = Role.Button + contentDescription = label + } + .clip(RoundedCornerShape(28.dp)), + slice = slice, + onWidthChanged = viewModel::onButtonSliceWidthChanged, + onClick = { ancPopup.show(null) } + ) + Text( + modifier = Modifier.clearAndSetSemantics {}, + text = label, + style = MaterialTheme.typography.labelMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt index 9f0da004730d..e1ee01e78566 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt @@ -16,9 +16,6 @@ package com.android.systemui.volume.panel.component.anc.ui.composable -import android.content.Context -import android.view.ContextThemeWrapper -import android.view.View import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.MaterialTheme @@ -30,14 +27,14 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.viewinterop.AndroidView import androidx.slice.Slice -import androidx.slice.widget.SliceView +import com.android.internal.logging.UiEventLogger import com.android.systemui.animation.Expandable import com.android.systemui.res.R import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel import com.android.systemui.volume.panel.component.popup.ui.composable.VolumePanelPopup +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import javax.inject.Inject /** ANC popup up displaying ANC control [Slice]. */ @@ -46,10 +43,12 @@ class AncPopup constructor( private val volumePanelPopup: VolumePanelPopup, private val viewModel: AncViewModel, + private val uiEventLogger: UiEventLogger, ) { /** Shows a popup with the [expandable] animation. */ - fun show(expandable: Expandable) { + fun show(expandable: Expandable?) { + uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_ANC_POPUP_SHOWN) volumePanelPopup.show(expandable, { Title() }, { Content(it) }) } @@ -66,49 +65,18 @@ constructor( @Composable private fun Content(dialog: SystemUIDialog) { - val slice: Slice? by viewModel.slice.collectAsState() + val isAvailable by viewModel.isAvailable.collectAsState(true) - if (slice == null) { + if (!isAvailable) { SideEffect { dialog.dismiss() } return } - AndroidView<SliceView>( + val slice by viewModel.popupSlice.collectAsState() + SliceAndroidView( modifier = Modifier.fillMaxWidth(), - factory = { context: Context -> - SliceView(ContextThemeWrapper(context, R.style.Widget_SliceView_VolumePanel)) - .apply { - mode = SliceView.MODE_LARGE - isScrollable = false - importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO - setShowTitleItems(true) - addOnLayoutChangeListener( - OnWidthChangedLayoutListener(viewModel::changeSliceWidth) - ) - } - }, - update = { sliceView: SliceView -> sliceView.slice = slice } + slice = slice, + onWidthChanged = viewModel::onPopupSliceWidthChanged ) } - - private class OnWidthChangedLayoutListener(private val widthChanged: (Int) -> Unit) : - View.OnLayoutChangeListener { - override fun onLayoutChange( - v: View?, - left: Int, - top: Int, - right: Int, - bottom: Int, - oldLeft: Int, - oldTop: Int, - oldRight: Int, - oldBottom: Int - ) { - val newWidth = right - left - val oldWidth = oldRight - oldLeft - if (oldWidth != newWidth) { - widthChanged(newWidth) - } - } - } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt new file mode 100644 index 000000000000..f354b80692f5 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.anc.ui.composable + +import android.annotation.SuppressLint +import android.content.Context +import android.view.ContextThemeWrapper +import android.view.MotionEvent +import android.view.View +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.viewinterop.AndroidView +import androidx.slice.Slice +import androidx.slice.widget.SliceView +import com.android.systemui.res.R + +@Composable +fun SliceAndroidView( + slice: Slice?, + modifier: Modifier = Modifier, + onWidthChanged: ((Int) -> Unit)? = null, + onClick: (() -> Unit)? = null, +) { + AndroidView( + modifier = modifier, + factory = { context: Context -> + ClickableSliceView( + ContextThemeWrapper(context, R.style.Widget_SliceView_VolumePanel), + onClick, + ) + .apply { + mode = SliceView.MODE_LARGE + isScrollable = false + importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO + setShowTitleItems(true) + if (onWidthChanged != null) { + addOnLayoutChangeListener(OnWidthChangedLayoutListener(onWidthChanged)) + } + if (onClick != null) { + setOnClickListener { onClick() } + } + } + }, + update = { sliceView: SliceView -> sliceView.slice = slice } + ) +} + +class OnWidthChangedLayoutListener(private val widthChanged: (Int) -> Unit) : + View.OnLayoutChangeListener { + + override fun onLayoutChange( + v: View?, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + val newWidth = right - left + val oldWidth = oldRight - oldLeft + if (oldWidth != newWidth) { + widthChanged(newWidth) + } + } +} + +/** + * [SliceView] that prioritises [onClick] when its clicked instead of passing the event to the slice + * first. + */ +@SuppressLint("ViewConstructor") // only used in this class +private class ClickableSliceView( + context: Context, + private val onClick: (() -> Unit)?, +) : SliceView(context) { + + init { + if (onClick != null) { + setOnClickListener {} + } + } + + override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { + return onClick != null || super.onInterceptTouchEvent(ev) + } + + override fun onClick(v: View?) { + onClick?.let { it() } ?: super.onClick(v) + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt index fc511e12ec54..e15d315f9a0a 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt @@ -69,9 +69,9 @@ class ButtonComponent( role = Role.Button contentDescription = label }, - color = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.tertiaryContainer, shape = RoundedCornerShape(28.dp), - contentColor = MaterialTheme.colorScheme.onPrimaryContainer, + contentColor = MaterialTheme.colorScheme.onTertiaryContainer, onClick = onClick, ) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt index 780e3f2de4c8..b2351c492fc1 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt @@ -66,8 +66,8 @@ class ToggleButtonComponent( val colors = if (viewModel.isChecked) { ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer, + containerColor = MaterialTheme.colorScheme.tertiaryContainer, + contentColor = MaterialTheme.colorScheme.onTertiaryContainer, ) } else { ButtonDefaults.buttonColors( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt index 9f9bc623a6b3..b489dfc2e39b 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt @@ -59,7 +59,7 @@ constructor( * @param content is the popup body */ fun show( - expandable: Expandable, + expandable: Expandable?, title: @Composable (SystemUIDialog) -> Unit, content: @Composable (SystemUIDialog) -> Unit, ) { @@ -70,7 +70,7 @@ constructor( ) { PopupComposable(it, title, content) } - val controller = expandable.dialogTransitionController() + val controller = expandable?.dialogTransitionController() if (controller == null) { dialog.show() } else { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt index c74331477229..51e206470389 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt @@ -30,9 +30,11 @@ import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment @@ -119,6 +121,7 @@ fun VolumePanelRadioButtonBar( ) { for (itemIndex in items.indices) { val item = items[itemIndex] + val isSelected = itemIndex == scope.selectedIndex Row( modifier = Modifier.height(48.dp) @@ -126,7 +129,7 @@ fun VolumePanelRadioButtonBar( .semantics { item.contentDescription?.let { contentDescription = it } role = Role.Switch - selected = itemIndex == scope.selectedIndex + selected = isSelected } .clickable( interactionSource = null, @@ -137,7 +140,11 @@ fun VolumePanelRadioButtonBar( verticalAlignment = Alignment.CenterVertically, ) { if (item.icon !== Empty) { - with(items[itemIndex]) { icon() } + CompositionLocalProvider( + LocalContentColor provides colors.getIconColor(isSelected) + ) { + with(items[itemIndex]) { icon() } + } } } } @@ -163,7 +170,10 @@ fun VolumePanelRadioButtonBar( ) { val item = items[itemIndex] if (item.icon !== Empty) { - with(items[itemIndex]) { label() } + val textColor = colors.getLabelColor(itemIndex == scope.selectedIndex) + CompositionLocalProvider(LocalContentColor provides textColor) { + with(items[itemIndex]) { label() } + } } } } @@ -265,8 +275,22 @@ data class VolumePanelRadioButtonBarColors( val indicatorColor: Color, /** Color of the indicator background. */ val indicatorBackgroundColor: Color, + /** Color of the icon. */ + val iconColor: Color, + /** Color of the icon when it's selected. */ + val selectedIconColor: Color, + /** Color of the label. */ + val labelColor: Color, + /** Color of the label when it's selected. */ + val selectedLabelColor: Color, ) +private fun VolumePanelRadioButtonBarColors.getIconColor(selected: Boolean): Color = + if (selected) selectedIconColor else iconColor + +private fun VolumePanelRadioButtonBarColors.getLabelColor(selected: Boolean): Color = + if (selected) selectedLabelColor else labelColor + object VolumePanelRadioButtonBarDefaults { val DefaultIndicatorBackgroundPadding = 8.dp @@ -283,12 +307,20 @@ object VolumePanelRadioButtonBarDefaults { */ @Composable fun defaultColors( - indicatorColor: Color = MaterialTheme.colorScheme.primaryContainer, + indicatorColor: Color = MaterialTheme.colorScheme.tertiaryContainer, indicatorBackgroundColor: Color = MaterialTheme.colorScheme.surface, + iconColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, + selectedIconColor: Color = MaterialTheme.colorScheme.onTertiaryContainer, + labelColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, + selectedLabelColor: Color = MaterialTheme.colorScheme.onSurface, ): VolumePanelRadioButtonBarColors = VolumePanelRadioButtonBarColors( indicatorColor = indicatorColor, indicatorBackgroundColor = indicatorBackgroundColor, + iconColor = iconColor, + selectedIconColor = selectedIconColor, + labelColor = labelColor, + selectedLabelColor = selectedLabelColor, ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt index eed54dab6faf..f377fa6276a0 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt @@ -17,6 +17,7 @@ package com.android.systemui.volume.panel.component.spatialaudio.ui.composable import androidx.compose.foundation.basicMarquee +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -26,14 +27,15 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import com.android.internal.logging.UiEventLogger import com.android.systemui.animation.Expandable import com.android.systemui.common.ui.compose.Icon -import com.android.systemui.common.ui.compose.toColor import com.android.systemui.res.R import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.volume.panel.component.popup.ui.composable.VolumePanelPopup import com.android.systemui.volume.panel.component.selector.ui.composable.VolumePanelRadioButtonBar import com.android.systemui.volume.panel.component.spatial.ui.viewmodel.SpatialAudioViewModel +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import javax.inject.Inject class SpatialAudioPopup @@ -41,10 +43,17 @@ class SpatialAudioPopup constructor( private val viewModel: SpatialAudioViewModel, private val volumePanelPopup: VolumePanelPopup, + private val uiEventLogger: UiEventLogger, ) { /** Shows a popup with the [expandable] animation. */ fun show(expandable: Expandable) { + uiEventLogger.logWithPosition( + VolumePanelUiEvent.VOLUME_PANEL_SPATIAL_AUDIO_POP_UP_SHOWN, + 0, + null, + viewModel.spatialAudioButtons.value.indexOfFirst { it.button.isChecked } + ) volumePanelPopup.show(expandable, { Title() }, { Content(it) }) } @@ -79,18 +88,13 @@ constructor( isSelected = buttonViewModel.button.isChecked, onItemSelected = { viewModel.setEnabled(buttonViewModel.model) }, contentDescription = label, - icon = { - Icon( - icon = buttonViewModel.button.icon, - tint = buttonViewModel.iconColor.toColor(), - ) - }, + icon = { Icon(icon = buttonViewModel.button.icon) }, label = { Text( modifier = Modifier.basicMarquee(), text = label, style = MaterialTheme.typography.labelMedium, - color = buttonViewModel.labelColor.toColor(), + color = LocalContentColor.current, textAlign = TextAlign.Center, maxLines = 2 ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt index f89669c8456c..a3467f2ab78e 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt @@ -85,6 +85,7 @@ fun ColumnVolumeSliders( onValueChange = { newValue: Float -> sliderViewModel.onValueChanged(sliderState, newValue) }, + onValueChangeFinished = { sliderViewModel.onValueChangeFinished() }, onIconTapped = { sliderViewModel.toggleMuted(sliderState) }, sliderColors = sliderColors, ) @@ -106,7 +107,7 @@ fun ColumnVolumeSliders( } } transition.AnimatedVisibility( - visible = { it }, + visible = { it || !isExpandable }, enter = expandVertically(animationSpec = tween(durationMillis = EXPAND_DURATION_MILLIS)), exit = @@ -121,7 +122,7 @@ fun ColumnVolumeSliders( val sliderState by sliderViewModel.slider.collectAsState() transition.AnimatedVisibility( modifier = Modifier.padding(top = 16.dp), - visible = { it }, + visible = { it || !isExpandable }, enter = enterTransition(index = index, totalCount = viewModels.size), exit = exitTransition(index = index, totalCount = viewModels.size) ) { @@ -131,6 +132,7 @@ fun ColumnVolumeSliders( onValueChange = { newValue: Float -> sliderViewModel.onValueChanged(sliderState, newValue) }, + onValueChangeFinished = { sliderViewModel.onValueChangeFinished() }, onIconTapped = { sliderViewModel.toggleMuted(sliderState) }, sliderColors = sliderColors, ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt index b284c691ef0e..bb17499f021f 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt @@ -46,6 +46,7 @@ fun GridVolumeSliders( onValueChange = { newValue: Float -> sliderViewModel.onValueChanged(sliderState, newValue) }, + onValueChangeFinished = { sliderViewModel.onValueChangeFinished() }, onIconTapped = { sliderViewModel.toggleMuted(sliderState) }, sliderColors = sliderColors, ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt index 19d3f599ef31..9f5ab3c0e284 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt @@ -16,13 +16,15 @@ package com.android.systemui.volume.panel.component.volume.ui.composable +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.getValue @@ -49,6 +51,7 @@ import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.Sl fun VolumeSlider( state: SliderState, onValueChange: (newValue: Float) -> Unit, + onValueChangeFinished: (() -> Unit)? = null, onIconTapped: () -> Unit, modifier: Modifier = Modifier, sliderColors: PlatformSliderColors, @@ -58,7 +61,8 @@ fun VolumeSlider( modifier = modifier.clearAndSetSemantics { if (!state.isEnabled) disabled() - contentDescription = state.label + contentDescription = + state.disabledMessage?.let { "${state.label}, $it" } ?: state.label // provide a not animated value to the a11y because it fails to announce the // settled value when it changes rapidly. @@ -83,28 +87,31 @@ fun VolumeSlider( value = value, valueRange = state.valueRange, onValueChange = onValueChange, + onValueChangeFinished = onValueChangeFinished, enabled = state.isEnabled, - icon = { isDragging -> - if (isDragging) { - Text(text = state.valueText, color = LocalContentColor.current) - } else { - state.icon?.let { - SliderIcon( - icon = it, - onIconTapped = onIconTapped, - isTappable = state.isMutable, - ) - } + icon = { + state.icon?.let { + SliderIcon( + icon = it, + onIconTapped = onIconTapped, + isTappable = state.isMutable, + ) } }, colors = sliderColors, - label = { - VolumeSliderContent( - modifier = Modifier, - label = state.label, - isEnabled = state.isEnabled, - disabledMessage = state.disabledMessage, - ) + label = { isDragging -> + AnimatedVisibility( + visible = !isDragging, + enter = fadeIn(tween(150)), + exit = fadeOut(tween(150)), + ) { + VolumeSliderContent( + modifier = Modifier, + label = state.label, + isEnabled = state.isEnabled, + disabledMessage = state.disabledMessage, + ) + } } ) } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt index b1cfdcf07977..dbec059715b4 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt @@ -204,15 +204,16 @@ internal class SceneTransitionLayoutImpl( } // Handle back events. - // TODO(b/290184746): Make sure that this works with SystemUI once we use - // SceneTransitionLayout in Flexiglass. - scene(state.transitionState.currentScene).userActions[Back]?.let { result -> - // TODO(b/290184746): Handle predictive back and use result.distance if - // specified. - BackHandler { - val targetScene = result.toScene - if (state.canChangeScene(targetScene)) { - with(state) { coroutineScope.onChangeScene(targetScene) } + val targetSceneForBackOrNull = + scene(state.transitionState.currentScene).userActions[Back]?.toScene + BackHandler( + enabled = targetSceneForBackOrNull != null, + ) { + targetSceneForBackOrNull?.let { targetSceneForBack -> + // TODO(b/290184746): Handle predictive back and use result.distance if + // specified. + if (state.canChangeScene(targetSceneForBack)) { + with(state) { coroutineScope.onChangeScene(targetSceneForBack) } } } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt index 1120914fec7c..ae9794a3dbda 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt @@ -50,6 +50,7 @@ import com.android.systemui.classifier.FalsingCollector import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository @@ -65,7 +66,6 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.FakeSceneDataSource import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource @@ -86,7 +86,6 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.GlobalSettings import com.google.common.truth.Truth -import dagger.Lazy import java.util.Optional import junit.framework.Assert import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -170,7 +169,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { private lateinit var sceneInteractor: SceneInteractor private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor private lateinit var deviceEntryInteractor: DeviceEntryInteractor - @Mock private lateinit var primaryBouncerInteractor: Lazy<PrimaryBouncerInteractor> + @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor private lateinit var sceneTransitionStateFlow: MutableStateFlow<ObservableTransitionState> private lateinit var fakeSceneDataSource: FakeSceneDataSource @@ -209,7 +208,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { val keyguardKeyboardInteractor = KeyguardKeyboardInteractor(FakeKeyboardRepository()) featureFlags = FakeFeatureFlags() - featureFlags.set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) featureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false) mSetFlagsRule.enableFlags( @@ -217,8 +215,13 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { ) mSetFlagsRule.disableFlags( FLAG_SIDEFPS_CONTROLLER_REFACTOR, - AConfigFlags.FLAG_KEYGUARD_WM_STATE_REFACTOR ) + if (!com.android.systemui.Flags.sceneContainer()) { + mSetFlagsRule.disableFlags( + AConfigFlags.FLAG_KEYGUARD_WM_STATE_REFACTOR, + AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT, + ) + } keyguardPasswordViewController = KeyguardPasswordViewController( @@ -267,7 +270,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { falsingManager, userSwitcherController, featureFlags, - kosmos.fakeSceneContainerFlags, globalSettings, sessionTracker, Optional.of(sideFpsController), @@ -282,7 +284,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { deviceProvisionedController, faceAuthAccessibilityDelegate, keyguardTransitionInteractor, - primaryBouncerInteractor, + { primaryBouncerInteractor }, ) { deviceEntryInteractor } @@ -803,17 +805,17 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { } @Test + @EnableSceneContainer fun dismissesKeyguard_whenSceneChangesToGone() = kosmos.testScope.runTest { - kosmos.fakeSceneContainerFlags.enabled = true // Upon init, we have never dismisses the keyguard. underTest.onInit() runCurrent() - verify(viewMediatorCallback, never()).keyguardDone(anyInt()) + verify(primaryBouncerInteractor, never()) + .notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) // Once the view is attached, we start listening but simply going to the bouncer scene - // is - // not enough to trigger a dismissal of the keyguard. + // is not enough to trigger a dismissal of the keyguard. underTest.onViewAttached() fakeSceneDataSource.pause() sceneInteractor.changeScene(Scenes.Bouncer, "reason") @@ -829,7 +831,8 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { fakeSceneDataSource.unpause(expectedScene = Scenes.Bouncer) sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Bouncer) runCurrent() - verify(viewMediatorCallback, never()).keyguardDone(anyInt()) + verify(primaryBouncerInteractor, never()) + .notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) // While listening, going from the bouncer scene to the gone scene, does dismiss the // keyguard. @@ -851,11 +854,11 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { fakeSceneDataSource.unpause(expectedScene = Scenes.Gone) sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone) runCurrent() - verify(viewMediatorCallback).keyguardDone(anyInt()) + verify(primaryBouncerInteractor).notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) // While listening, moving back to the bouncer scene does not dismiss the keyguard // again. - clearInvocations(viewMediatorCallback) + clearInvocations(primaryBouncerInteractor) fakeSceneDataSource.pause() sceneInteractor.changeScene(Scenes.Bouncer, "reason") sceneTransitionStateFlow.value = @@ -870,7 +873,8 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { fakeSceneDataSource.unpause(expectedScene = Scenes.Bouncer) sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Bouncer) runCurrent() - verify(viewMediatorCallback, never()).keyguardDone(anyInt()) + verify(primaryBouncerInteractor, never()) + .notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) // Detaching the view stops listening, so moving from the bouncer scene to the gone // scene @@ -890,7 +894,8 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { fakeSceneDataSource.unpause(expectedScene = Scenes.Gone) sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone) runCurrent() - verify(viewMediatorCallback, never()).keyguardDone(anyInt()) + verify(primaryBouncerInteractor, never()) + .notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) // While not listening, moving to the lockscreen does not dismiss the keyguard. fakeSceneDataSource.pause() @@ -907,7 +912,8 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { fakeSceneDataSource.unpause(expectedScene = Scenes.Lockscreen) sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Lockscreen) runCurrent() - verify(viewMediatorCallback, never()).keyguardDone(anyInt()) + verify(primaryBouncerInteractor, never()) + .notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) // Reattaching the view starts listening again so moving from the bouncer scene to the // gone scene now does dismiss the keyguard again, this time from lockscreen. @@ -926,7 +932,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { fakeSceneDataSource.unpause(expectedScene = Scenes.Gone) sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone) runCurrent() - verify(viewMediatorCallback).keyguardDone(anyInt()) + verify(primaryBouncerInteractor).notifyKeyguardAuthenticatedPrimaryAuth(anyInt()) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java index 0f8fc3824e3f..04c4efbf7c78 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; import static com.google.common.truth.Truth.assertThat; @@ -31,6 +31,8 @@ import android.animation.ValueAnimator; import android.content.pm.UserInfo; import android.graphics.Rect; import android.graphics.Region; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; @@ -41,10 +43,11 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; import com.android.internal.widget.LockPatternUtils; +import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; +import com.android.systemui.ambient.touch.scrim.ScrimController; +import com.android.systemui.ambient.touch.scrim.ScrimManager; import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants; -import com.android.systemui.dreams.touch.scrim.ScrimController; -import com.android.systemui.dreams.touch.scrim.ScrimManager; import com.android.systemui.settings.FakeUserTracker; import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.shared.system.InputChannelCompat; @@ -85,7 +88,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { FlingAnimationUtils mFlingAnimationUtilsClosing; @Mock - DreamTouchHandler.TouchSession mTouchSession; + TouchHandler.TouchSession mTouchSession; BouncerSwipeTouchHandler mTouchHandler; @@ -255,7 +258,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { } private static void onSessionStartHelper(BouncerSwipeTouchHandler touchHandler, - DreamTouchHandler.TouchSession touchSession, + TouchHandler.TouchSession touchSession, NotificationShadeWindowController notificationShadeWindowController) { touchHandler.onSessionStart(touchSession); verify(notificationShadeWindowController).setForcePluginOpen(eq(true), any()); @@ -277,6 +280,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { /** * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount. */ + @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING) @Test public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion() { when(mCentralSurfaces.isBouncerShowing()).thenReturn(true); @@ -297,8 +301,36 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); - assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)) - .isTrue(); + assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)).isTrue(); + + verify(mScrimController, never()).expand(any()); + } + + /** + * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount. + */ + @Test + @EnableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING) + public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion_directionFiltering() { + when(mCentralSurfaces.isBouncerShowing()).thenReturn(true); + + mTouchHandler.onSessionStart(mTouchSession); + ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = + ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class); + verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture()); + + final OnGestureListener gestureListener = gestureListenerCaptor.getValue(); + + final float percent = .3f; + final float distanceY = SCREEN_HEIGHT_PX * percent; + + // Swiping up near the top of the screen where the touch initiation region is. + final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, + 0, distanceY, 0); + final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, + 0, 0, 0); + + assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)).isFalse(); verify(mScrimController, never()).expand(any()); } @@ -307,6 +339,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount. */ @Test + @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING) public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion() { mTouchHandler.onSessionStart(mTouchSession); ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = @@ -324,8 +357,34 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, SCREEN_HEIGHT_PX, 0); - assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)) - .isTrue(); + assertThat(gestureListener.onScroll(event1, event2, 0, -distanceY)).isTrue(); + + verify(mScrimController, never()).expand(any()); + } + + /** + * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount. + */ + @Test + @EnableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING) + public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion_directionFiltering() { + mTouchHandler.onSessionStart(mTouchSession); + ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = + ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class); + verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture()); + + final OnGestureListener gestureListener = gestureListenerCaptor.getValue(); + + final float percent = .15f; + final float distanceY = SCREEN_HEIGHT_PX * percent; + + // Swiping down near the bottom of the screen where the touch initiation region is. + final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, + 0, SCREEN_HEIGHT_PX - distanceY, 0); + final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, + 0, SCREEN_HEIGHT_PX, 0); + + assertThat(gestureListener.onScroll(event1, event2, 0, -distanceY)).isFalse(); verify(mScrimController, never()).expand(any()); } @@ -444,7 +503,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { 0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0); reset(mScrimController); - assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)) + assertThat(gestureListener.onScroll(event1, event2, 0, + direction == Direction.UP ? distanceY : -distanceY)) .isTrue(); // Ensure only called once @@ -617,8 +677,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { @Test public void testTouchSessionOnRemovedCalledTwice() { mTouchHandler.onSessionStart(mTouchSession); - ArgumentCaptor<DreamTouchHandler.TouchSession.Callback> onRemovedCallbackCaptor = - ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.Callback.class); + ArgumentCaptor<TouchHandler.TouchSession.Callback> onRemovedCallbackCaptor = + ArgumentCaptor.forClass(TouchHandler.TouchSession.Callback.class); verify(mTouchSession).registerCallback(onRemovedCallbackCaptor.capture()); onRemovedCallbackCaptor.getValue().onRemoved(); onRemovedCallbackCaptor.getValue().onRemoved(); @@ -643,7 +703,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0); - assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0, distanceY)) + assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0, + direction == Direction.UP ? distanceY : -distanceY)) .isTrue(); final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java index 6aa821f15ab1..27bffd0818e7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; import static com.google.common.truth.Truth.assertThat; @@ -52,7 +52,7 @@ public class ShadeTouchHandlerTest extends SysuiTestCase { ShadeViewController mShadeViewController; @Mock - DreamTouchHandler.TouchSession mTouchSession; + TouchHandler.TouchSession mTouchSession; ShadeTouchHandler mTouchHandler; diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimControllerTest.java index 7cdd4781631f..099771c32b64 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim; +package com.android.systemui.ambient.touch.scrim; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/ScrimManagerTest.java index ebbcf981b762..82de50c54dc2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/ScrimManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim; +package com.android.systemui.ambient.touch.scrim; import static com.google.common.truth.Truth.assertThat; diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt index caf92199737c..1cd9d76a189e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt @@ -32,7 +32,6 @@ import com.android.systemui.coroutines.collectValues import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.log.table.TableLogBuffer -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.testKosmos @@ -86,7 +85,6 @@ class AuthenticationRepositoryTest : SysuiTestCase() { AuthenticationRepositoryImpl( applicationScope = testScope.backgroundScope, backgroundDispatcher = kosmos.testDispatcher, - flags = kosmos.sceneContainerFlags, clock = clock, getSecurityMode = getSecurityMode, userRepository = userRepository, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index 4950b96b077f..60b48f28fc23 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt @@ -537,4 +537,65 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { assertThat(lp.height).isEqualTo(overlayParams.sensorBounds.height()) } } + + @Test + fun addViewPending_layoutIsNotUpdated() = + testScope.runTest { + withReasonSuspend(REASON_AUTH_KEYGUARD) { + mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE) + mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) + + // GIVEN going to sleep + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.OFF, + to = KeyguardState.GONE, + testScope = this, + ) + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + runCurrent() + + // WHEN a request comes to show the view + controllerOverlay.show(udfpsController, overlayParams) + runCurrent() + + // THEN the view does not get added immediately + verify(windowManager, never()).addView(any(), any()) + + // WHEN updateOverlayParams gets called when the view is pending to be added + controllerOverlay.updateOverlayParams(overlayParams) + + // THEN the view layout is never updated + verify(windowManager, never()).updateViewLayout(any(), any()) + + // CLEANUP we hide to end the job that listens for the finishedGoingToSleep signal + controllerOverlay.hide() + } + } + + @Test + fun updateOverlayParams_viewLayoutUpdated() = + testScope.runTest { + withReasonSuspend(REASON_AUTH_KEYGUARD) { + mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE) + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + runCurrent() + controllerOverlay.show(udfpsController, overlayParams) + runCurrent() + verify(windowManager).addView(any(), any()) + + // WHEN updateOverlayParams gets called + controllerOverlay.updateOverlayParams(overlayParams) + + // THEN the view layout is updated + verify(windowManager).updateViewLayout(any(), any()) + } + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt index 741cde82354a..d850f17cd89a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt @@ -29,10 +29,10 @@ import com.android.systemui.authentication.data.repository.fakeAuthenticationRep import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testScope -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository import com.android.systemui.telephony.data.repository.fakeTelephonyRepository @@ -56,6 +56,7 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class BouncerActionButtonInteractorTest : SysuiTestCase() { @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor @@ -75,7 +76,6 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - kosmos.fakeSceneContainerFlags.enabled = true mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt index b0d03b15d310..361b078ebd30 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.bouncer.domain.interactor import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.internal.logging.uiEventLoggerFake import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository @@ -25,14 +26,15 @@ import com.android.systemui.authentication.domain.interactor.AuthenticationResul import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate +import com.android.systemui.bouncer.shared.logging.BouncerUiEvent import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository import com.android.systemui.kosmos.testScope import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.res.R -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds @@ -48,11 +50,13 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class BouncerInteractorTest : SysuiTestCase() { - private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true } + private val kosmos = testKosmos() private val testScope = kosmos.testScope private val authenticationInteractor = kosmos.authenticationInteractor + private val uiEventLoggerFake = kosmos.uiEventLoggerFake private lateinit var underTest: BouncerInteractor @@ -83,6 +87,7 @@ class BouncerInteractorTest : SysuiTestCase() { // Thus, when auth method is sim, we expect to skip here. assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SKIPPED) + assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test @@ -104,6 +109,8 @@ class BouncerInteractorTest : SysuiTestCase() { // Wrong 6-digit pin assertThat(underTest.authenticate(listOf(1, 2, 3, 5, 5, 6), tryAutoConfirm = true)) .isEqualTo(AuthenticationResult.FAILED) + assertThat(uiEventLoggerFake[0].eventId) + .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_FAILURE.id) // Correct input. assertThat( @@ -113,6 +120,9 @@ class BouncerInteractorTest : SysuiTestCase() { ) ) .isEqualTo(AuthenticationResult.SUCCEEDED) + assertThat(uiEventLoggerFake[1].eventId) + .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS.id) + assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2) } @Test @@ -148,6 +158,8 @@ class BouncerInteractorTest : SysuiTestCase() { // Wrong input. assertThat(underTest.authenticate("alohamora".toList())) .isEqualTo(AuthenticationResult.FAILED) + assertThat(uiEventLoggerFake[0].eventId) + .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_FAILURE.id) // Too short input. assertThat( @@ -165,6 +177,9 @@ class BouncerInteractorTest : SysuiTestCase() { // Correct input. assertThat(underTest.authenticate("password".toList())) .isEqualTo(AuthenticationResult.SUCCEEDED) + assertThat(uiEventLoggerFake[1].eventId) + .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS.id) + assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2) } @Test @@ -187,6 +202,8 @@ class BouncerInteractorTest : SysuiTestCase() { assertThat(wrongPattern.size) .isAtLeast(kosmos.fakeAuthenticationRepository.minPatternLength) assertThat(underTest.authenticate(wrongPattern)).isEqualTo(AuthenticationResult.FAILED) + assertThat(uiEventLoggerFake[0].eventId) + .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_FAILURE.id) // Too short input. val tooShortPattern = @@ -200,6 +217,9 @@ class BouncerInteractorTest : SysuiTestCase() { // Correct input. assertThat(underTest.authenticate(FakeAuthenticationRepository.PATTERN)) .isEqualTo(AuthenticationResult.SUCCEEDED) + assertThat(uiEventLoggerFake[1].eventId) + .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS.id) + assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt index 3afca96e07a0..b83c0ce702a7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt @@ -18,6 +18,10 @@ package com.android.systemui.bouncer.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.SwipeDirection +import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository @@ -30,11 +34,14 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Sim import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testScope -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos +import com.android.systemui.truth.containsEntriesExactly import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -53,6 +60,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class BouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() @@ -63,7 +71,6 @@ class BouncerViewModelTest : SysuiTestCase() { @Before fun setUp() { - kosmos.fakeSceneContainerFlags.enabled = true underTest = kosmos.bouncerViewModel } @@ -193,6 +200,23 @@ class BouncerViewModelTest : SysuiTestCase() { assertThat(isFoldSplitRequired).isTrue() } + @Test + fun destinationScenes() = + testScope.runTest { + val destinationScenes by collectLastValue(underTest.destinationScenes) + kosmos.fakeSceneDataSource.changeScene(Scenes.QuickSettings) + runCurrent() + + kosmos.fakeSceneDataSource.changeScene(Scenes.Bouncer) + runCurrent() + + assertThat(destinationScenes) + .containsEntriesExactly( + Back to UserActionResult(Scenes.QuickSettings), + Swipe(SwipeDirection.Down) to UserActionResult(Scenes.QuickSettings), + ) + } + private fun authMethodsToTest(): List<AuthenticationMethodModel> { return listOf(None, Pin, Password, Pattern, Sim) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index 5bb36a0acbdf..256687b56f4e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt @@ -389,6 +389,61 @@ class PinBouncerViewModelTest : SysuiTestCase() { assertThat(isAnimationEnabled).isTrue() } + @Test + fun onPinButtonClicked_whenInputSameLengthAsHintedPin_ignoresClick() = + testScope.runTest { + val pin by collectLastValue(underTest.pinInput.map { it.getPin() }) + kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true) + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + assertThat(hintedPinLength).isEqualTo(FakeAuthenticationRepository.HINTING_PIN_LENGTH) + lockDeviceAndOpenPinBouncer() + + repeat(FakeAuthenticationRepository.HINTING_PIN_LENGTH - 1) { repetition -> + underTest.onPinButtonClicked(repetition + 1) + runCurrent() + } + kosmos.fakeAuthenticationRepository.pauseCredentialChecking() + // If credential checking were not paused, this would check the credentials and succeed. + underTest.onPinButtonClicked(FakeAuthenticationRepository.HINTING_PIN_LENGTH) + runCurrent() + + // This one should be ignored because the user has already entered a number of digits + // that's equal to the length of the hinting PIN length. It should result in a PIN + // that's exactly the same length as the hinting PIN length. + underTest.onPinButtonClicked(FakeAuthenticationRepository.HINTING_PIN_LENGTH + 1) + runCurrent() + + assertThat(pin) + .isEqualTo( + buildList { + repeat(FakeAuthenticationRepository.HINTING_PIN_LENGTH) { index -> + add(index + 1) + } + } + ) + + kosmos.fakeAuthenticationRepository.unpauseCredentialChecking() + runCurrent() + assertThat(pin).isEmpty() + } + + @Test + fun onPinButtonClicked_whenPinNotHinted_doesNotIgnoreClick() = + testScope.runTest { + val pin by collectLastValue(underTest.pinInput.map { it.getPin() }) + kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(false) + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + assertThat(hintedPinLength).isNull() + lockDeviceAndOpenPinBouncer() + + repeat(FakeAuthenticationRepository.HINTING_PIN_LENGTH + 1) { repetition -> + underTest.onPinButtonClicked(repetition + 1) + runCurrent() + } + + assertThat(pin).hasSize(FakeAuthenticationRepository.HINTING_PIN_LENGTH + 1) + } + private fun TestScope.switchToScene(toScene: SceneKey) { val currentScene by collectLastValue(sceneInteractor.currentScene) val bouncerHidden = currentScene == Scenes.Bouncer && toScene != Scenes.Bouncer diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt index a944afb70f38..76f15d2ed257 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt @@ -120,19 +120,20 @@ class CommunalSceneStartableTest : SysuiTestCase() { } @Test - fun exitingDream_forceCommunalScene() = + fun occluded_forceBlankScene() = with(kosmos) { testScope.runTest { val scene by collectLastValue(communalInteractor.desiredScene) - assertThat(scene).isEqualTo(CommunalScenes.Blank) + communalInteractor.changeScene(CommunalScenes.Communal) + assertThat(scene).isEqualTo(CommunalScenes.Communal) updateDocked(true) fakeKeyguardTransitionRepository.sendTransitionSteps( - from = KeyguardState.DREAMING, - to = KeyguardState.LOCKSCREEN, + from = KeyguardState.GLANCEABLE_HUB, + to = KeyguardState.OCCLUDED, testScope = this ) - assertThat(scene).isEqualTo(CommunalScenes.Communal) + assertThat(scene).isEqualTo(CommunalScenes.Blank) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt index f71121c43ff8..ce7b60e86f8f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt @@ -23,6 +23,7 @@ import android.app.admin.devicePolicyManager import android.appwidget.AppWidgetProviderInfo import android.content.Intent import android.content.pm.UserInfo +import android.os.UserManager.USER_TYPE_PROFILE_MANAGED import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.provider.Settings @@ -59,6 +60,7 @@ class CommunalSettingsRepositoryImplTest : SysuiTestCase() { kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true) setKeyguardFeaturesDisabled(PRIMARY_USER, KEYGUARD_DISABLE_FEATURES_NONE) setKeyguardFeaturesDisabled(SECONDARY_USER, KEYGUARD_DISABLE_FEATURES_NONE) + setKeyguardFeaturesDisabled(WORK_PROFILE, KEYGUARD_DISABLE_FEATURES_NONE) underTest = kosmos.communalSettingsRepository } @@ -133,6 +135,30 @@ class CommunalSettingsRepositoryImplTest : SysuiTestCase() { @EnableFlags(FLAG_COMMUNAL_HUB) @Test + fun widgetsAllowedForWorkProfile_isFalse_whenDisallowedByDevicePolicy() = + testScope.runTest { + val widgetsAllowedForWorkProfile by + collectLastValue(underTest.getAllowedByDevicePolicy(WORK_PROFILE)) + assertThat(widgetsAllowedForWorkProfile).isTrue() + + setKeyguardFeaturesDisabled(WORK_PROFILE, KEYGUARD_DISABLE_WIDGETS_ALL) + assertThat(widgetsAllowedForWorkProfile).isFalse() + } + + @EnableFlags(FLAG_COMMUNAL_HUB) + @Test + fun hubIsEnabled_whenDisallowedByDevicePolicyForWorkProfile() = + testScope.runTest { + val enabledStateForPrimaryUser by + collectLastValue(underTest.getEnabledState(PRIMARY_USER)) + assertThat(enabledStateForPrimaryUser?.enabled).isTrue() + + setKeyguardFeaturesDisabled(WORK_PROFILE, KEYGUARD_DISABLE_WIDGETS_ALL) + assertThat(enabledStateForPrimaryUser?.enabled).isTrue() + } + + @EnableFlags(FLAG_COMMUNAL_HUB) + @Test fun hubIsDisabledByUserAndDevicePolicy() = testScope.runTest { val enabledState by collectLastValue(underTest.getEnabledState(PRIMARY_USER)) @@ -189,5 +215,13 @@ class CommunalSettingsRepositoryImplTest : SysuiTestCase() { val PRIMARY_USER = UserInfo(/* id= */ 0, /* name= */ "primary user", /* flags= */ UserInfo.FLAG_MAIN) val SECONDARY_USER = UserInfo(/* id= */ 1, /* name= */ "secondary user", /* flags= */ 0) + val WORK_PROFILE = + UserInfo( + 10, + "work", + /* iconPath= */ "", + /* flags= */ 0, + USER_TYPE_PROFILE_MANAGED, + ) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index e7ccde26e161..497180b60151 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -17,6 +17,8 @@ package com.android.systemui.communal.domain.interactor +import android.app.admin.DevicePolicyManager +import android.app.admin.devicePolicyManager import android.app.smartspace.SmartspaceTarget import android.appwidget.AppWidgetProviderInfo import android.content.Intent @@ -32,6 +34,7 @@ import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.broadcastDispatcher import com.android.systemui.communal.data.repository.CommunalSettingsRepositoryImpl import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository import com.android.systemui.communal.data.repository.FakeCommunalPrefsRepository @@ -49,6 +52,7 @@ import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.widgets.EditWidgetsActivityStarter import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository @@ -58,7 +62,6 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.activityStarter import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.FakeUserTracker import com.android.systemui.settings.fakeUserTracker @@ -71,6 +74,7 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat @@ -694,10 +698,9 @@ class CommunalInteractorTest : SysuiTestCase() { } @Test + @EnableSceneContainer fun isCommunalShowing_whenSceneContainerEnabled() = testScope.runTest { - kosmos.fakeSceneContainerFlags.enabled = true - // Verify default is false val isCommunalShowing by collectLastValue(underTest.isCommunalShowing) runCurrent() @@ -929,7 +932,6 @@ class CommunalInteractorTest : SysuiTestCase() { keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardOccluded(false) tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - userRepository.setSelectedUserInfo(mainUser) val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) userRepository.setUserInfos(userInfos) @@ -937,6 +939,7 @@ class CommunalInteractorTest : SysuiTestCase() { userInfos = userInfos, selectedUserIndex = 0, ) + userRepository.setSelectedUserInfo(MAIN_USER_INFO) runCurrent() // Widgets available. @@ -955,7 +958,6 @@ class CommunalInteractorTest : SysuiTestCase() { AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD, mainUser.id ) - runCurrent() // Only the keyguard widget is enabled. assertThat(widgetContent).hasSize(3) @@ -974,7 +976,6 @@ class CommunalInteractorTest : SysuiTestCase() { keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardOccluded(false) tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - userRepository.setSelectedUserInfo(mainUser) val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) userRepository.setUserInfos(userInfos) @@ -982,6 +983,7 @@ class CommunalInteractorTest : SysuiTestCase() { userInfos = userInfos, selectedUserIndex = 0, ) + userRepository.setSelectedUserInfo(MAIN_USER_INFO) runCurrent() // Widgets available. @@ -1001,7 +1003,6 @@ class CommunalInteractorTest : SysuiTestCase() { AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN, mainUser.id ) - runCurrent() // All widgets are enabled. assertThat(widgetContent).hasSize(3) @@ -1011,6 +1012,79 @@ class CommunalInteractorTest : SysuiTestCase() { } } + @Test + fun filterWidgets_whenDisallowedByDevicePolicyForWorkProfile() = + testScope.runTest { + // Keyguard showing, and tutorial completed. + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) + + val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) + userRepository.setUserInfos(userInfos) + userTracker.set( + userInfos = userInfos, + selectedUserIndex = 0, + ) + userRepository.setSelectedUserInfo(MAIN_USER_INFO) + runCurrent() + + val widgetContent by collectLastValue(underTest.widgetContent) + // Given three widgets, and one of them is associated with work profile. + val widget1 = createWidgetForUser(1, USER_INFO_WORK.id) + val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id) + val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id) + val widgets = listOf(widget1, widget2, widget3) + widgetRepository.setCommunalWidgets(widgets) + + setKeyguardFeaturesDisabled( + USER_INFO_WORK, + DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL + ) + + // Widget under work profile is filtered out and the remaining two link to main user id. + assertThat(widgetContent).hasSize(2) + widgetContent!!.forEach { model -> + assertThat(model.providerInfo.profile?.identifier).isEqualTo(MAIN_USER_INFO.id) + } + } + + @Test + fun filterWidgets_whenAllowedByDevicePolicyForWorkProfile() = + testScope.runTest { + // Keyguard showing, and tutorial completed. + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) + + val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) + userRepository.setUserInfos(userInfos) + userTracker.set( + userInfos = userInfos, + selectedUserIndex = 0, + ) + userRepository.setSelectedUserInfo(MAIN_USER_INFO) + runCurrent() + + val widgetContent by collectLastValue(underTest.widgetContent) + // Given three widgets, and one of them is associated with work profile. + val widget1 = createWidgetForUser(1, USER_INFO_WORK.id) + val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id) + val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id) + val widgets = listOf(widget1, widget2, widget3) + widgetRepository.setCommunalWidgets(widgets) + + setKeyguardFeaturesDisabled( + USER_INFO_WORK, + DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE + ) + + // Widget under work profile is available. + assertThat(widgetContent).hasSize(3) + assertThat(widgetContent!![0].providerInfo.profile?.identifier) + .isEqualTo(USER_INFO_WORK.id) + } + private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget { val timer = mock(SmartspaceTarget::class.java) whenever(timer.smartspaceTargetId).thenReturn(id) @@ -1020,6 +1094,15 @@ class CommunalInteractorTest : SysuiTestCase() { return timer } + private fun setKeyguardFeaturesDisabled(user: UserInfo, disabledFlags: Int) { + whenever(kosmos.devicePolicyManager.getKeyguardDisabledFeatures(nullable(), eq(user.id))) + .thenReturn(disabledFlags) + kosmos.broadcastDispatcher.sendIntentToMatchingReceiversOnly( + context, + Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), + ) + } + private fun createWidgetForUser(appWidgetId: Int, userId: Int): CommunalWidgetContentModel = mock<CommunalWidgetContentModel> { whenever(this.appWidgetId).thenReturn(appWidgetId) @@ -1044,6 +1127,13 @@ class CommunalInteractorTest : SysuiTestCase() { private companion object { val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) - val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE) + val USER_INFO_WORK = + UserInfo( + 10, + "work", + /* iconPath= */ "", + /* flags= */ 0, + UserManager.USER_TYPE_PROFILE_MANAGED, + ) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt index 9a13bb261aa7..6b2a1d59e62d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt @@ -32,7 +32,6 @@ import android.hardware.face.FaceManager import android.hardware.face.FaceSensorProperties import android.hardware.face.FaceSensorPropertiesInternal import android.os.CancellationSignal -import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId.fakeInstanceId @@ -54,7 +53,6 @@ import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus -import com.android.systemui.display.data.repository.display import com.android.systemui.display.data.repository.displayRepository import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FakeFeatureFlags @@ -68,6 +66,7 @@ import com.android.systemui.keyguard.data.repository.fakeTrustRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testDispatcher @@ -697,9 +696,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { ) runCurrent() - displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_OFF))) - displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY) - + displayRepository.setDefaultDisplayOff(true) runCurrent() assertThat(canFaceAuthRun()).isTrue() @@ -717,10 +714,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { ) runCurrent() - displayRepository.emit( - setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_OFF)) - ) - displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY) + displayRepository.setDefaultDisplayOff(true) } } @@ -827,13 +821,14 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { } @Test - fun isAuthenticatedIsResetToFalseWhenTransitioningToGone() = + fun isAuthenticatedIsResetToFalseWhenFinishedTransitioningToGoneAndStatusBarStateShade() = testScope.runTest { initCollectors() allPreconditionsToRunFaceAuthAreTrue() triggerFaceAuth(false) + keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) authenticationCallback.value.onAuthenticationSucceeded( mock(FaceManager.AuthenticationResult::class.java) ) @@ -847,7 +842,16 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { to = KeyguardState.GONE, ) ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.FINISHED, + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + ) + ) + assertThat(authenticated()).isTrue() + keyguardRepository.setStatusBarState(StatusBarState.SHADE) assertThat(authenticated()).isFalse() } @@ -1167,8 +1171,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { faceLockoutResetCallback.value.onLockoutReset(0) bouncerRepository.setAlternateVisible(true) keyguardRepository.setKeyguardShowing(true) - displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_ON))) - displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY) + displayRepository.setDefaultDisplayOff(false) keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt index 5caf35ba90d4..37a6ac6adac7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt @@ -38,6 +38,7 @@ import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReaso import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason.TrustAgentDisabled import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason.UnattendedUpdate import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason.UserLockdown +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.fakeSystemPropertiesHelper import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository @@ -47,7 +48,6 @@ import com.android.systemui.keyguard.shared.model.AuthenticationFlags import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat @@ -62,6 +62,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class DeviceEntryInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() @@ -74,7 +75,6 @@ class DeviceEntryInteractorTest : SysuiTestCase() { @Before fun setUp() { - kosmos.fakeSceneContainerFlags.enabled = true underTest = kosmos.deviceEntryInteractor } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java index 2af6566e993a..41bc1dc271f1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java @@ -39,10 +39,10 @@ import androidx.test.filters.SmallTest; import com.android.dream.lowlight.LowLightTransitionCoordinator; import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.SysuiTestCase; +import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController; import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor; import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback; import com.android.systemui.complication.ComplicationHostViewController; -import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController; import com.android.systemui.statusbar.BlurUtils; import org.junit.Before; diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java index c14346899ede..4e18a47b45f6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java @@ -50,11 +50,12 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; +import com.android.systemui.ambient.touch.TouchMonitor; +import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent; import com.android.systemui.complication.ComplicationLayoutEngine; import com.android.systemui.dreams.complication.HideComplicationTouchHandler; import com.android.systemui.dreams.complication.dagger.ComplicationComponent; import com.android.systemui.dreams.dagger.DreamOverlayComponent; -import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -127,6 +128,12 @@ public class DreamOverlayServiceTest extends SysuiTestCase { DreamOverlayComponent mDreamOverlayComponent; @Mock + AmbientTouchComponent.Factory mAmbientTouchComponentFactory; + + @Mock + AmbientTouchComponent mAmbientTouchComponent; + + @Mock DreamOverlayContainerView mDreamOverlayContainerView; @Mock @@ -136,7 +143,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock - DreamOverlayTouchMonitor mDreamOverlayTouchMonitor; + TouchMonitor mTouchMonitor; @Mock DreamOverlayStateController mStateController; @@ -166,8 +173,6 @@ public class DreamOverlayServiceTest extends SysuiTestCase { .thenReturn(mDreamOverlayContainerViewController); when(mLifecycleOwner.getRegistry()) .thenReturn(mLifecycleRegistry); - when(mDreamOverlayComponent.getDreamOverlayTouchMonitor()) - .thenReturn(mDreamOverlayTouchMonitor); when(mComplicationComponentFactory .create(any(), any(), any(), any())) .thenReturn(mComplicationComponent); @@ -179,8 +184,11 @@ public class DreamOverlayServiceTest extends SysuiTestCase { .create(any(), any())) .thenReturn(mDreamComplicationComponent); when(mDreamOverlayComponentFactory - .create(any(), any(), any(), any())) + .create(any(), any(), any())) .thenReturn(mDreamOverlayComponent); + when(mAmbientTouchComponentFactory.create(any(), any())).thenReturn(mAmbientTouchComponent); + when(mAmbientTouchComponent.getTouchMonitor()) + .thenReturn(mTouchMonitor); when(mDreamOverlayContainerViewController.getContainerView()) .thenReturn(mDreamOverlayContainerView); @@ -193,6 +201,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { mComplicationComponentFactory, mDreamComplicationComponentFactory, mDreamOverlayComponentFactory, + mAmbientTouchComponentFactory, mStateController, mKeyguardUpdateMonitor, mUiEventLogger, @@ -486,6 +495,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { assertThat(mService.shouldShowComplications()).isFalse(); clearInvocations(mDreamOverlayComponent); + clearInvocations(mAmbientTouchComponent); clearInvocations(mWindowManager); // New dream starting with dream complications showing. Note that when a new dream is @@ -505,7 +515,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { // Verify that new instances of overlay container view controller and overlay touch monitor // are created. verify(mDreamOverlayComponent).getDreamOverlayContainerViewController(); - verify(mDreamOverlayComponent).getDreamOverlayTouchMonitor(); + verify(mAmbientTouchComponent).getTouchMonitor(); } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java index 315a24bfd945..848158606a09 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java @@ -16,6 +16,8 @@ package com.android.systemui.dreams.complication; +import static com.android.systemui.Flags.FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH; + import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; @@ -23,6 +25,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.Handler; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.view.MotionEvent; import android.view.View; @@ -31,9 +35,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.complication.Complication; import com.android.systemui.dreams.DreamOverlayStateController; -import com.android.systemui.dreams.touch.DreamTouchHandler; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.touch.TouchInsetManager; @@ -70,7 +74,7 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase { MotionEvent mMotionEvent; @Mock - DreamTouchHandler.TouchSession mSession; + TouchHandler.TouchSession mSession; @Mock DreamOverlayStateController mStateController; @@ -90,6 +94,7 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase { * Ensures no actions are taken when there multiple sessions. */ @Test + @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH) public void testSessionEndOnMultipleSessions() { final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler( mVisibilityController, @@ -122,6 +127,7 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase { * Ensures no actions are taken when the bouncer is showing. */ @Test + @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH) public void testSessionEndWhenBouncerShowing() { final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler( mVisibilityController, @@ -154,6 +160,7 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase { * Ensures no actions are taken when there multiple sessions. */ @Test + @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH) public void testSessionEndWithTouchInInset() { final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler( mVisibilityController, @@ -202,6 +209,7 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase { * Make sure visibility changes are triggered from session events. */ @Test + @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH) public void testSessionLifecycle() { final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler( mVisibilityController, @@ -259,4 +267,34 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase { // Verify session ended. verify(mSession).pop(); } + + @Test + @EnableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH) + public void testNoActionWhenDisabledByFlag() { + final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler( + mVisibilityController, + RESTORE_TIMEOUT, + HIDE_DELAY, + mTouchInsetManager, + mStatusBarKeyguardViewManager, + mFakeExecutor, + mStateController); + + // Report one session. + when(mSession.getActiveSessionCount()).thenReturn(1); + + // Bouncer is showing. + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + + // Start session. + touchHandler.onSessionStart(mSession); + + // Verify session end. + verify(mSession).pop(); + + mClock.advanceTime(HIDE_DELAY); + + // Verify no interaction with visibility controller. + verify(mVisibilityController, never()).setVisibility(anyInt()); + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java index 8dcf9032759b..29fbee01a18b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java @@ -31,6 +31,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.statusbar.phone.CentralSurfaces; @@ -54,7 +55,7 @@ public class CommunalTouchHandlerTest extends SysuiTestCase { @Mock CentralSurfaces mCentralSurfaces; @Mock - DreamTouchHandler.TouchSession mTouchSession; + TouchHandler.TouchSession mTouchSession; CommunalTouchHandler mTouchHandler; @Mock Lifecycle mLifecycle; diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt index 8f03717b42f2..3889703e74c4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt @@ -26,39 +26,34 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.AnimatorTestRule import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.haptics.vibratorHelper +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.kosmos.backgroundCoroutineContext import com.android.systemui.kosmos.testScope -import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.testKosmos -import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any import org.mockito.Mock -import org.mockito.Mockito.never -import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule @SmallTest @RunWith(AndroidJUnit4::class) -@OptIn(ExperimentalCoroutinesApi::class) @RunWithLooper(setAsMainLooper = true) class QSLongPressEffectTest : SysuiTestCase() { @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule() - @Mock private lateinit var vibratorHelper: VibratorHelper @Mock private lateinit var testView: View @get:Rule val animatorTestRule = AnimatorTestRule(this) private val kosmos = testKosmos() + private val vibratorHelper = kosmos.vibratorHelper private val effectDuration = 400 private val lowTickDuration = 12 @@ -68,19 +63,71 @@ class QSLongPressEffectTest : SysuiTestCase() { @Before fun setup() { - whenever( - vibratorHelper.getPrimitiveDurations( - VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - VibrationEffect.Composition.PRIMITIVE_SPIN, - ) - ) - .thenReturn(intArrayOf(lowTickDuration, spinDuration)) + vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] = + lowTickDuration + vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_SPIN] = spinDuration + + kosmos.fakeKeyguardRepository.setKeyguardDismissible(true) longPressEffect = QSLongPressEffect( vibratorHelper, - effectDuration, + kosmos.keyguardInteractor, + CoroutineScope(kosmos.backgroundCoroutineContext), ) + longPressEffect.initializeEffect(effectDuration) + } + + @Test + fun onReset_whileIdle_resetsEffect() = testWithScope { + // GIVEN a call to reset + longPressEffect.resetEffect() + + // THEN the effect remains idle and has not been initialized + val state by collectLastValue(longPressEffect.state) + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) + assertThat(longPressEffect.hasInitialized).isFalse() + } + + @Test + fun onReset_whileRunning_resetsEffect() = testWhileRunning { + // GIVEN a call to reset + longPressEffect.resetEffect() + + // THEN the effect remains idle and has not been initialized + val state by collectLastValue(longPressEffect.state) + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) + assertThat(longPressEffect.hasInitialized).isFalse() + } + + @Test + fun onInitialize_withNegativeDuration_doesNotInitialize() = testWithScope { + // GIVEN an effect that has reset + longPressEffect.resetEffect() + + // WHEN attempting to initialize with a negative duration + val couldInitialize = longPressEffect.initializeEffect(-1) + + // THEN the effect can't initialized and remains reset + val state by collectLastValue(longPressEffect.state) + assertThat(couldInitialize).isFalse() + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) + assertThat(longPressEffect.hasInitialized).isFalse() + } + + @Test + fun onInitialize_withPositiveDuration_initializes() = testWithScope { + // GIVEN an effect that has reset + longPressEffect.resetEffect() + + // WHEN attempting to initialize with a positive duration + val couldInitialize = longPressEffect.initializeEffect(effectDuration) + + // THEN the effect is initialized + val state by collectLastValue(longPressEffect.state) + assertThat(couldInitialize).isTrue() + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) + assertThat(longPressEffect.hasInitialized).isTrue() } @Test @@ -90,7 +137,8 @@ class QSLongPressEffectTest : SysuiTestCase() { longPressEffect.onTouch(testView, downEvent) // THEN the effect moves to the TIMEOUT_WAIT state - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT) + val state by collectLastValue(longPressEffect.state) + assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT) } @Test @@ -100,7 +148,8 @@ class QSLongPressEffectTest : SysuiTestCase() { longPressEffect.onTouch(testView, cancelEvent) // THEN the effect goes back to idle and does not start - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE) + val state by collectLastValue(longPressEffect.state) + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) assertEffectDidNotStart() } @@ -121,7 +170,7 @@ class QSLongPressEffectTest : SysuiTestCase() { @Test fun onWaitComplete_whileWaiting_beginsEffect() = testWhileWaiting { // GIVEN the pressed timeout is complete - advanceTimeBy(QSLongPressEffect.PRESSED_TIMEOUT + 10L) + longPressEffect.handleTimeoutComplete() // THEN the effect starts assertEffectStarted() @@ -154,15 +203,28 @@ class QSLongPressEffectTest : SysuiTestCase() { } @Test - fun onAnimationComplete_effectEnds() = testWhileRunning { + fun onAnimationComplete_keyguardDismissible_effectEndsWithLongPress() = testWhileRunning { // GIVEN that the animation completes animatorTestRule.advanceTimeBy(effectDuration + 10L) - // THEN the long-press effect completes - assertEffectCompleted() + // THEN the long-press effect completes with a LONG_PRESS + assertEffectCompleted(QSLongPressEffect.ActionType.LONG_PRESS) } @Test + fun onAnimationComplete_keyguardNotDismissible_effectEndsWithResetAndLongPress() = + testWhileRunning { + // GIVEN that the keyguard is not dismissible + kosmos.fakeKeyguardRepository.setKeyguardDismissible(false) + + // GIVEN that the animation completes + animatorTestRule.advanceTimeBy(effectDuration + 10L) + + // THEN the long-press effect completes with RESET_AND_LONG_PRESS + assertEffectCompleted(QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS) + } + + @Test fun onActionDown_whileRunningBackwards_resets() = testWhileRunning { // GIVEN that the effect is at the middle of its completion (progress of 50%) animatorTestRule.advanceTimeBy(effectDuration / 2L) @@ -192,33 +254,21 @@ class QSLongPressEffectTest : SysuiTestCase() { animatorTestRule.advanceTimeBy(effectDuration.toLong()) // THEN the state goes to [QSLongPressEffect.State.IDLE] - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE) + val state by collectLastValue(longPressEffect.state) + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) } private fun buildMotionEvent(action: Int): MotionEvent = MotionEventBuilder.newBuilder().setAction(action).build() private fun testWithScope(test: suspend TestScope.() -> Unit) = - with(kosmos) { - testScope.runTest { - // GIVEN an effect with a testing scope - longPressEffect.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler)) - - // THEN run the test - test() - } - } + with(kosmos) { testScope.runTest { test() } } private fun testWhileWaiting(test: suspend TestScope.() -> Unit) = with(kosmos) { testScope.runTest { - // GIVEN an effect with a testing scope - longPressEffect.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler)) - // GIVEN the TIMEOUT_WAIT state is entered - val downEvent = - MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_DOWN).build() - longPressEffect.onTouch(testView, downEvent) + longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT) // THEN run the test test() @@ -228,16 +278,9 @@ class QSLongPressEffectTest : SysuiTestCase() { private fun testWhileRunning(test: suspend TestScope.() -> Unit) = with(kosmos) { testScope.runTest { - // GIVEN an effect with a testing scope - longPressEffect.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler)) - - // GIVEN the down event that enters the TIMEOUT_WAIT state - val downEvent = - MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_DOWN).build() - longPressEffect.onTouch(testView, downEvent) - - // GIVEN that the timeout completes and the effect starts - advanceTimeBy(QSLongPressEffect.PRESSED_TIMEOUT + 10L) + // GIVEN that the effect starts after the tap timeout is complete + longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT) + longPressEffect.handleTimeoutComplete() // THEN run the test test() @@ -252,6 +295,7 @@ class QSLongPressEffectTest : SysuiTestCase() { */ private fun TestScope.assertEffectStarted() { val effectProgress by collectLastValue(longPressEffect.effectProgress) + val state by collectLastValue(longPressEffect.state) val longPressHint = LongPressHapticBuilder.createLongPressHint( lowTickDuration, @@ -259,10 +303,10 @@ class QSLongPressEffectTest : SysuiTestCase() { effectDuration, ) - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD) + assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD) assertThat(effectProgress).isEqualTo(0f) assertThat(longPressHint).isNotNull() - verify(vibratorHelper).vibrate(longPressHint!!) + assertThat(vibratorHelper.hasVibratedWithEffects(longPressHint!!)).isTrue() } /** @@ -274,11 +318,12 @@ class QSLongPressEffectTest : SysuiTestCase() { */ private fun TestScope.assertEffectDidNotStart() { val effectProgress by collectLastValue(longPressEffect.effectProgress) + val state by collectLastValue(longPressEffect.state) - assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD) - assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS) + assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD) + assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS) assertThat(effectProgress).isNull() - verify(vibratorHelper, never()).vibrate(any(/* type= */ VibrationEffect::class.java)) + assertThat(vibratorHelper.totalVibrations).isEqualTo(0) } /** @@ -286,18 +331,19 @@ class QSLongPressEffectTest : SysuiTestCase() { * 1. The progress is null * 2. The final snap haptics are played * 3. The internal state goes back to [QSLongPressEffect.State.IDLE] - * 4. The action to perform on the tile is the long-press action + * 4. The action to perform on the tile is the action given as a parameter */ - private fun TestScope.assertEffectCompleted() { + private fun TestScope.assertEffectCompleted(expectedAction: QSLongPressEffect.ActionType) { val action by collectLastValue(longPressEffect.actionType) val effectProgress by collectLastValue(longPressEffect.effectProgress) val snapEffect = LongPressHapticBuilder.createSnapEffect() + val state by collectLastValue(longPressEffect.state) assertThat(effectProgress).isNull() assertThat(snapEffect).isNotNull() - verify(vibratorHelper).vibrate(snapEffect!!) - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE) - assertThat(action).isEqualTo(QSLongPressEffect.ActionType.LONG_PRESS) + assertThat(vibratorHelper.hasVibratedWithEffects(snapEffect!!)).isTrue() + assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE) + assertThat(action).isEqualTo(expectedAction) } /** @@ -305,17 +351,18 @@ class QSLongPressEffectTest : SysuiTestCase() { * 1. The internal state is [QSLongPressEffect.State.RUNNING_BACKWARDS] * 2. The reverse haptics plays at the point where the animation was paused */ - private fun assertEffectReverses(pausedProgress: Float) { + private fun TestScope.assertEffectReverses(pausedProgress: Float) { val reverseHaptics = LongPressHapticBuilder.createReversedEffect( pausedProgress, lowTickDuration, effectDuration, ) + val state by collectLastValue(longPressEffect.state) - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS) + assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS) assertThat(reverseHaptics).isNotNull() - verify(vibratorHelper).vibrate(reverseHaptics!!) + assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue() } /** @@ -325,8 +372,9 @@ class QSLongPressEffectTest : SysuiTestCase() { */ private fun TestScope.assertEffectResets() { val effectProgress by collectLastValue(longPressEffect.effectProgress) - assertThat(effectProgress).isEqualTo(0f) + val state by collectLastValue(longPressEffect.state) - assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT) + assertThat(effectProgress).isNull() + assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt new file mode 100644 index 000000000000..c88e432d15d2 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.domain.interactor + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardClockSwitch.LARGE +import com.android.keyguard.KeyguardClockSwitch.SMALL +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.flags.Flags +import com.android.systemui.flags.fakeFeatureFlagsClassic +import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.keyguardClockRepository +import com.android.systemui.keyguard.data.repository.keyguardRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.media.controls.data.repository.mediaFilterRepository +import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.shade.data.repository.shadeRepository +import com.android.systemui.shade.shared.model.ShadeMode +import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository +import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs +import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class KeyguardClockInteractorTest : SysuiTestCase() { + private lateinit var kosmos: Kosmos + private lateinit var underTest: KeyguardClockInteractor + private lateinit var testScope: TestScope + + @Before + fun setup() { + kosmos = testKosmos() + testScope = kosmos.testScope + underTest = kosmos.keyguardClockInteractor + } + + @Test + @DisableSceneContainer + fun clockSize_sceneContainerFlagOff_basedOnRepository() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + kosmos.keyguardClockRepository.setClockSize(LARGE) + assertThat(value).isEqualTo(LARGE) + + kosmos.keyguardClockRepository.setClockSize(SMALL) + assertThat(value).isEqualTo(SMALL) + } + + @Test + @DisableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOff_basedOnRepository() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.keyguardInteractor.setClockShouldBeCentered(true) + assertThat(value).isEqualTo(true) + + kosmos.keyguardInteractor.setClockShouldBeCentered(false) + assertThat(value).isEqualTo(false) + } + + @Test + @EnableSceneContainer + fun clockSize_forceSmallClock_SMALL() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + kosmos.fakeKeyguardClockRepository.setShouldForceSmallClock(true) + kosmos.fakeFeatureFlagsClassic.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true) + transitionTo(KeyguardState.AOD, KeyguardState.LOCKSCREEN) + assertThat(value).isEqualTo(SMALL) + } + + @Test + @EnableSceneContainer + fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasNotifs_SMALL() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + kosmos.shadeRepository.setShadeMode(ShadeMode.Single) + kosmos.activeNotificationListRepository.setActiveNotifs(1) + assertThat(value).isEqualTo(SMALL) + } + + @Test + @EnableSceneContainer + fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasMedia_SMALL() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + kosmos.shadeRepository.setShadeMode(ShadeMode.Single) + val userMedia = MediaData().copy(active = true) + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + assertThat(value).isEqualTo(SMALL) + } + + @Test + @EnableSceneContainer + fun clockSize_SceneContainerFlagOn_shadeModeSplit_isMediaVisible_SMALL() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + val userMedia = MediaData().copy(active = true) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + kosmos.keyguardRepository.setIsDozing(false) + assertThat(value).isEqualTo(SMALL) + } + + @Test + @EnableSceneContainer + fun clockSize_SceneContainerFlagOn_shadeModeSplit_noMedia_LARGE() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.keyguardRepository.setIsDozing(false) + assertThat(value).isEqualTo(LARGE) + } + + @Test + @EnableSceneContainer + fun clockSize_SceneContainerFlagOn_shadeModeSplit_isDozing_LARGE() = + testScope.runTest { + val value by collectLastValue(underTest.clockSize) + val userMedia = MediaData().copy(active = true) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + kosmos.keyguardRepository.setIsDozing(true) + assertThat(value).isEqualTo(LARGE) + } + + @Test + @EnableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOn_notSplitMode_true() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.shadeRepository.setShadeMode(ShadeMode.Single) + assertThat(value).isEqualTo(true) + } + + @Test + @EnableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_noActiveNotifications_true() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.activeNotificationListRepository.setActiveNotifs(0) + assertThat(value).isEqualTo(true) + } + + @Test + @EnableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_isActiveDreamLockscreenHosted_true() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.activeNotificationListRepository.setActiveNotifs(1) + kosmos.keyguardRepository.setIsActiveDreamLockscreenHosted(true) + assertThat(value).isEqualTo(true) + } + + @Test + @EnableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_hasPulsingNotifications_false() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.activeNotificationListRepository.setActiveNotifs(1) + kosmos.headsUpNotificationRepository.isHeadsUpAnimatingAway.value = true + kosmos.keyguardRepository.setIsDozing(true) + assertThat(value).isEqualTo(false) + } + + @Test + @EnableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_onAod_true() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.activeNotificationListRepository.setActiveNotifs(1) + transitionTo(KeyguardState.LOCKSCREEN, KeyguardState.AOD) + assertThat(value).isEqualTo(true) + } + + @Test + @EnableSceneContainer + fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_offAod_false() = + testScope.runTest { + val value by collectLastValue(underTest.clockShouldBeCentered) + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + kosmos.activeNotificationListRepository.setActiveNotifs(1) + transitionTo(KeyguardState.AOD, KeyguardState.LOCKSCREEN) + assertThat(value).isEqualTo(false) + } + + private suspend fun transitionTo(from: KeyguardState, to: KeyguardState) { + kosmos.fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(from, to, 0f, TransitionState.STARTED) + ) + kosmos.fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(from, to, 0.5f, TransitionState.RUNNING) + ) + kosmos.fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(from, to, 1f, TransitionState.FINISHED) + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index 6d7a0a96a71b..12f891835d0e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepositor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository @@ -37,7 +38,6 @@ import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor @@ -75,7 +75,6 @@ class KeyguardInteractorTest : SysuiTestCase() { repository = repository, commandQueue = commandQueue, powerInteractor = PowerInteractorFactory.create().powerInteractor, - sceneContainerFlags = kosmos.fakeSceneContainerFlags, bouncerRepository = bouncerRepository, configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()), shadeRepository = shadeRepository, @@ -248,9 +247,9 @@ class KeyguardInteractorTest : SysuiTestCase() { } @Test + @EnableSceneContainer fun animationDozingTransitions() = testScope.runTest { - kosmos.fakeSceneContainerFlags.enabled = true val isAnimate by collectLastValue(underTest.animateDozingTransitions) underTest.setAnimateDozingTransitions(true) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt index 15c9cf73d51d..412292554e73 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt @@ -55,28 +55,29 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() { val testScope = kosmos.testScope @Test - fun transitionCollectorsReceivesOnlyAppropriateEvents() = runTest { - val lockscreenToAodSteps by collectValues(underTest.lockscreenToAodTransition) - val aodToLockscreenSteps by collectValues(underTest.aodToLockscreenTransition) - - val steps = mutableListOf<TransitionStep>() - steps.add(TransitionStep(AOD, GONE, 0f, STARTED)) - steps.add(TransitionStep(AOD, GONE, 1f, FINISHED)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING)) + fun transitionCollectorsReceivesOnlyAppropriateEvents() = + testScope.runTest { + val lockscreenToAodSteps by collectValues(underTest.transition(LOCKSCREEN, AOD)) + val aodToLockscreenSteps by collectValues(underTest.transition(AOD, LOCKSCREEN)) - steps.forEach { - repository.sendTransitionStep(it) - runCurrent() - } + val steps = mutableListOf<TransitionStep>() + steps.add(TransitionStep(AOD, GONE, 0f, STARTED)) + steps.add(TransitionStep(AOD, GONE, 1f, FINISHED)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING)) - assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5)) - assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8)) - } + steps.forEach { + repository.sendTransitionStep(it) + runCurrent() + } + + assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5)) + assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8)) + } @Test fun dozeAmountTransitionTest_AodToFromLockscreen() = @@ -187,59 +188,60 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() { } @Test - fun finishedKeyguardTransitionStepTests() = runTest { - val finishedSteps by collectValues(underTest.finishedKeyguardTransitionStep) + fun finishedKeyguardTransitionStepTests() = + testScope.runTest { + val finishedSteps by collectValues(underTest.finishedKeyguardTransitionStep) + val steps = mutableListOf<TransitionStep>() - val steps = mutableListOf<TransitionStep>() + steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) + steps.add(TransitionStep(AOD, GONE, 1f, STARTED)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) - steps.add(TransitionStep(AOD, GONE, 1f, STARTED)) + steps.forEach { + repository.sendTransitionStep(it) + runCurrent() + } - steps.forEach { - repository.sendTransitionStep(it) - runCurrent() + // Ignore the default state. + assertThat(finishedSteps.subList(1, finishedSteps.size)) + .isEqualTo(listOf(steps[2], steps[5])) } - // Ignore the default state. - assertThat(finishedSteps.subList(1, finishedSteps.size)) - .isEqualTo(listOf(steps[2], steps[5])) - } - @Test - fun startedKeyguardTransitionStepTests() = runTest { - val startedSteps by collectValues(underTest.startedKeyguardTransitionStep) + fun startedKeyguardTransitionStepTests() = + testScope.runTest { + val startedSteps by collectValues(underTest.startedKeyguardTransitionStep) - val steps = mutableListOf<TransitionStep>() + val steps = mutableListOf<TransitionStep>() - steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) - steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING)) - steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED)) - steps.add(TransitionStep(AOD, GONE, 1f, STARTED)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) + steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING)) + steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED)) + steps.add(TransitionStep(AOD, GONE, 1f, STARTED)) - steps.forEach { - repository.sendTransitionStep(it) - runCurrent() - } + steps.forEach { + repository.sendTransitionStep(it) + runCurrent() + } - assertThat(startedSteps) - .isEqualTo( - listOf( - // The initial transition will also get sent when collect started - TransitionStep(OFF, LOCKSCREEN, 0f, STARTED), - steps[0], - steps[3], - steps[6] + assertThat(startedSteps) + .isEqualTo( + listOf( + // The initial transition will also get sent when collect started + TransitionStep(OFF, LOCKSCREEN, 0f, STARTED), + steps[0], + steps[3], + steps[6] + ) ) - ) - } + } @Test fun transitionValue() = diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt index f0607f4b70e1..0ac7ff5232a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE import com.android.systemui.SysuiTestCase @@ -35,10 +36,9 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class KeyguardTransitionAnimationFlowTest : SysuiTestCase() { val kosmos = testKosmos() val testScope = kosmos.testScope diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt index 78bdfb350085..5bf0f4b8dc28 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt @@ -36,6 +36,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -45,16 +46,19 @@ import org.junit.runner.RunWith class AlternateBouncerToGoneTransitionViewModelTest : SysuiTestCase() { val kosmos = testKosmos().apply { - fakeFeatureFlagsClassic.apply { - set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) - set(Flags.FULL_SCREEN_USER_SWITCHER, false) - } + fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } + private val testScope = kosmos.testScope private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository private val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController private val underTest by lazy { kosmos.alternateBouncerToGoneTransitionViewModel } + @Before + fun setup() { + mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT) + } + @Test fun deviceEntryParentViewDisappear() = testScope.runTest { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt index ff41ea25f470..854a4786d059 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt @@ -32,6 +32,7 @@ import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -41,15 +42,17 @@ import org.junit.runner.RunWith class AlternateBouncerToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - fakeFeatureFlagsClassic.apply { - set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) - set(Flags.FULL_SCREEN_USER_SWITCHER, false) - } + fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } private val testScope = kosmos.testScope private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } private val underTest by lazy { kosmos.alternateBouncerToPrimaryBouncerTransitionViewModel } + @Before + fun setup() { + mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT) + } + @Test fun deviceEntryParentViewDisappear() = testScope.runTest { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt index e6b30176d3ee..ee217a63e8ac 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt @@ -57,10 +57,7 @@ class BouncerToGoneFlowsTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - fakeFeatureFlagsClassic.apply { - set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) - set(Flags.FULL_SCREEN_USER_SWITCHER, false) - } + fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } private val testScope = kosmos.testScope private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository @@ -72,6 +69,7 @@ class BouncerToGoneFlowsTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) + mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT) whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false) sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt index fc604aa5a1d2..e3eca6729188 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt @@ -30,11 +30,8 @@ import com.android.systemui.communal.data.repository.communalRepository import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository -import com.android.systemui.flags.Flags -import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository -import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -60,13 +57,9 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class KeyguardRootViewModelTest : SysuiTestCase() { - private val kosmos = - testKosmos().apply { - fakeFeatureFlagsClassic.apply { set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) } - } + private val kosmos = testKosmos() private val testScope = kosmos.testScope private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - private val keyguardInteractor = kosmos.keyguardInteractor private val keyguardRepository = kosmos.fakeKeyguardRepository private val communalRepository = kosmos.communalRepository private val screenOffAnimationController = kosmos.screenOffAnimationController @@ -82,7 +75,10 @@ class KeyguardRootViewModelTest : SysuiTestCase() { fun setUp() { mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR) mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION) - mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) + mSetFlagsRule.disableFlags( + AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, + AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT, + ) } @Test @@ -426,4 +422,23 @@ class KeyguardRootViewModelTest : SysuiTestCase() { shadeRepository.setQsExpansion(0.5f) assertThat(alpha).isEqualTo(0f) } + + @Test + fun alpha_idleOnDream_isZero() = + testScope.runTest { + val alpha by collectLastValue(underTest.alpha(viewState)) + assertThat(alpha).isEqualTo(1f) + + // Go to GONE state + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.DREAMING, + testScope = testScope, + ) + assertThat(alpha).isEqualTo(0f) + + // Try pulling down shade and ensure the value doesn't change + shadeRepository.setQsExpansion(0.5f) + assertThat(alpha).isEqualTo(0f) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt index 66f7e015a133..776f1a55fdcb 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt @@ -34,6 +34,8 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.kosmos.testScope +import com.android.systemui.power.data.repository.fakePowerRepository +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.shadeRepository @@ -43,6 +45,7 @@ import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificati import com.android.systemui.testKosmos import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat +import kotlin.math.pow import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.BeforeClass @@ -57,22 +60,26 @@ import platform.test.runner.parameterized.Parameters class LockscreenSceneViewModelTest : SysuiTestCase() { companion object { + private const val parameterCount = 6 + @Parameters( name = "canSwipeToEnter={0}, downWithTwoPointers={1}, downFromEdge={2}," + - " isSingleShade={3}, isCommunalAvailable={4}" + " isSingleShade={3}, isCommunalAvailable={4}, isShadeTouchable={5}" ) @JvmStatic fun combinations() = buildList { - repeat(32) { combination -> + repeat(2f.pow(parameterCount).toInt()) { combination -> add( arrayOf( - /* canSwipeToEnter= */ combination and 1 != 0, - /* downWithTwoPointers= */ combination and 2 != 0, - /* downFromEdge= */ combination and 4 != 0, - /* isSingleShade= */ combination and 8 != 0, - /* isCommunalAvailable= */ combination and 16 != 0, - ) + /* canSwipeToEnter= */ combination and 1 != 0, + /* downWithTwoPointers= */ combination and 2 != 0, + /* downFromEdge= */ combination and 4 != 0, + /* isSingleShade= */ combination and 8 != 0, + /* isCommunalAvailable= */ combination and 16 != 0, + /* isShadeTouchable= */ combination and 32 != 0, + ) + .also { check(it.size == parameterCount) } ) } } @@ -82,8 +89,15 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun setUp() { val combinationStrings = combinations().map { array -> - check(array.size == 5) - "${array[4]},${array[3]},${array[2]},${array[1]},${array[0]}" + check(array.size == parameterCount) + buildString { + ((parameterCount - 1) downTo 0).forEach { index -> + append("${array[index]}") + if (index > 0) { + append(",") + } + } + } } val uniqueCombinations = combinationStrings.toSet() assertThat(combinationStrings).hasSize(uniqueCombinations.size) @@ -92,8 +106,35 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { private fun expectedDownDestination( downFromEdge: Boolean, isSingleShade: Boolean, - ): SceneKey { - return if (downFromEdge && isSingleShade) Scenes.QuickSettings else Scenes.Shade + isShadeTouchable: Boolean, + ): SceneKey? { + return when { + !isShadeTouchable -> null + downFromEdge && isSingleShade -> Scenes.QuickSettings + else -> Scenes.Shade + } + } + + private fun expectedUpDestination( + canSwipeToEnter: Boolean, + isShadeTouchable: Boolean, + ): SceneKey? { + return when { + !isShadeTouchable -> null + canSwipeToEnter -> Scenes.Gone + else -> Scenes.Bouncer + } + } + + private fun expectedLeftDestination( + isCommunalAvailable: Boolean, + isShadeTouchable: Boolean, + ): SceneKey? { + return when { + !isShadeTouchable -> null + isCommunalAvailable -> Scenes.Communal + else -> null + } } } @@ -106,6 +147,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { @JvmField @Parameter(2) var downFromEdge: Boolean = false @JvmField @Parameter(3) var isSingleShade: Boolean = true @JvmField @Parameter(4) var isCommunalAvailable: Boolean = false + @JvmField @Parameter(5) var isShadeTouchable: Boolean = false private val underTest by lazy { createLockscreenSceneViewModel() } @@ -130,6 +172,14 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { } ) kosmos.setCommunalAvailable(isCommunalAvailable) + kosmos.fakePowerRepository.updateWakefulness( + rawState = + if (isShadeTouchable) { + WakefulnessState.AWAKE + } else { + WakefulnessState.ASLEEP + }, + ) val destinationScenes by collectLastValue(underTest.destinationScenes) @@ -148,14 +198,25 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { expectedDownDestination( downFromEdge = downFromEdge, isSingleShade = isSingleShade, + isShadeTouchable = isShadeTouchable, ) ) assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.toScene) - .isEqualTo(if (canSwipeToEnter) Scenes.Gone else Scenes.Bouncer) + .isEqualTo( + expectedUpDestination( + canSwipeToEnter = canSwipeToEnter, + isShadeTouchable = isShadeTouchable, + ) + ) assertThat(destinationScenes?.get(Swipe(SwipeDirection.Left))?.toScene) - .isEqualTo(Scenes.Communal.takeIf { isCommunalAvailable }) + .isEqualTo( + expectedLeftDestination( + isCommunalAvailable = isCommunalAvailable, + isShadeTouchable = isShadeTouchable, + ) + ) } private fun createLockscreenSceneViewModel(): LockscreenSceneViewModel { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt index dddf6485d0f4..4c16a339d696 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt @@ -49,9 +49,7 @@ class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() { val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository val configurationRepository = kosmos.fakeConfigurationRepository - val underTest by lazy { - kosmos.occludedToLockscreenTransitionViewModel - } + val underTest by lazy { kosmos.occludedToLockscreenTransitionViewModel } @Test fun lockscreenFadeIn() = @@ -164,25 +162,6 @@ class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() { values.forEach { assertThat(it).isEqualTo(1f) } } - @Test - fun deviceEntryBackgroundView_noUdfpsEnrolled_noUpdates() = - testScope.runTest { - fingerprintPropertyRepository.supportsRearFps() - biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) - val values by collectValues(underTest.deviceEntryBackgroundViewAlpha) - - keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED)) - keyguardTransitionRepository.sendTransitionStep(step(0.1f)) - keyguardTransitionRepository.sendTransitionStep(step(0.3f)) - keyguardTransitionRepository.sendTransitionStep(step(0.4f)) - keyguardTransitionRepository.sendTransitionStep(step(0.5f)) - keyguardTransitionRepository.sendTransitionStep(step(0.6f)) - keyguardTransitionRepository.sendTransitionStep(step(0.8f)) - keyguardTransitionRepository.sendTransitionStep(step(1f)) - - assertThat(values).isEmpty() // no updates - } - private fun step( value: Float, state: TransitionState = TransitionState.RUNNING diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt index db1d5d91eb65..18e9009611c9 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt @@ -44,10 +44,7 @@ import org.junit.runner.RunWith class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() { val kosmos = testKosmos().apply { - fakeFeatureFlagsClassic.apply { - set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) - set(Flags.FULL_SCREEN_USER_SWITCHER, false) - } + fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } val testScope = kosmos.testScope @@ -58,6 +55,7 @@ class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() { @Before fun setUp() { + mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT) whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false) sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt index 956ef661d467..f685058c77fa 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt @@ -25,8 +25,11 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.MediaTestHelper +import com.android.systemui.media.controls.shared.model.MediaCommonModel import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData +import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest @@ -144,7 +147,173 @@ class MediaFilterRepositoryTest : SysuiTestCase() { assertThat(smartspaceMediaData?.isActive).isFalse() } + @Test + fun addMediaDataLoadingState() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(underTest.mediaDataLoadedStates) + val instanceId = InstanceId.fakeInstanceId(123) + val mediaLoadedStates = mutableListOf(MediaDataLoadingModel.Loaded(instanceId)) + + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId)) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates) + + mediaLoadedStates.remove(MediaDataLoadingModel.Loaded(instanceId)) + + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Removed(instanceId)) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates) + } + + @Test + fun setRecommendationsLoadingState() = + testScope.runTest { + val recommendationsLoadingState by + collectLastValue(underTest.recommendationsLoadingState) + val recommendationsLoadingModel = + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE) + + underTest.setRecommendationsLoadingState(recommendationsLoadingModel) + + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) + } + + @Test + fun addMediaControlPlayingThenRemote() = + testScope.runTest { + val sortedMedia by collectLastValue(underTest.sortedMedia) + val playingInstanceId = InstanceId.fakeInstanceId(123) + val remoteInstanceId = InstanceId.fakeInstanceId(321) + val playingData = createMediaData("app1", true, LOCAL, false, playingInstanceId) + val remoteData = createMediaData("app2", true, REMOTE, false, remoteInstanceId) + + underTest.addSelectedUserMediaEntry(playingData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId)) + underTest.addSelectedUserMediaEntry(remoteData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(remoteInstanceId)) + + assertThat(sortedMedia?.size).isEqualTo(2) + assertThat(sortedMedia?.values) + .containsExactly( + MediaCommonModel.MediaControl(playingInstanceId), + MediaCommonModel.MediaControl(remoteInstanceId) + ) + } + + @Test + fun switchMediaControlsPlaying() = + testScope.runTest { + val sortedMedia by collectLastValue(underTest.sortedMedia) + val playingInstanceId1 = InstanceId.fakeInstanceId(123) + val playingInstanceId2 = InstanceId.fakeInstanceId(321) + var playingData1 = createMediaData("app1", true, LOCAL, false, playingInstanceId1) + var playingData2 = createMediaData("app2", false, LOCAL, false, playingInstanceId2) + + underTest.addSelectedUserMediaEntry(playingData1) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId1)) + underTest.addSelectedUserMediaEntry(playingData2) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId2)) + + assertThat(sortedMedia?.size).isEqualTo(2) + assertThat(sortedMedia?.values) + .containsExactly( + MediaCommonModel.MediaControl(playingInstanceId1), + MediaCommonModel.MediaControl(playingInstanceId2) + ) + .inOrder() + + playingData1 = createMediaData("app1", false, LOCAL, false, playingInstanceId1) + playingData2 = createMediaData("app2", true, LOCAL, false, playingInstanceId2) + + underTest.addSelectedUserMediaEntry(playingData1) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId1)) + underTest.addSelectedUserMediaEntry(playingData2) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId2)) + + assertThat(sortedMedia?.size).isEqualTo(2) + assertThat(sortedMedia?.values) + .containsExactly( + MediaCommonModel.MediaControl(playingInstanceId2), + MediaCommonModel.MediaControl(playingInstanceId1) + ) + .inOrder() + } + + @Test + fun fullOrderTest() = + testScope.runTest { + val sortedMedia by collectLastValue(underTest.sortedMedia) + val instanceId1 = InstanceId.fakeInstanceId(123) + val instanceId2 = InstanceId.fakeInstanceId(456) + val instanceId3 = InstanceId.fakeInstanceId(321) + val instanceId4 = InstanceId.fakeInstanceId(654) + val instanceId5 = InstanceId.fakeInstanceId(124) + val playingAndLocalData = createMediaData("app1", true, LOCAL, false, instanceId1) + val playingAndRemoteData = createMediaData("app2", true, REMOTE, false, instanceId2) + val stoppedAndLocalData = createMediaData("app3", false, LOCAL, false, instanceId3) + val stoppedAndRemoteData = createMediaData("app4", false, REMOTE, false, instanceId4) + val canResumeData = createMediaData("app5", false, LOCAL, true, instanceId5) + + val icon = Icon.createWithResource(context, R.drawable.ic_media_play) + val mediaRecommendations = + SmartspaceMediaData( + targetId = KEY_MEDIA_SMARTSPACE, + isActive = true, + recommendations = MediaTestHelper.getValidRecommendationList(icon), + ) + + underTest.addSelectedUserMediaEntry(stoppedAndLocalData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId3)) + + underTest.addSelectedUserMediaEntry(stoppedAndRemoteData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId4)) + + underTest.addSelectedUserMediaEntry(canResumeData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId5)) + + underTest.addSelectedUserMediaEntry(playingAndLocalData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId1)) + + underTest.addSelectedUserMediaEntry(playingAndRemoteData) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId2)) + + underTest.setRecommendation(mediaRecommendations) + underTest.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) + ) + + assertThat(sortedMedia?.size).isEqualTo(6) + assertThat(sortedMedia?.values) + .containsExactly( + MediaCommonModel.MediaControl(instanceId1), + MediaCommonModel.MediaControl(instanceId2), + MediaCommonModel.MediaRecommendations(KEY_MEDIA_SMARTSPACE), + MediaCommonModel.MediaControl(instanceId4), + MediaCommonModel.MediaControl(instanceId3), + MediaCommonModel.MediaControl(instanceId5), + ) + .inOrder() + } + + private fun createMediaData( + app: String, + playing: Boolean, + playbackLocation: Int, + isResume: Boolean, + instanceId: InstanceId, + ): MediaData { + return MediaData( + playbackLocation = playbackLocation, + resumption = isResume, + notificationKey = "key: $app", + isPlaying = playing, + instanceId = instanceId + ) + } + companion object { + private const val LOCAL = MediaData.PLAYBACK_LOCAL + private const val REMOTE = MediaData.PLAYBACK_CAST_LOCAL private const val KEY = "KEY" private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID" } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt index d9d84f2d2aac..c15776e5345e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt @@ -20,6 +20,7 @@ import android.R import android.graphics.drawable.Icon import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.Flags @@ -28,13 +29,21 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.MediaTestHelper import com.android.systemui.media.controls.data.repository.MediaFilterRepository import com.android.systemui.media.controls.data.repository.mediaFilterRepository +import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor +import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter +import com.android.systemui.media.controls.shared.model.MediaCommonModel import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData +import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel +import com.android.systemui.statusbar.notificationLockscreenUserManager import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -45,9 +54,17 @@ class MediaCarouselInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope + private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter + private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository + private val underTest: MediaCarouselInteractor = kosmos.mediaCarouselInteractor + @Before + fun setUp() { + underTest.start() + } + @Test fun addUserMediaEntry_activeThenInactivate() = testScope.runTest { @@ -56,7 +73,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() { val hasActiveMedia by collectLastValue(underTest.hasActiveMedia) val hasAnyMedia by collectLastValue(underTest.hasAnyMedia) - val userMedia = MediaData().copy(active = true) + val userMedia = MediaData(active = true) mediaFilterRepository.addSelectedUserMediaEntry(userMedia) @@ -78,22 +95,29 @@ class MediaCarouselInteractorTest : SysuiTestCase() { collectLastValue(underTest.hasActiveMediaOrRecommendation) val hasActiveMedia by collectLastValue(underTest.hasActiveMedia) val hasAnyMedia by collectLastValue(underTest.hasAnyMedia) + val sortedMedia by collectLastValue(underTest.sortedMedia) - val userMedia = MediaData().copy(active = false) + val userMedia = MediaData(active = false) val instanceId = userMedia.instanceId mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId)) assertThat(hasActiveMediaOrRecommendation).isFalse() assertThat(hasActiveMedia).isFalse() assertThat(hasAnyMedia).isTrue() + assertThat(sortedMedia).containsExactly(MediaCommonModel.MediaControl(instanceId)) assertThat(mediaFilterRepository.removeSelectedUserMediaEntry(instanceId, userMedia)) .isTrue() + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Removed(instanceId) + ) assertThat(hasActiveMediaOrRecommendation).isFalse() assertThat(hasActiveMedia).isFalse() assertThat(hasAnyMedia).isFalse() + assertThat(sortedMedia).isEmpty() } @Test @@ -103,6 +127,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() { collectLastValue(underTest.hasActiveMediaOrRecommendation) val hasAnyMediaOrRecommendation by collectLastValue(underTest.hasAnyMediaOrRecommendation) + val sortedMedia by collectLastValue(underTest.sortedMedia) kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) val icon = Icon.createWithResource(context, R.drawable.ic_media_play) @@ -112,17 +137,31 @@ class MediaCarouselInteractorTest : SysuiTestCase() { isActive = true, recommendations = MediaTestHelper.getValidRecommendationList(icon), ) - val userMedia = MediaData().copy(active = false) + val userMedia = MediaData(active = false) mediaFilterRepository.setRecommendation(userMediaRecommendation) + mediaFilterRepository.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) + ) assertThat(hasActiveMediaOrRecommendation).isTrue() assertThat(hasAnyMediaOrRecommendation).isTrue() + assertThat(sortedMedia) + .containsExactly(MediaCommonModel.MediaRecommendations(KEY_MEDIA_SMARTSPACE)) mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Loaded(userMedia.instanceId) + ) assertThat(hasActiveMediaOrRecommendation).isTrue() assertThat(hasAnyMediaOrRecommendation).isTrue() + assertThat(sortedMedia) + .containsExactly( + MediaCommonModel.MediaRecommendations(KEY_MEDIA_SMARTSPACE), + MediaCommonModel.MediaControl(userMedia.instanceId) + ) + .inOrder() } @Test @@ -199,7 +238,80 @@ class MediaCarouselInteractorTest : SysuiTestCase() { fun hasActiveMediaOrRecommendation_nothingSet_returnsFalse() = testScope.runTest { assertThat(underTest.hasActiveMediaOrRecommendation.value).isFalse() } + @Test + fun onMediaDataUpdated_updatesLoadingState() = + testScope.runTest { + whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true) + whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true) + val mediaDataLoadedStates by collectLastValue(underTest.mediaDataLoadedStates) + val instanceId = InstanceId.fakeInstanceId(123) + val mediaLoadedStates: MutableList<MediaDataLoadingModel> = mutableListOf() + + mediaLoadedStates.add(MediaDataLoadingModel.Loaded(instanceId)) + mediaDataFilter.onMediaDataLoaded( + KEY, + KEY, + MediaData(userId = USER_ID, instanceId = instanceId) + ) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates) + + val newInstanceId = InstanceId.fakeInstanceId(321) + + mediaLoadedStates.add(MediaDataLoadingModel.Loaded(newInstanceId)) + mediaDataFilter.onMediaDataLoaded( + KEY_2, + KEY_2, + MediaData(userId = USER_ID, instanceId = newInstanceId) + ) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates) + + mediaLoadedStates.remove(MediaDataLoadingModel.Loaded(instanceId)) + + mediaDataFilter.onMediaDataRemoved(KEY) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates) + + mediaLoadedStates.remove(MediaDataLoadingModel.Loaded(newInstanceId)) + + mediaDataFilter.onMediaDataRemoved(KEY_2) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates) + } + + @Test + fun onMediaRecommendationsUpdated_updatesLoadingState() = + testScope.runTest { + whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true) + whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true) + val recommendationsLoadingState by + collectLastValue(underTest.recommendationsLoadingState) + val icon = Icon.createWithResource(context, R.drawable.ic_media_play) + val mediaRecommendations = + SmartspaceMediaData( + targetId = KEY_MEDIA_SMARTSPACE, + isActive = true, + recommendations = MediaTestHelper.getValidRecommendationList(icon), + ) + var recommendationsLoadingModel: SmartspaceMediaLoadingModel = + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, isPrioritized = true) + + mediaDataFilter.onSmartspaceMediaDataLoaded(KEY_MEDIA_SMARTSPACE, mediaRecommendations) + + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) + + recommendationsLoadingModel = SmartspaceMediaLoadingModel.Removed(KEY_MEDIA_SMARTSPACE) + + mediaDataFilter.onSmartspaceMediaDataRemoved(KEY_MEDIA_SMARTSPACE) + + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) + } + companion object { + private const val KEY = "key" + private const val KEY_2 = "key2" + private const val USER_ID = 0 private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID" } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt index a1cee8aaac7c..d9224d7e3421 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt @@ -16,10 +16,17 @@ package com.android.systemui.media.controls.domain.interactor +import android.app.PendingIntent +import android.os.Bundle import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase +import com.android.systemui.activityIntentHelper +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.animation.DialogTransitionAnimator +import com.android.systemui.animation.Expandable +import com.android.systemui.bluetooth.mockBroadcastDialogController import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl @@ -28,13 +35,22 @@ import com.android.systemui.media.controls.domain.pipeline.interactor.mediaContr import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.util.mediaInstanceId +import com.android.systemui.media.mediaOutputDialogManager +import com.android.systemui.mockActivityIntentHelper +import com.android.systemui.plugins.activityStarter import com.android.systemui.statusbar.notificationLockscreenUserManager +import com.android.systemui.statusbar.policy.keyguardStateController import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.never +import org.mockito.Mockito.verify @SmallTest @RunWith(AndroidJUnit4::class) @@ -44,10 +60,16 @@ class MediaControlInteractorTest : SysuiTestCase() { private val testScope = kosmos.testScope private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter + private val activityStarter = kosmos.activityStarter + private val keyguardStateController = kosmos.keyguardStateController private val instanceId: InstanceId = kosmos.mediaInstanceId private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager - private val underTest: MediaControlInteractor = kosmos.mediaControlInteractor + private val underTest: MediaControlInteractor = + with(kosmos) { + activityIntentHelper = mockActivityIntentHelper + kosmos.mediaControlInteractor + } @Test fun onMediaDataUpdated() = @@ -55,39 +77,146 @@ class MediaControlInteractorTest : SysuiTestCase() { whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true) whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true) val controlModel by collectLastValue(underTest.mediaControl) - var mediaData = - MediaData(userId = USER_ID, instanceId = instanceId, artist = SESSION_ARTIST) + var mediaData = MediaData(userId = USER_ID, instanceId = instanceId, artist = ARTIST) mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData) assertThat(controlModel?.instanceId).isEqualTo(instanceId) - assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST) + assertThat(controlModel?.artistName).isEqualTo(ARTIST) - mediaData = - MediaData(userId = USER_ID, instanceId = instanceId, artist = SESSION_ARTIST_2) + mediaData = MediaData(userId = USER_ID, instanceId = instanceId, artist = ARTIST_2) mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData) assertThat(controlModel?.instanceId).isEqualTo(instanceId) - assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST_2) + assertThat(controlModel?.artistName).isEqualTo(ARTIST_2) mediaData = MediaData( userId = USER_ID, instanceId = InstanceId.fakeInstanceId(2), - artist = SESSION_ARTIST + artist = ARTIST ) mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData) assertThat(controlModel?.instanceId).isNotEqualTo(mediaData.instanceId) - assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST_2) + assertThat(controlModel?.artistName).isEqualTo(ARTIST_2) } + @Test + fun startSettings() { + underTest.startSettings() + + verify(activityStarter).startActivity(any(), eq(true)) + } + + @Test + fun startClickIntent_showOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())) + .thenReturn(true) + + val clickIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + val expandable = mock<Expandable>() + + underTest.startClickIntent(expandable, clickIntent) + + verify(clickIntent).send(any<Bundle>()) + } + + @Test + fun startClickIntent_hideOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(false) + + val clickIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + val expandable = mock<Expandable>() + val activityController = mock<ActivityTransitionAnimator.Controller>() + whenever(expandable.activityTransitionController(any())).thenReturn(activityController) + + underTest.startClickIntent(expandable, clickIntent) + + verify(activityStarter) + .postStartActivityDismissingKeyguard(eq(clickIntent), eq(activityController)) + } + + @Test + fun startDeviceIntent_showOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())) + .thenReturn(true) + + val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + + underTest.startDeviceIntent(deviceIntent) + + verify(deviceIntent).send(any<Bundle>()) + } + + @Test + fun startDeviceIntent_intentNotActivity() { + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())) + .thenReturn(true) + + val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(false) } + + underTest.startDeviceIntent(deviceIntent) + + verify(deviceIntent, never()).send(any<Bundle>()) + } + + @Test + fun startDeviceIntent_hideOverLockscreen() { + whenever(keyguardStateController.isShowing).thenReturn(false) + + val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) } + + underTest.startDeviceIntent(deviceIntent) + + verify(activityStarter).postStartActivityDismissingKeyguard(eq(deviceIntent)) + } + + @Test + fun startMediaOutputDialog() { + val expandable = mock<Expandable>() + val dialogTransitionController = mock<DialogTransitionAnimator.Controller>() + whenever(expandable.dialogTransitionController(any())) + .thenReturn(dialogTransitionController) + + underTest.startMediaOutputDialog(expandable, PACKAGE_NAME) + + verify(kosmos.mediaOutputDialogManager) + .createAndShowWithController( + eq(PACKAGE_NAME), + eq(true), + eq(dialogTransitionController), + eq(null) + ) + } + + @Test + fun startBroadcastDialog() { + val expandable = mock<Expandable>() + val dialogTransitionController = mock<DialogTransitionAnimator.Controller>() + whenever(expandable.dialogTransitionController()).thenReturn(dialogTransitionController) + + underTest.startBroadcastDialog(expandable, APP_NAME, PACKAGE_NAME) + + verify(kosmos.mockBroadcastDialogController) + .createBroadcastDialogWithController( + eq(APP_NAME), + eq(PACKAGE_NAME), + eq(dialogTransitionController) + ) + } + companion object { private const val USER_ID = 0 private const val KEY = "key" - private const val SESSION_ARTIST = "artist" - private const val SESSION_ARTIST_2 = "artist2" + private const val PACKAGE_NAME = "com.example.app" + private const val APP_NAME = "app" + private const val ARTIST = "artist" + private const val ARTIST_2 = "artist2" } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt new file mode 100644 index 000000000000..9558e5d23a25 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.viewmodel + +import android.R +import android.content.packageManager +import android.content.pm.ApplicationInfo +import android.media.MediaMetadata +import android.media.session.MediaSession +import android.media.session.PlaybackState +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.internal.logging.InstanceId +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope +import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl +import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter +import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.controls.shared.model.MediaDeviceData +import com.android.systemui.media.controls.util.mediaInstanceId +import com.android.systemui.statusbar.notificationLockscreenUserManager +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.mockito.Mockito + +@SmallTest +@RunWith(AndroidJUnit4::class) +class MediaControlViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter + private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager + private val packageManager = kosmos.packageManager + private val drawable = context.getDrawable(R.drawable.ic_media_play) + private val instanceId: InstanceId = kosmos.mediaInstanceId + + private val underTest: MediaControlViewModel = kosmos.mediaControlViewModel + + @Test + fun addMediaControl_mediaControlViewModelIsLoaded() = + testScope.runTest { + whenever(packageManager.getApplicationIcon(Mockito.anyString())).thenReturn(drawable) + whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java))) + .thenReturn(drawable) + whenever(packageManager.getApplicationInfo(eq(PACKAGE_NAME), ArgumentMatchers.anyInt())) + .thenReturn(ApplicationInfo()) + whenever(packageManager.getApplicationLabel(any())).thenReturn(PACKAGE_NAME) + whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true) + whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true) + val playerModel by collectLastValue(underTest.player) + + context.setMockPackageManager(packageManager) + + val mediaData = initMediaData() + + mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData) + + assertThat(playerModel).isNotNull() + assertThat(playerModel?.titleName).isEqualTo(TITLE) + assertThat(playerModel?.artistName).isEqualTo(ARTIST) + assertThat(playerModel?.gutsMenu).isNotNull() + assertThat(playerModel?.outputSwitcher).isNotNull() + assertThat(playerModel?.actionButtons).isNotNull() + assertThat(playerModel?.playTurbulenceNoise).isFalse() + } + + private fun initMediaData(): MediaData { + val device = MediaDeviceData(true, null, DEVICE_NAME, null, showBroadcastButton = true) + + // Create media session + val metadataBuilder = + MediaMetadata.Builder().apply { + putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST) + putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE) + } + val playbackBuilder = + PlaybackState.Builder().apply { + setState(PlaybackState.STATE_PAUSED, 6000L, 1f) + setActions(PlaybackState.ACTION_PLAY) + } + val session = + MediaSession(context, SESSION_KEY).apply { + setMetadata(metadataBuilder.build()) + setPlaybackState(playbackBuilder.build()) + } + session.isActive = true + + return MediaData( + userId = USER_ID, + artist = ARTIST, + song = TITLE, + packageName = PACKAGE, + token = session.sessionToken, + device = device, + instanceId = instanceId + ) + } + + companion object { + private const val USER_ID = 0 + private const val KEY = "key" + private const val PACKAGE_NAME = "com.example.app" + private const val PACKAGE = "PKG" + private const val ARTIST = "ARTIST" + private const val TITLE = "TITLE" + private const val DEVICE_NAME = "DEVICE_NAME" + private const val SESSION_KEY = "SESSION_KEY" + private const val SESSION_ARTIST = "SESSION_ARTIST" + private const val SESSION_TITLE = "SESSION_TITLE" + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt index 6d6fd754341d..d0699aa12a43 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt @@ -16,7 +16,9 @@ package com.android.systemui.qs.pipeline.domain.autoaddable -import android.platform.test.annotations.EnabledOnRavenwood +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import android.view.accessibility.Flags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase @@ -44,7 +46,6 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@EnabledOnRavenwood @RunWith(AndroidJUnit4::class) class ReduceBrightColorsAutoAddableTest : SysuiTestCase() { @@ -67,12 +68,14 @@ class ReduceBrightColorsAutoAddableTest : SysuiTestCase() { } @Test + @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) fun available_strategyIfNotAdded() = testWithFeatureAvailability(available = true) { assertThat(underTest.autoAddTracking).isEqualTo(AutoAddTracking.IfNotAdded(SPEC)) } @Test + @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) fun activated_addSignal() = testWithFeatureAvailability { val signal by collectLastValue(underTest.autoAddSignal(0)) runCurrent() @@ -85,6 +88,7 @@ class ReduceBrightColorsAutoAddableTest : SysuiTestCase() { } @Test + @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) fun notActivated_noSignal() = testWithFeatureAvailability { val signal by collectLastValue(underTest.autoAddSignal(0)) runCurrent() @@ -96,6 +100,13 @@ class ReduceBrightColorsAutoAddableTest : SysuiTestCase() { assertThat(signal).isNull() } + @Test + @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) + fun available_a11yQsShortcutFlagEnabled_strategyDisabled() = + testWithFeatureAvailability(available = true) { + assertThat(underTest.autoAddTracking).isEqualTo(AutoAddTracking.Disabled) + } + private fun testWithFeatureAvailability( available: Boolean = true, body: suspend TestScope.() -> TestResult diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractorTest.kt new file mode 100644 index 000000000000..2e5fde8e4bd6 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractorTest.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor + +import android.os.UserHandle +import android.platform.test.annotations.EnabledOnRavenwood +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.accessibility.reduceBrightColorsController +import com.android.systemui.coroutines.collectValues +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.toCollection +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@EnabledOnRavenwood +@RunWith(AndroidJUnit4::class) +class ReduceBrightColorsTileDataInteractorTest : SysuiTestCase() { + + private val isAvailable = true + private val kosmos = Kosmos() + private val testScope = kosmos.testScope + private val reduceBrightColorsController = kosmos.reduceBrightColorsController + private val underTest: ReduceBrightColorsTileDataInteractor = + ReduceBrightColorsTileDataInteractor( + testScope.testScheduler, + isAvailable, + reduceBrightColorsController + ) + + @Test + fun alwaysAvailable() = + testScope.runTest { + val availability = underTest.availability(TEST_USER).toCollection(mutableListOf()) + + assertThat(availability).hasSize(1) + assertThat(availability.last()).isEqualTo(isAvailable) + } + + @Test + fun dataMatchesTheRepository() = + testScope.runTest { + val dataList: List<ReduceBrightColorsTileModel> by + collectValues( + underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)) + ) + runCurrent() + + reduceBrightColorsController.isReduceBrightColorsActivated = true + runCurrent() + + reduceBrightColorsController.isReduceBrightColorsActivated = false + runCurrent() + + assertThat(dataList).hasSize(3) + assertThat(dataList.map { it.isEnabled }).isEqualTo(listOf(false, true, false)) + } + + private companion object { + val TEST_USER = UserHandle.of(1)!! + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractorTest.kt new file mode 100644 index 000000000000..6ea5e63fdff6 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractorTest.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor + +import android.platform.test.annotations.EnabledOnRavenwood +import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.accessibility.reduceBrightColorsController +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler +import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject +import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@EnabledOnRavenwood +@RunWith(AndroidJUnit4::class) +class ReduceBrightColorsTileUserActionInteractorTest : SysuiTestCase() { + + private val kosmos = Kosmos() + private val inputHandler = FakeQSTileIntentUserInputHandler() + private val controller = kosmos.reduceBrightColorsController + + private val underTest = + ReduceBrightColorsTileUserActionInteractor( + inputHandler, + controller, + ) + + @Test + fun handleClickWhenEnabled() = runTest { + val wasEnabled = true + controller.isReduceBrightColorsActivated = wasEnabled + + underTest.handleInput(QSTileInputTestKtx.click(ReduceBrightColorsTileModel(wasEnabled))) + + assertThat(controller.isReduceBrightColorsActivated).isEqualTo(!wasEnabled) + } + + @Test + fun handleClickWhenDisabled() = runTest { + val wasEnabled = false + controller.isReduceBrightColorsActivated = wasEnabled + + underTest.handleInput(QSTileInputTestKtx.click(ReduceBrightColorsTileModel(wasEnabled))) + + assertThat(controller.isReduceBrightColorsActivated).isEqualTo(!wasEnabled) + } + + @Test + fun handleLongClickWhenDisabled() = runTest { + val enabled = false + + underTest.handleInput(QSTileInputTestKtx.longClick(ReduceBrightColorsTileModel(enabled))) + + QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput { + assertThat(it.intent.action).isEqualTo(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS) + } + } + + @Test + fun handleLongClickWhenEnabled() = runTest { + val enabled = true + + underTest.handleInput(QSTileInputTestKtx.longClick(ReduceBrightColorsTileModel(enabled))) + + QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput { + assertThat(it.intent.action).isEqualTo(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS) + } + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt new file mode 100644 index 000000000000..10e9bd695cbc --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.ui + +import android.graphics.drawable.TestStubDrawable +import android.service.quicksettings.Tile +import android.widget.Switch +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.android.systemui.qs.tiles.impl.reducebrightness.qsReduceBrightColorsTileConfig +import com.android.systemui.qs.tiles.viewmodel.QSTileState +import com.android.systemui.res.R +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class ReduceBrightColorsTileMapperTest : SysuiTestCase() { + private val kosmos = Kosmos() + private val config = kosmos.qsReduceBrightColorsTileConfig + + private lateinit var mapper: ReduceBrightColorsTileMapper + + @Before + fun setup() { + mapper = + ReduceBrightColorsTileMapper( + context.orCreateTestableResources + .apply { + addOverride(R.drawable.qs_extra_dim_icon_on, TestStubDrawable()) + addOverride(R.drawable.qs_extra_dim_icon_off, TestStubDrawable()) + } + .resources, + context.theme + ) + } + + @Test + fun disabledModel() { + val inputModel = ReduceBrightColorsTileModel(false) + + val outputState = mapper.map(config, inputModel) + + val expectedState = + createReduceBrightColorsTileState( + QSTileState.ActivationState.INACTIVE, + ) + QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) + } + + @Test + fun enabledModel() { + val inputModel = ReduceBrightColorsTileModel(true) + + val outputState = mapper.map(config, inputModel) + + val expectedState = createReduceBrightColorsTileState(QSTileState.ActivationState.ACTIVE) + QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) + } + + private fun createReduceBrightColorsTileState( + activationState: QSTileState.ActivationState, + ): QSTileState { + val label = + context.getString(com.android.internal.R.string.reduce_bright_colors_feature_name) + return QSTileState( + { + Icon.Loaded( + context.getDrawable( + if (activationState == QSTileState.ActivationState.ACTIVE) + R.drawable.qs_extra_dim_icon_on + else R.drawable.qs_extra_dim_icon_off + )!!, + null + ) + }, + label, + activationState, + context.resources + .getStringArray(R.array.tile_states_reduce_brightness)[ + if (activationState == QSTileState.ActivationState.ACTIVE) Tile.STATE_ACTIVE + else Tile.STATE_INACTIVE], + setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK), + label, + null, + QSTileState.SideViewIcon.None, + QSTileState.EnabledState.ENABLED, + Switch::class.qualifiedName + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt index 139289ae4299..3727c113a58e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt @@ -24,8 +24,8 @@ import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.flags.Flags +import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testScope import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel @@ -34,18 +34,8 @@ import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel -import com.android.systemui.shade.domain.interactor.privacyChipInteractor -import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor -import com.android.systemui.shade.domain.interactor.shadeInteractor -import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel +import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModel import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel -import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository -import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor -import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository -import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor -import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel -import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock @@ -64,8 +54,6 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) - private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) } private val qsFlexiglassAdapter = FakeQSSceneAdapter({ mock() }) private val footerActionsViewModel = mock<FooterActionsViewModel>() private val footerActionsViewModelFactory = @@ -74,45 +62,18 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { } private val footerActionsController = mock<FooterActionsController>() - private var mobileIconsViewModel: MobileIconsViewModel = - MobileIconsViewModel( - logger = mock(), - verboseLogger = mock(), - interactor = mobileIconsInteractor, - airplaneModeInteractor = - AirplaneModeInteractor( - FakeAirplaneModeRepository(), - FakeConnectivityRepository(), - FakeMobileConnectionsRepository(), - ), - constants = mock(), - flags, - scope = testScope.backgroundScope, - ) private val sceneInteractor = kosmos.sceneInteractor - private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel - private lateinit var underTest: QuickSettingsSceneViewModel @Before fun setUp() { - shadeHeaderViewModel = - ShadeHeaderViewModel( - applicationScope = testScope.backgroundScope, - context = context, - shadeInteractor = kosmos.shadeInteractor, - mobileIconsInteractor = mobileIconsInteractor, - mobileIconsViewModel = mobileIconsViewModel, - privacyChipInteractor = kosmos.privacyChipInteractor, - clockInteractor = kosmos.shadeHeaderClockInteractor, - broadcastDispatcher = fakeBroadcastDispatcher, - ) + kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false) underTest = QuickSettingsSceneViewModel( brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel, - shadeHeaderViewModel = shadeHeaderViewModel, + shadeHeaderViewModel = kosmos.shadeHeaderViewModel, qsSceneAdapter = qsFlexiglassAdapter, notifications = kosmos.notificationsPlaceholderViewModel, footerActionsViewModelFactory = footerActionsViewModelFactory, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index 9856f9050c4b..65fd1010ec38 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -51,6 +51,7 @@ import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepositor import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.domain.interactor.keyguardInteractor @@ -69,30 +70,22 @@ import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.domain.startable.SceneContainerStartable -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel -import com.android.systemui.shade.domain.interactor.privacyChipInteractor -import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor -import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel +import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModel import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel -import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository -import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository -import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor -import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel -import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor import com.android.systemui.telephony.data.repository.fakeTelephonyRepository import com.android.systemui.testKosmos +import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever @@ -136,9 +129,10 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) @RunWithLooper +@EnableSceneContainer class SceneFrameworkIntegrationTest : SysuiTestCase() { - private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true } + private val kosmos = testKosmos() private val testScope = kosmos.testScope private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig } private val sceneInteractor by lazy { kosmos.sceneInteractor } @@ -180,25 +174,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { ) } - private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) - - private var mobileIconsViewModel: MobileIconsViewModel = - MobileIconsViewModel( - logger = mock(), - verboseLogger = mock(), - interactor = mobileIconsInteractor, - airplaneModeInteractor = - AirplaneModeInteractor( - FakeAirplaneModeRepository(), - FakeConnectivityRepository(), - FakeMobileConnectionsRepository(), - ), - constants = mock(), - flags = kosmos.fakeFeatureFlagsClassic, - scope = testScope.backgroundScope, - ) - - private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel private lateinit var shadeSceneViewModel: ShadeSceneViewModel private val keyguardInteractor by lazy { kosmos.keyguardInteractor } @@ -241,23 +216,11 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { bouncerActionButtonInteractor = kosmos.bouncerActionButtonInteractor bouncerViewModel = kosmos.bouncerViewModel - shadeHeaderViewModel = - ShadeHeaderViewModel( - applicationScope = testScope.backgroundScope, - context = context, - shadeInteractor = kosmos.shadeInteractor, - mobileIconsInteractor = mobileIconsInteractor, - mobileIconsViewModel = mobileIconsViewModel, - privacyChipInteractor = kosmos.privacyChipInteractor, - clockInteractor = kosmos.shadeHeaderClockInteractor, - broadcastDispatcher = fakeBroadcastDispatcher, - ) - shadeSceneViewModel = ShadeSceneViewModel( applicationScope = testScope.backgroundScope, deviceEntryInteractor = deviceEntryInteractor, - shadeHeaderViewModel = shadeHeaderViewModel, + shadeHeaderViewModel = kosmos.shadeHeaderViewModel, qsSceneAdapter = qsFlexiglassAdapter, notifications = kosmos.notificationsPlaceholderViewModel, brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel, @@ -266,6 +229,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { footerActionsController = kosmos.footerActionsController, footerActionsViewModelFactory = kosmos.footerActionsViewModelFactory, sceneInteractor = sceneInteractor, + unfoldTransitionInteractor = kosmos.unfoldTransitionInteractor, ) val displayTracker = FakeDisplayTracker(context) @@ -275,15 +239,15 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { applicationScope = testScope.backgroundScope, sceneInteractor = sceneInteractor, deviceEntryInteractor = deviceEntryInteractor, + deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor, + bouncerInteractor = bouncerInteractor, keyguardInteractor = keyguardInteractor, - flags = kosmos.fakeSceneContainerFlags, sysUiState = sysUiState, displayId = displayTracker.defaultDisplayId, sceneLogger = mock(), falsingCollector = kosmos.falsingCollector, falsingManager = kosmos.falsingManager, powerInteractor = powerInteractor, - bouncerInteractor = bouncerInteractor, simBouncerInteractor = dagger.Lazy { kosmos.simBouncerInteractor }, authenticationInteractor = dagger.Lazy { kosmos.authenticationInteractor }, windowController = mock(), @@ -292,7 +256,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { headsUpInteractor = kosmos.headsUpNotificationInteractor, occlusionInteractor = kosmos.sceneContainerOcclusionInteractor, faceUnlockInteractor = kosmos.deviceEntryFaceAuthInteractor, - deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor, + shadeInteractor = kosmos.shadeInteractor, ) startable.start() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt index ae31058e7a54..8e2eea178708 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt @@ -23,10 +23,10 @@ import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.testScope import com.android.systemui.scene.sceneContainerConfig import com.android.systemui.scene.sceneKeys -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat @@ -39,10 +39,10 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) -@android.platform.test.annotations.EnabledOnRavenwood +@EnableSceneContainer class SceneContainerRepositoryTest : SysuiTestCase() { - private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true } + private val kosmos = testKosmos() private val testScope = kosmos.testScope @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt index b179c30e60b9..63f481695232 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt @@ -23,13 +23,13 @@ import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope import com.android.systemui.scene.data.repository.sceneContainerRepository import com.android.systemui.scene.sceneContainerConfig import com.android.systemui.scene.sceneKeys -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos @@ -45,6 +45,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class SceneInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() @@ -55,7 +56,6 @@ class SceneInteractorTest : SysuiTestCase() { @Before fun setUp() { - kosmos.fakeSceneContainerFlags.enabled = true underTest = kosmos.sceneInteractor } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt index d5e43f44426b..bfe5ef7acbce 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt @@ -31,7 +31,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.statusbar.NotificationPresenter import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs @@ -82,7 +81,6 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() { headsUpManager, powerInteractor, activeNotificationsInteractor, - kosmos.sceneContainerFlags, kosmos::sceneInteractor, ) .apply { setUp(notificationPresenter, notificationsController) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index 3fd5306abb71..1472a4d0a620 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -20,13 +20,11 @@ package com.android.systemui.scene.domain.startable import android.app.StatusBarManager import android.os.PowerManager -import android.platform.test.annotations.EnableFlags import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey -import com.android.systemui.Flags as AconfigFlags import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.domain.interactor.authenticationInteractor @@ -40,6 +38,7 @@ import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepositor import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository @@ -48,14 +47,16 @@ import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState +import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.PowerInteractorFactory +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource +import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor @@ -91,7 +92,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) -@EnableFlags(AconfigFlags.FLAG_SCENE_CONTAINER) +@EnableSceneContainer class SceneContainerStartableTest : SysuiTestCase() { @Mock private lateinit var windowController: NotificationShadeWindowController @@ -100,7 +101,6 @@ class SceneContainerStartableTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val sceneInteractor by lazy { kosmos.sceneInteractor } - private val sceneContainerFlags by lazy { kosmos.fakeSceneContainerFlags } private val authenticationInteractor by lazy { kosmos.authenticationInteractor } private val bouncerInteractor by lazy { kosmos.bouncerInteractor } private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository } @@ -122,15 +122,15 @@ class SceneContainerStartableTest : SysuiTestCase() { applicationScope = testScope.backgroundScope, sceneInteractor = sceneInteractor, deviceEntryInteractor = deviceEntryInteractor, + deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor, + bouncerInteractor = bouncerInteractor, keyguardInteractor = keyguardInteractor, - flags = sceneContainerFlags, sysUiState = sysUiState, displayId = Display.DEFAULT_DISPLAY, sceneLogger = mock(), falsingCollector = falsingCollector, falsingManager = kosmos.falsingManager, powerInteractor = powerInteractor, - bouncerInteractor = bouncerInteractor, simBouncerInteractor = { kosmos.simBouncerInteractor }, authenticationInteractor = { authenticationInteractor }, windowController = windowController, @@ -139,7 +139,7 @@ class SceneContainerStartableTest : SysuiTestCase() { headsUpInteractor = kosmos.headsUpNotificationInteractor, occlusionInteractor = kosmos.sceneContainerOcclusionInteractor, faceUnlockInteractor = kosmos.deviceEntryFaceAuthInteractor, - deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor, + shadeInteractor = kosmos.shadeInteractor, ) } @@ -287,6 +287,38 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + fun switchFromBouncerToQuickSettingsWhenDeviceUnlocked() = + testScope.runTest { + val currentSceneKey by collectLastValue(sceneInteractor.currentScene) + + val transitionState = + prepareState( + authenticationMethod = AuthenticationMethodModel.Pin, + isDeviceUnlocked = false, + initialSceneKey = Scenes.Lockscreen, + ) + assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) + underTest.start() + runCurrent() + + sceneInteractor.changeScene(Scenes.QuickSettings, "switching to qs for test") + transitionState.value = ObservableTransitionState.Idle(Scenes.QuickSettings) + runCurrent() + assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings) + + sceneInteractor.changeScene(Scenes.Bouncer, "switching to bouncer for test") + transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer) + runCurrent() + assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer) + + kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus( + SuccessFingerprintAuthenticationStatus(0, true) + ) + + assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings) + } + + @Test fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn() = testScope.runTest { val currentSceneKey by collectLastValue(sceneInteractor.currentScene) @@ -1127,6 +1159,33 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(kosmos.fakeDeviceEntryFaceAuthRepository.isAuthRunning.value).isTrue() } + @Test + fun switchToLockscreen_whenShadeBecomesNotTouchable() = + testScope.runTest { + val currentScene by collectLastValue(sceneInteractor.currentScene) + val isShadeTouchable by collectLastValue(kosmos.shadeInteractor.isShadeTouchable) + val transitionStateFlow = prepareState() + underTest.start() + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + // Flung to bouncer, 90% of the way there: + transitionStateFlow.value = + ObservableTransitionState.Transition( + fromScene = Scenes.Lockscreen, + toScene = Scenes.Bouncer, + progress = flowOf(0.9f), + isInitiatedByUserInput = true, + isUserInputOngoing = flowOf(false), + ) + runCurrent() + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + + kosmos.fakePowerRepository.updateWakefulness(WakefulnessState.ASLEEP) + runCurrent() + assertThat(isShadeTouchable).isFalse() + + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + } + private fun TestScope.emulateSceneTransition( transitionStateFlow: MutableStateFlow<ObservableTransitionState>, toScene: SceneKey, @@ -1166,6 +1225,7 @@ class SceneContainerStartableTest : SysuiTestCase() { isLockscreenEnabled: Boolean = true, startsAwake: Boolean = true, isDeviceProvisioned: Boolean = true, + isInteractive: Boolean = true, ): MutableStateFlow<ObservableTransitionState> { if (authenticationMethod?.isSecure == true) { assert(isLockscreenEnabled) { @@ -1182,7 +1242,6 @@ class SceneContainerStartableTest : SysuiTestCase() { "Cannot start on the Gone scene and have the device be locked at the same time." } - sceneContainerFlags.enabled = true kosmos.fakeDeviceEntryRepository.setBypassEnabled(isBypassEnabled) authenticationMethod?.let { kosmos.fakeAuthenticationRepository.setAuthenticationMethod(authenticationMethod) @@ -1205,6 +1264,7 @@ class SceneContainerStartableTest : SysuiTestCase() { } else { powerInteractor.setAsleepForTest() } + kosmos.fakePowerRepository.setInteractive(isInteractive) kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(isDeviceProvisioned) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt new file mode 100644 index 000000000000..db31ad52e3b0 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.scene.shared.flag + +import android.platform.test.flag.junit.FlagsParameterization +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN +import com.android.systemui.Flags.FLAG_EXAMPLE_FLAG +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER +import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.andSceneContainer +import com.google.common.truth.Truth +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +internal class SceneContainerFlagParameterizationTest : SysuiTestCase() { + + @Test + fun emptyAndSceneContainer() { + val result = FlagsParameterization.allCombinationsOf().andSceneContainer() + Truth.assertThat(result).hasSize(2) + Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse() + Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue() + } + + @Test + fun oneUnrelatedAndSceneContainer() { + val unrelatedFlag = FLAG_EXAMPLE_FLAG + val result = FlagsParameterization.allCombinationsOf(unrelatedFlag).andSceneContainer() + Truth.assertThat(result).hasSize(4) + Truth.assertThat(result[0].mOverrides[unrelatedFlag]).isFalse() + Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse() + Truth.assertThat(result[1].mOverrides[unrelatedFlag]).isFalse() + Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue() + Truth.assertThat(result[2].mOverrides[unrelatedFlag]).isTrue() + Truth.assertThat(result[2].mOverrides[FLAG_SCENE_CONTAINER]).isFalse() + Truth.assertThat(result[3].mOverrides[unrelatedFlag]).isTrue() + Truth.assertThat(result[3].mOverrides[FLAG_SCENE_CONTAINER]).isTrue() + } + + @Test + fun oneDependencyAndSceneContainer() { + val dependentFlag = FLAG_COMPOSE_LOCKSCREEN + val result = FlagsParameterization.allCombinationsOf(dependentFlag).andSceneContainer() + Truth.assertThat(result).hasSize(3) + Truth.assertThat(result[0].mOverrides[dependentFlag]).isFalse() + Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse() + Truth.assertThat(result[1].mOverrides[dependentFlag]).isTrue() + Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isFalse() + Truth.assertThat(result[2].mOverrides[dependentFlag]).isTrue() + Truth.assertThat(result[2].mOverrides[FLAG_SCENE_CONTAINER]).isTrue() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt index 543f6c91513e..ae5bf073a9f8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt @@ -16,11 +16,10 @@ package com.android.systemui.scene.shared.flag -import android.platform.test.annotations.DisableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.EnableSceneContainer import com.google.common.truth.Truth import org.junit.Test @@ -31,16 +30,14 @@ import org.junit.runner.RunWith internal class SceneContainerFlagsTest : SysuiTestCase() { @Test - @DisableFlags(FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun isNotEnabled_withoutAconfigFlags() { Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(false) - Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(false) } @Test @EnableSceneContainer fun isEnabled_withAconfigFlags() { Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(true) - Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(true) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt index 7b0127e94fb7..427b66bcff8a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt @@ -23,13 +23,13 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.classifier.fakeFalsingManager import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.testScope import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.sceneContainerConfig import com.android.systemui.scene.sceneKeys -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos @@ -45,6 +45,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class SceneContainerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() @@ -58,7 +59,6 @@ class SceneContainerViewModelTest : SysuiTestCase() { @Before fun setUp() { - kosmos.fakeSceneContainerFlags.enabled = true underTest = SceneContainerViewModel( sceneInteractor = sceneInteractor, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt index cbbcce96873b..420418b60d07 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt @@ -22,6 +22,7 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.systemui.SysuiTestCase import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository @@ -30,7 +31,6 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testCase import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor @@ -52,6 +52,7 @@ import org.mockito.Mockito.verify @ExperimentalCoroutinesApi @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class ShadeControllerSceneImplTest : SysuiTestCase() { private val kosmos = Kosmos() private val testScope = kosmos.testScope @@ -64,7 +65,6 @@ class ShadeControllerSceneImplTest : SysuiTestCase() { @Before fun setup() { kosmos.testCase = this - kosmos.fakeSceneContainerFlags.enabled = true kosmos.fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) set(Flags.NSSL_DEBUG_LINES, false) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt index e759b504d5c3..26f342aa05ce 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt @@ -22,9 +22,9 @@ import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shared.recents.utilities.Utilities import com.android.systemui.testKosmos @@ -43,8 +43,9 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @Ignore("b/328827631") +@EnableSceneContainer class ShadeBackActionInteractorImplTest : SysuiTestCase() { - val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true } + val kosmos = testKosmos() val testScope = kosmos.testScope val sceneInteractor = kosmos.sceneInteractor val underTest = kosmos.shadeBackActionInteractor diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt index 757a6c9e5ac6..5b33ecbb28be 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt @@ -641,7 +641,6 @@ class ShadeInteractorImplTest : SysuiTestCase() { ) ) val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) - runCurrent() assertThat(isShadeTouchable).isFalse() } @@ -668,13 +667,17 @@ class ShadeInteractorImplTest : SysuiTestCase() { ) ) val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) - runCurrent() assertThat(isShadeTouchable).isTrue() } @Test fun isShadeTouchable_isFalse_whenStartingToSleepAndNotControlScreenOff() = testScope.runTest { + whenever(dozeParameters.shouldControlScreenOff()).thenReturn(false) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + // Assert the default condition is true + assertThat(isShadeTouchable).isTrue() + powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -688,15 +691,17 @@ class ShadeInteractorImplTest : SysuiTestCase() { transitionState = TransitionState.STARTED, ) ) - whenever(dozeParameters.shouldControlScreenOff()).thenReturn(false) - val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) - runCurrent() assertThat(isShadeTouchable).isFalse() } @Test fun isShadeTouchable_isTrue_whenStartingToSleepAndControlScreenOff() = testScope.runTest { + whenever(dozeParameters.shouldControlScreenOff()).thenReturn(true) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + // Assert the default condition is true + assertThat(isShadeTouchable).isTrue() + powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -710,9 +715,6 @@ class ShadeInteractorImplTest : SysuiTestCase() { transitionState = TransitionState.STARTED, ) ) - whenever(dozeParameters.shouldControlScreenOff()).thenReturn(true) - val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) - runCurrent() assertThat(isShadeTouchable).isTrue() } @@ -730,7 +732,6 @@ class ShadeInteractorImplTest : SysuiTestCase() { ) ) val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) - runCurrent() assertThat(isShadeTouchable).isTrue() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt index 4c573d3b83ea..f89f18ac29f1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt @@ -2,29 +2,18 @@ package com.android.systemui.shade.ui.viewmodel import android.content.Intent import android.provider.AlarmClock +import android.provider.Settings import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.flags.FakeFeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.activityStarter -import com.android.systemui.shade.domain.interactor.privacyChipInteractor -import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor -import com.android.systemui.shade.domain.interactor.shadeInteractor -import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository -import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel -import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository -import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor -import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel -import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository +import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.argThat -import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Before @@ -40,43 +29,13 @@ import org.mockito.MockitoAnnotations class ShadeHeaderViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope + private val mobileIconsInteractor = kosmos.fakeMobileIconsInteractor - private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) - private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) } - - private var mobileIconsViewModel: MobileIconsViewModel = - MobileIconsViewModel( - logger = mock(), - verboseLogger = mock(), - interactor = mobileIconsInteractor, - airplaneModeInteractor = - AirplaneModeInteractor( - FakeAirplaneModeRepository(), - FakeConnectivityRepository(), - FakeMobileConnectionsRepository(), - ), - constants = mock(), - flags, - scope = testScope.backgroundScope, - ) - - private lateinit var underTest: ShadeHeaderViewModel + private val underTest: ShadeHeaderViewModel = kosmos.shadeHeaderViewModel @Before fun setUp() { MockitoAnnotations.initMocks(this) - - underTest = - ShadeHeaderViewModel( - applicationScope = testScope.backgroundScope, - context = context, - shadeInteractor = kosmos.shadeInteractor, - mobileIconsInteractor = mobileIconsInteractor, - mobileIconsViewModel = mobileIconsViewModel, - privacyChipInteractor = kosmos.privacyChipInteractor, - clockInteractor = kosmos.shadeHeaderClockInteractor, - broadcastDispatcher = fakeBroadcastDispatcher, - ) } @Test @@ -105,6 +64,19 @@ class ShadeHeaderViewModelTest : SysuiTestCase() { ) } + @Test + fun onShadeCarrierGroupClicked_launchesNetworkSettings() = + testScope.runTest { + val activityStarter = kosmos.activityStarter + underTest.onShadeCarrierGroupClicked() + + verify(activityStarter) + .postStartActivityDismissingKeyguard( + argThat(IntentMatcherAction(Settings.ACTION_WIRELESS_SETTINGS)), + anyInt(), + ) + } + companion object { private val SUB_1 = SubscriptionModel( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt index 7a681b383aad..2727af64733c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt @@ -27,8 +27,6 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor -import com.android.systemui.flags.FakeFeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope @@ -41,20 +39,13 @@ import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel import com.android.systemui.shade.data.repository.shadeRepository -import com.android.systemui.shade.domain.interactor.privacyChipInteractor -import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.domain.startable.shadeStartable import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel -import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository -import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor -import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository -import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor -import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel -import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.testKosmos +import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor +import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat @@ -79,29 +70,8 @@ class ShadeSceneViewModelTest : SysuiTestCase() { private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor } private val shadeRepository by lazy { kosmos.shadeRepository } - private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) - private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) } - - private var mobileIconsViewModel: MobileIconsViewModel = - MobileIconsViewModel( - logger = mock(), - verboseLogger = mock(), - interactor = mobileIconsInteractor, - airplaneModeInteractor = - AirplaneModeInteractor( - FakeAirplaneModeRepository(), - FakeConnectivityRepository(), - FakeMobileConnectionsRepository(), - ), - constants = mock(), - flags, - scope = testScope.backgroundScope, - ) - private val qsSceneAdapter = FakeQSSceneAdapter({ mock() }) - private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel - private lateinit var underTest: ShadeSceneViewModel @Mock private lateinit var mediaDataManager: MediaDataManager @@ -109,23 +79,12 @@ class ShadeSceneViewModelTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - shadeHeaderViewModel = - ShadeHeaderViewModel( - applicationScope = testScope.backgroundScope, - context = context, - shadeInteractor = kosmos.shadeInteractor, - mobileIconsInteractor = mobileIconsInteractor, - mobileIconsViewModel = mobileIconsViewModel, - privacyChipInteractor = kosmos.privacyChipInteractor, - clockInteractor = kosmos.shadeHeaderClockInteractor, - broadcastDispatcher = fakeBroadcastDispatcher, - ) underTest = ShadeSceneViewModel( applicationScope = testScope.backgroundScope, deviceEntryInteractor = deviceEntryInteractor, - shadeHeaderViewModel = shadeHeaderViewModel, + shadeHeaderViewModel = kosmos.shadeHeaderViewModel, qsSceneAdapter = qsSceneAdapter, notifications = kosmos.notificationsPlaceholderViewModel, brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel, @@ -134,6 +93,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() { footerActionsViewModelFactory = kosmos.footerActionsViewModelFactory, footerActionsController = kosmos.footerActionsController, sceneInteractor = kosmos.sceneInteractor, + unfoldTransitionInteractor = kosmos.unfoldTransitionInteractor, ) } @@ -297,4 +257,26 @@ class ShadeSceneViewModelTest : SysuiTestCase() { shadeRepository.setShadeMode(ShadeMode.Split) assertThat(shadeMode).isEqualTo(ShadeMode.Split) } + + @Test + fun unfoldTransitionProgress() = + testScope.runTest { + val unfoldProvider = kosmos.fakeUnfoldTransitionProgressProvider + val progress by collectLastValue(underTest.unfoldTransitionProgress) + + unfoldProvider.onTransitionStarted() + assertThat(progress).isEqualTo(1f) + + repeat(10) { repetition -> + val transitionProgress = 0.1f * (repetition + 1) + unfoldProvider.onTransitionProgress(transitionProgress) + assertThat(progress).isEqualTo(transitionProgress) + } + + unfoldProvider.onTransitionFinishing() + assertThat(progress).isEqualTo(1f) + + unfoldProvider.onTransitionFinished() + assertThat(progress).isEqualTo(1f) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt index a3cf92986bd6..01e1aa59912f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt @@ -23,11 +23,11 @@ import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds @@ -46,11 +46,11 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) +@EnableSceneContainer class NotificationStackAppearanceIntegrationTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - fakeSceneContainerFlags.enabled = true fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) set(Flags.NSSL_DEBUG_LINES, false) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index ac8387f28e6c..a023033e3aa3 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -20,17 +20,21 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.platform.test.annotations.DisableFlags -import androidx.test.ext.junit.runners.AndroidJUnit4 +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX +import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues +import com.android.systemui.flags.BrokenWithSceneContainer import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags +import com.android.systemui.flags.andSceneContainer import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository @@ -47,6 +51,7 @@ import com.android.systemui.keyguard.ui.viewmodel.aodBurnInViewModel import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel import com.android.systemui.kosmos.testScope import com.android.systemui.res.R +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.mockLargeScreenHeaderHelper import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor @@ -64,19 +69,36 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.mock +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters @SmallTest -@RunWith(AndroidJUnit4::class) -class SharedNotificationContainerViewModelTest : SysuiTestCase() { +@RunWith(ParameterizedAndroidJunit4::class) +// SharedNotificationContainerViewModel is only bound when FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT is on +@EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) +class SharedNotificationContainerViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() { + + companion object { + @JvmStatic + @Parameters(name = "{0}") + fun getParams(): List<FlagsParameterization> { + return FlagsParameterization.allCombinationsOf( + FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, + ) + .andSceneContainer() + } + } + + init { + mSetFlagsRule.setFlagsParameterization(flags!!) + } + val aodBurnInViewModel = mock(AodBurnInViewModel::class.java) lateinit var movementFlow: MutableStateFlow<BurnInModel> val kosmos = testKosmos().apply { - fakeFeatureFlagsClassic.apply { - set(Flags.FULL_SCREEN_USER_SWITCHER, false) - set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) - } + fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } init { @@ -84,19 +106,28 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } val testScope = kosmos.testScope - val configurationRepository = kosmos.fakeConfigurationRepository - val keyguardRepository = kosmos.fakeKeyguardRepository - val keyguardInteractor = kosmos.keyguardInteractor - val keyguardRootViewModel = kosmos.keyguardRootViewModel - val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - val shadeRepository = kosmos.shadeRepository - val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor - val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper + val configurationRepository + get() = kosmos.fakeConfigurationRepository + val keyguardRepository + get() = kosmos.fakeKeyguardRepository + val keyguardInteractor + get() = kosmos.keyguardInteractor + val keyguardRootViewModel + get() = kosmos.keyguardRootViewModel + val keyguardTransitionRepository + get() = kosmos.fakeKeyguardTransitionRepository + val shadeRepository + get() = kosmos.shadeRepository + val sharedNotificationContainerInteractor + get() = kosmos.sharedNotificationContainerInteractor + val largeScreenHeaderHelper + get() = kosmos.mockLargeScreenHeaderHelper lateinit var underTest: SharedNotificationContainerViewModel @Before fun setUp() { + assertThat(SceneContainerFlag.isEnabled).isEqualTo(SceneContainerFlag.isEnabled) overrideResource(R.bool.config_use_split_notification_shade, false) movementFlow = MutableStateFlow(BurnInModel()) whenever(aodBurnInViewModel.movement(any())).thenReturn(movementFlow) @@ -130,9 +161,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) fun validatePaddingTopInSplitShade_refactorFlagOff_usesLargeHeaderResource() = testScope.runTest { - mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5) overrideResource(R.bool.config_use_split_notification_shade, true) overrideResource(R.bool.config_use_large_screen_shade_header, true) @@ -148,9 +179,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) fun validatePaddingTopInSplitShade_refactorFlagOn_usesLargeHeaderHelper() = testScope.runTest { - mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5) overrideResource(R.bool.config_use_split_notification_shade, true) overrideResource(R.bool.config_use_large_screen_shade_header, true) @@ -243,9 +274,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test @DisableFlags(FLAG_SCENE_CONTAINER) + @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) fun validateMarginTopWithLargeScreenHeader_refactorFlagOn_usesHelper() = testScope.runTest { - mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) val headerResourceHeight = 50 val headerHelperHeight = 100 whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()) @@ -263,9 +294,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test @EnableSceneContainer + @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) fun validateMarginTopWithLargeScreenHeader_sceneContainerFlagOn_stillZero() = testScope.runTest { - mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) val headerResourceHeight = 50 val headerHelperHeight = 100 whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()) @@ -282,6 +313,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun glanceableHubAlpha_lockscreenToHub() = testScope.runTest { val alpha by collectLastValue(underTest.glanceableHubAlpha) @@ -431,6 +463,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun isOnLockscreenWithoutShade() = testScope.runTest { val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade) @@ -467,6 +500,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun isOnGlanceableHubWithoutShade() = testScope.runTest { val isOnGlanceableHubWithoutShade by @@ -503,6 +537,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun boundsOnLockscreenNotInSplitShade() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) @@ -523,9 +558,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, FLAG_SCENE_CONTAINER) fun boundsOnLockscreenInSplitShade_refactorFlagOff_usesLargeHeaderResource() = testScope.runTest { - mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) val bounds by collectLastValue(underTest.bounds) // When in split shade @@ -547,13 +582,20 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { runCurrent() // Top should be equal to bounds (1) - padding adjustment (10) - assertThat(bounds).isEqualTo(NotificationContainerBounds(top = -9f, bottom = 2f)) + assertThat(bounds) + .isEqualTo( + NotificationContainerBounds( + top = -9f, + bottom = 2f, + ) + ) } @Test + @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) + @DisableFlags(FLAG_SCENE_CONTAINER) fun boundsOnLockscreenInSplitShade_refactorFlagOn_usesLargeHeaderHelper() = testScope.runTest { - mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX) val bounds by collectLastValue(underTest.bounds) // When in split shade @@ -579,6 +621,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun boundsOnShade() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) @@ -594,6 +637,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun boundsOnQS() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) @@ -638,6 +682,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun maxNotificationsOnLockscreen_DoesNotUpdateWhenUserInteracting() = testScope.runTest { var notificationCount = 10 @@ -674,6 +719,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun maxNotificationsOnShade() = testScope.runTest { val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> 10 } @@ -693,6 +739,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun translationYUpdatesOnKeyguardForBurnIn() = testScope.runTest { val translationY by collectLastValue(underTest.translationY(BurnInParameters())) @@ -726,6 +773,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun translationYDoesNotUpdateWhenShadeIsExpanded() = testScope.runTest { val translationY by collectLastValue(underTest.translationY(BurnInParameters())) @@ -746,6 +794,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCENE_CONTAINER) fun updateBounds_fromKeyguardRoot() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) @@ -757,6 +806,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun alphaOnFullQsExpansion() = testScope.runTest { val viewState = ViewStateAccessor() @@ -864,6 +914,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + @BrokenWithSceneContainer(bugId = 333132830) fun shadeCollapseFadeIn() = testScope.runTest { val fadeIn by collectValues(underTest.shadeCollapseFadeIn) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt index c8062fb4e724..f0498ded64a5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt @@ -16,57 +16,20 @@ package com.android.systemui.statusbar.phone -import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent -import android.os.Bundle -import android.os.RemoteException -import android.os.UserHandle -import android.view.View -import android.widget.FrameLayout -import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.keyguard.KeyguardUpdateMonitor -import com.android.systemui.ActivityIntentHelper import com.android.systemui.SysuiTestCase -import com.android.systemui.animation.ActivityTransitionAnimator -import com.android.systemui.animation.LaunchableView -import com.android.systemui.assist.AssistManager -import com.android.systemui.keyguard.KeyguardViewMediator -import com.android.systemui.keyguard.WakefulnessLifecycle -import com.android.systemui.plugins.ActivityStarter.OnDismissAction -import com.android.systemui.settings.UserTracker -import com.android.systemui.shade.ShadeController -import com.android.systemui.shade.data.repository.FakeShadeRepository -import com.android.systemui.shade.data.repository.ShadeAnimationRepository -import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl -import com.android.systemui.statusbar.CommandQueue -import com.android.systemui.statusbar.NotificationLockscreenUserManager -import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.SysuiStatusBarStateController -import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow -import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.KeyguardStateController -import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.concurrency.FakeExecutor -import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.argumentCaptor -import com.android.systemui.util.mockito.eq -import com.android.systemui.util.mockito.nullable -import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat -import dagger.Lazy -import java.util.Optional import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock -import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.mock -import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -74,177 +37,22 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class ActivityStarterImplTest : SysuiTestCase() { - @Mock private lateinit var centralSurfaces: CentralSurfaces - @Mock private lateinit var assistManager: AssistManager - @Mock private lateinit var dozeServiceHost: DozeServiceHost - @Mock private lateinit var biometricUnlockController: BiometricUnlockController - @Mock private lateinit var keyguardViewMediator: KeyguardViewMediator - @Mock private lateinit var shadeController: ShadeController - @Mock private lateinit var commandQueue: CommandQueue - @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager - @Mock private lateinit var mActivityTransitionAnimator: ActivityTransitionAnimator - @Mock private lateinit var lockScreenUserManager: NotificationLockscreenUserManager - @Mock private lateinit var statusBarWindowController: StatusBarWindowController - @Mock private lateinit var notifShadeWindowController: NotificationShadeWindowController - @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle - @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var legacyActivityStarterInternal: LegacyActivityStarterInternalImpl + @Mock private lateinit var activityStarterInternal: ActivityStarterInternalImpl @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController - @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor - @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController - @Mock private lateinit var userTracker: UserTracker - @Mock private lateinit var activityIntentHelper: ActivityIntentHelper private lateinit var underTest: ActivityStarterImpl private val mainExecutor = FakeExecutor(FakeSystemClock()) - private val shadeAnimationInteractor = - ShadeAnimationInteractorLegacyImpl(ShadeAnimationRepository(), FakeShadeRepository()) @Before fun setUp() { MockitoAnnotations.initMocks(this) underTest = ActivityStarterImpl( - Lazy { Optional.of(centralSurfaces) }, - Lazy { assistManager }, - Lazy { dozeServiceHost }, - Lazy { biometricUnlockController }, - Lazy { keyguardViewMediator }, - Lazy { shadeController }, - commandQueue, - shadeAnimationInteractor, - Lazy { statusBarKeyguardViewManager }, - Lazy { notifShadeWindowController }, - mActivityTransitionAnimator, - context, - DISPLAY_ID, - lockScreenUserManager, - statusBarWindowController, - wakefulnessLifecycle, - keyguardStateController, - statusBarStateController, - keyguardUpdateMonitor, - deviceProvisionedController, - userTracker, - activityIntentHelper, - mainExecutor, + statusBarStateController = statusBarStateController, + mainExecutor = mainExecutor, + legacyActivityStarter = { legacyActivityStarterInternal }, + activityStarterInternal = { activityStarterInternal }, ) - whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER) - } - - @Test - fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() { - val pendingIntent = mock(PendingIntent::class.java) - whenever(pendingIntent.isActivity).thenReturn(true) - whenever(keyguardStateController.isShowing).thenReturn(true) - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) - - underTest.startPendingIntentDismissingKeyguard(pendingIntent) - mainExecutor.runAllReady() - - verify(statusBarKeyguardViewManager) - .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null)) - } - - @Test - fun startPendingIntentMaybeDismissingKeyguard_keyguardShowing_showOverLs_launchAnimator() { - val pendingIntent = mock(PendingIntent::class.java) - val parent = FrameLayout(context) - val view = - object : View(context), LaunchableView { - override fun setShouldBlockVisibilityChanges(block: Boolean) {} - } - parent.addView(view) - val controller = ActivityTransitionAnimator.Controller.fromView(view) - whenever(pendingIntent.isActivity).thenReturn(true) - whenever(keyguardStateController.isShowing).thenReturn(true) - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) - whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) - .thenReturn(true) - - underTest.startPendingIntentMaybeDismissingKeyguard( - intent = pendingIntent, - animationController = controller, - intentSentUiThreadCallback = null, - ) - mainExecutor.runAllReady() - - verify(mActivityTransitionAnimator) - .startPendingIntentWithAnimation( - nullable(), - eq(true), - nullable(), - eq(true), - any(), - ) - } - - fun startPendingIntentDismissingKeyguard_fillInIntentAndExtraOptions_sendAndReturnResult() { - val pendingIntent = mock(PendingIntent::class.java) - val fillInIntent = mock(Intent::class.java) - val parent = FrameLayout(context) - val view = - object : View(context), LaunchableView { - override fun setShouldBlockVisibilityChanges(block: Boolean) {} - } - parent.addView(view) - val controller = ActivityTransitionAnimator.Controller.fromView(view) - whenever(pendingIntent.isActivity).thenReturn(true) - whenever(keyguardStateController.isShowing).thenReturn(true) - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) - whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) - .thenReturn(false) - - // extra activity options to set on pending intent - val activityOptions = mock(ActivityOptions::class.java) - activityOptions.splashScreenStyle = SPLASH_SCREEN_STYLE_SOLID_COLOR - activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission = false - val bundleCaptor = argumentCaptor<Bundle>() - - underTest.startPendingIntentMaybeDismissingKeyguard( - intent = pendingIntent, - animationController = controller, - intentSentUiThreadCallback = null, - fillInIntent = fillInIntent, - extraOptions = activityOptions.toBundle(), - ) - mainExecutor.runAllReady() - - // Fill-in intent is passed and options contain extra values specified - verify(pendingIntent) - .sendAndReturnResult( - eq(context), - eq(0), - eq(fillInIntent), - nullable(), - nullable(), - nullable(), - bundleCaptor.capture() - ) - val options = ActivityOptions.fromBundle(bundleCaptor.value) - assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse() - assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR) - } - - @Test - fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() { - val pendingIntent = mock(PendingIntent::class.java) - val associatedView = mock(ExpandableNotificationRow::class.java) - - underTest.startPendingIntentDismissingKeyguard( - intent = pendingIntent, - intentSentUiThreadCallback = null, - associatedView = associatedView, - ) - - verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView) - } - - @Test - fun startActivity_noUserHandleProvided_getUserHandle() { - val intent = mock(Intent::class.java) - - underTest.startActivity(intent, false) - - verify(userTracker).userHandle } @Test @@ -258,115 +66,9 @@ class ActivityStarterImplTest : SysuiTestCase() { @Test fun postStartActivityDismissingKeyguard_intent_postsOnMain() { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) - val intent = mock(Intent::class.java) - - underTest.postStartActivityDismissingKeyguard(intent, 0) + underTest.postStartActivityDismissingKeyguard(mock(Intent::class.java), 0) assertThat(mainExecutor.numPending()).isEqualTo(1) - mainExecutor.runAllReady() - - verify(deviceProvisionedController).isDeviceProvisioned - verify(shadeController).collapseShadeForActivityStart() - } - - @Test - fun postStartActivityDismissingKeyguard_intent_notDeviceProvisioned_doesNotProceed() { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(false) - val intent = mock(Intent::class.java) - - underTest.postStartActivityDismissingKeyguard(intent, 0) - mainExecutor.runAllReady() - - verify(deviceProvisionedController).isDeviceProvisioned - verify(shadeController, never()).collapseShadeForActivityStart() - } - - @Test - fun dismissKeyguardThenExecute_startWakeAndUnlock() { - whenever(wakefulnessLifecycle.wakefulness) - .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) - whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true) - whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false) - whenever(dozeServiceHost.isPulsing).thenReturn(true) - - underTest.dismissKeyguardThenExecute({ true }, {}, false) - - verify(biometricUnlockController) - .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) - } - - @Test - fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() { - val customMessage = "Enter your pin." - whenever(keyguardStateController.isShowing).thenReturn(true) - - underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage) - - verify(statusBarKeyguardViewManager) - .dismissWithAction( - any(OnDismissAction::class.java), - any(Runnable::class.java), - eq(false), - eq(customMessage) - ) - } - - @Test - fun dismissKeyguardThenExecute_awakeDreams() { - val customMessage = "Enter your pin." - var dismissActionExecuted = false - whenever(keyguardStateController.isShowing).thenReturn(false) - whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) - - underTest.dismissKeyguardThenExecute( - { - dismissActionExecuted = true - true - }, - {}, - false, - customMessage - ) - - verify(centralSurfaces).awakenDreams() - assertThat(dismissActionExecuted).isTrue() - } - - @Test - @Throws(RemoteException::class) - fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() { - whenever(keyguardStateController.isShowing).thenReturn(false) - whenever(keyguardStateController.isOccluded).thenReturn(false) - whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) - - underTest.executeRunnableDismissingKeyguard( - runnable = {}, - cancelAction = null, - dismissShade = false, - afterKeyguardGone = false, - deferred = false - ) - - verify(centralSurfaces, times(1)).awakenDreams() - } - - @Test - @Throws(RemoteException::class) - fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() { - whenever(keyguardStateController.isShowing).thenReturn(false) - whenever(keyguardStateController.isOccluded).thenReturn(false) - whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false) - - underTest.executeRunnableDismissingKeyguard( - runnable = {}, - cancelAction = null, - dismissShade = false, - afterKeyguardGone = false, - deferred = false - ) - - verify(centralSurfaces, never()).awakenDreams() } @Test @@ -377,8 +79,4 @@ class ActivityStarterImplTest : SysuiTestCase() { mainExecutor.runAllReady() verify(statusBarStateController).setLeaveOpenOnKeyguardHide(true) } - - private companion object { - private const val DISPLAY_ID = 0 - } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt new file mode 100644 index 000000000000..b443489f98e2 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.app.ActivityOptions +import android.app.PendingIntent +import android.content.Intent +import android.os.Bundle +import android.os.RemoteException +import android.os.UserHandle +import android.view.View +import android.widget.FrameLayout +import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.ActivityIntentHelper +import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.animation.LaunchableView +import com.android.systemui.assist.AssistManager +import com.android.systemui.keyguard.KeyguardViewMediator +import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.plugins.ActivityStarter.OnDismissAction +import com.android.systemui.settings.UserTracker +import com.android.systemui.shade.ShadeController +import com.android.systemui.shade.data.repository.FakeShadeRepository +import com.android.systemui.shade.data.repository.ShadeAnimationRepository +import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl +import com.android.systemui.statusbar.CommandQueue +import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.NotificationShadeWindowController +import com.android.systemui.statusbar.SysuiStatusBarStateController +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.statusbar.window.StatusBarWindowController +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.nullable +import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat +import java.util.Optional +import kotlinx.coroutines.ExperimentalCoroutinesApi +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.anyBoolean +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +class LegacyActivityStarterInternalImplTest : SysuiTestCase() { + @Mock private lateinit var centralSurfaces: CentralSurfaces + @Mock private lateinit var assistManager: AssistManager + @Mock private lateinit var dozeServiceHost: DozeServiceHost + @Mock private lateinit var biometricUnlockController: BiometricUnlockController + @Mock private lateinit var keyguardViewMediator: KeyguardViewMediator + @Mock private lateinit var shadeController: ShadeController + @Mock private lateinit var commandQueue: CommandQueue + @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager + @Mock private lateinit var activityTransitionAnimator: ActivityTransitionAnimator + @Mock private lateinit var lockScreenUserManager: NotificationLockscreenUserManager + @Mock private lateinit var statusBarWindowController: StatusBarWindowController + @Mock private lateinit var notifShadeWindowController: NotificationShadeWindowController + @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle + @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController + @Mock private lateinit var userTracker: UserTracker + @Mock private lateinit var activityIntentHelper: ActivityIntentHelper + private lateinit var underTest: LegacyActivityStarterInternalImpl + private val mainExecutor = FakeExecutor(FakeSystemClock()) + private val shadeAnimationInteractor = + ShadeAnimationInteractorLegacyImpl(ShadeAnimationRepository(), FakeShadeRepository()) + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + underTest = + LegacyActivityStarterInternalImpl( + centralSurfacesOptLazy = { Optional.of(centralSurfaces) }, + assistManagerLazy = { assistManager }, + dozeServiceHostLazy = { dozeServiceHost }, + biometricUnlockControllerLazy = { biometricUnlockController }, + keyguardViewMediatorLazy = { keyguardViewMediator }, + shadeControllerLazy = { shadeController }, + commandQueue = commandQueue, + shadeAnimationInteractor = shadeAnimationInteractor, + statusBarKeyguardViewManagerLazy = { statusBarKeyguardViewManager }, + notifShadeWindowControllerLazy = { notifShadeWindowController }, + activityTransitionAnimator = activityTransitionAnimator, + context = context, + displayId = DISPLAY_ID, + lockScreenUserManager = lockScreenUserManager, + statusBarWindowController = statusBarWindowController, + wakefulnessLifecycle = wakefulnessLifecycle, + keyguardStateController = keyguardStateController, + statusBarStateController = statusBarStateController, + keyguardUpdateMonitor = keyguardUpdateMonitor, + deviceProvisionedController = deviceProvisionedController, + userTracker = userTracker, + activityIntentHelper = activityIntentHelper, + mainExecutor = mainExecutor, + ) + whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER) + } + + @Test + fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() { + val pendingIntent = mock(PendingIntent::class.java) + whenever(pendingIntent.isActivity).thenReturn(true) + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + + underTest.startPendingIntentDismissingKeyguard(pendingIntent) + mainExecutor.runAllReady() + + verify(statusBarKeyguardViewManager) + .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null)) + } + + @Test + fun startPendingIntentMaybeDismissingKeyguard_keyguardShowing_showOverLs_launchAnimator() { + val pendingIntent = mock(PendingIntent::class.java) + val parent = FrameLayout(context) + val view = + object : View(context), LaunchableView { + override fun setShouldBlockVisibilityChanges(block: Boolean) {} + } + parent.addView(view) + val controller = ActivityTransitionAnimator.Controller.fromView(view) + whenever(pendingIntent.isActivity).thenReturn(true) + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) + .thenReturn(true) + + startPendingIntentMaybeDismissingKeyguard( + intent = pendingIntent, + animationController = controller, + intentSentUiThreadCallback = null, + ) + mainExecutor.runAllReady() + + verify(activityTransitionAnimator) + .startPendingIntentWithAnimation( + nullable(), + eq(true), + nullable(), + eq(true), + any(), + ) + } + + fun startPendingIntentDismissingKeyguard_fillInIntentAndExtraOptions_sendAndReturnResult() { + val pendingIntent = mock(PendingIntent::class.java) + val fillInIntent = mock(Intent::class.java) + val parent = FrameLayout(context) + val view = + object : View(context), LaunchableView { + override fun setShouldBlockVisibilityChanges(block: Boolean) {} + } + parent.addView(view) + val controller = ActivityTransitionAnimator.Controller.fromView(view) + whenever(pendingIntent.isActivity).thenReturn(true) + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) + .thenReturn(false) + + // extra activity options to set on pending intent + val activityOptions = mock(ActivityOptions::class.java) + activityOptions.splashScreenStyle = SPLASH_SCREEN_STYLE_SOLID_COLOR + activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission = false + val bundleCaptor = argumentCaptor<Bundle>() + + startPendingIntentMaybeDismissingKeyguard( + intent = pendingIntent, + animationController = controller, + intentSentUiThreadCallback = null, + fillInIntent = fillInIntent, + extraOptions = activityOptions.toBundle(), + ) + mainExecutor.runAllReady() + + // Fill-in intent is passed and options contain extra values specified + verify(pendingIntent) + .sendAndReturnResult( + eq(context), + eq(0), + eq(fillInIntent), + nullable(), + nullable(), + nullable(), + bundleCaptor.capture() + ) + val options = ActivityOptions.fromBundle(bundleCaptor.value) + assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse() + assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR) + } + + @Test + fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() { + val pendingIntent = mock(PendingIntent::class.java) + val associatedView = mock(ExpandableNotificationRow::class.java) + + underTest.startPendingIntentDismissingKeyguard( + intent = pendingIntent, + intentSentUiThreadCallback = null, + associatedView = associatedView, + ) + + verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView) + } + + @Test + fun startActivity_noUserHandleProvided_getUserHandle() { + val intent = mock(Intent::class.java) + + underTest.startActivity(intent, false, null, false, null) + + verify(userTracker).userHandle + } + + @Test + fun dismissKeyguardThenExecute_startWakeAndUnlock() { + whenever(wakefulnessLifecycle.wakefulness) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) + whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true) + whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false) + whenever(dozeServiceHost.isPulsing).thenReturn(true) + + underTest.dismissKeyguardThenExecute({ true }, {}, false) + + verify(biometricUnlockController) + .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) + } + + @Test + fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() { + val customMessage = "Enter your pin." + whenever(keyguardStateController.isShowing).thenReturn(true) + + underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage) + + verify(statusBarKeyguardViewManager) + .dismissWithAction( + any(OnDismissAction::class.java), + any(Runnable::class.java), + eq(false), + eq(customMessage) + ) + } + + @Test + fun dismissKeyguardThenExecute_awakeDreams() { + val customMessage = "Enter your pin." + var dismissActionExecuted = false + whenever(keyguardStateController.isShowing).thenReturn(false) + whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) + + underTest.dismissKeyguardThenExecute( + { + dismissActionExecuted = true + true + }, + {}, + false, + customMessage + ) + + verify(centralSurfaces).awakenDreams() + assertThat(dismissActionExecuted).isTrue() + } + + @Test + @Throws(RemoteException::class) + fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() { + whenever(keyguardStateController.isShowing).thenReturn(false) + whenever(keyguardStateController.isOccluded).thenReturn(false) + whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) + + underTest.executeRunnableDismissingKeyguard( + runnable = {}, + cancelAction = null, + dismissShade = false, + afterKeyguardGone = false, + deferred = false + ) + + verify(centralSurfaces, times(1)).awakenDreams() + } + + @Test + @Throws(RemoteException::class) + fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() { + whenever(keyguardStateController.isShowing).thenReturn(false) + whenever(keyguardStateController.isOccluded).thenReturn(false) + whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false) + + underTest.executeRunnableDismissingKeyguard( + runnable = {}, + cancelAction = null, + dismissShade = false, + afterKeyguardGone = false, + deferred = false + ) + + verify(centralSurfaces, never()).awakenDreams() + } + + private fun startPendingIntentMaybeDismissingKeyguard( + intent: PendingIntent, + intentSentUiThreadCallback: Runnable?, + animationController: ActivityTransitionAnimator.Controller?, + fillInIntent: Intent? = null, + extraOptions: Bundle? = null, + ) { + underTest.startPendingIntentDismissingKeyguard( + intent = intent, + intentSentUiThreadCallback = intentSentUiThreadCallback, + animationController = animationController, + showOverLockscreen = true, + fillInIntent = fillInIntent, + extraOptions = extraOptions, + ) + } + + private companion object { + private const val DISPLAY_ID = 0 + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java index 3c9dc6345d31..69207ba07e6e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java @@ -89,7 +89,7 @@ class TestableHeadsUpManager extends BaseHeadsUpManager { } @Override - public boolean isHeadsUpGoingAway() { + public boolean isHeadsUpAnimatingAwayValue() { throw new UnsupportedOperationException(); } @@ -115,7 +115,7 @@ class TestableHeadsUpManager extends BaseHeadsUpManager { } @Override - public void setHeadsUpGoingAway(boolean headsUpGoingAway) { + public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) { throw new UnsupportedOperationException(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt index 6a801e01a4a5..3b4cce448da9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt @@ -15,42 +15,31 @@ */ package com.android.systemui.unfold.domain.interactor -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider -import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider import com.google.common.truth.Truth.assertThat -import java.util.Optional import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(AndroidTestingRunner::class) -open class UnfoldTransitionInteractorTest : SysuiTestCase() { +@RunWith(AndroidJUnit4::class) +class UnfoldTransitionInteractorTest : SysuiTestCase() { - private val testScope = TestScope() + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val unfoldTransitionProgressProvider = kosmos.fakeUnfoldTransitionProgressProvider - private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider() - private val unfoldTransitionRepository = - UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider)) - - private lateinit var underTest: UnfoldTransitionInteractor - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - - underTest = UnfoldTransitionInteractorImpl(unfoldTransitionRepository) - } + private val underTest: UnfoldTransitionInteractor = kosmos.unfoldTransitionInteractor @Test fun waitForTransitionFinish_noEvents_doesNotComplete() = @@ -88,4 +77,26 @@ open class UnfoldTransitionInteractorTest : SysuiTestCase() { assertThat(deferred.isCompleted).isFalse() deferred.cancel() } + + @Test + fun unfoldProgress() = + testScope.runTest { + val progress by collectLastValue(underTest.unfoldProgress) + runCurrent() + + unfoldTransitionProgressProvider.onTransitionStarted() + assertThat(progress).isEqualTo(1f) + + repeat(10) { repetition -> + val transitionProgress = 0.1f * (repetition + 1) + unfoldTransitionProgressProvider.onTransitionProgress(transitionProgress) + assertThat(progress).isEqualTo(transitionProgress) + } + + unfoldTransitionProgressProvider.onTransitionFinishing() + assertThat(progress).isEqualTo(1f) + + unfoldTransitionProgressProvider.onTransitionFinished() + assertThat(progress).isEqualTo(1f) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt new file mode 100644 index 000000000000..8bb36724d1d8 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.domain.startable + +import android.media.AudioManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.internal.logging.uiEventLogger +import com.android.internal.logging.uiEventLoggerFake +import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.android.systemui.volume.audioModeInteractor +import com.android.systemui.volume.audioRepository +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule + +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +@SmallTest +class AudioModeLoggerStartableTest : SysuiTestCase() { + @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() + + private val kosmos = testKosmos() + + private lateinit var underTest: AudioModeLoggerStartable + + @Before + fun setUp() { + with(kosmos) { + underTest = + AudioModeLoggerStartable( + applicationCoroutineScope, + uiEventLogger, + audioModeInteractor + ) + } + } + + @Test + fun audioMode_inCall() { + with(kosmos) { + testScope.runTest { + audioRepository.setMode(AudioManager.MODE_IN_CALL) + + underTest.start() + runCurrent() + + assertThat(uiEventLoggerFake.eventId(0)) + .isEqualTo(VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_CALLING.id) + } + } + } + + @Test + fun audioMode_notInCall() { + with(kosmos) { + testScope.runTest { + audioRepository.setMode(AudioManager.MODE_NORMAL) + + underTest.start() + runCurrent() + + assertThat(uiEventLoggerFake.eventId(0)) + .isEqualTo(VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_NORMAL.id) + } + } + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt index e31cdcd82e7e..dc9613904e4e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt @@ -72,7 +72,7 @@ class AncSliceRepositoryTest : SysuiTestCase() { testScope.runTest { localMediaRepository.updateCurrentConnectedDevice(null) - val slice by collectLastValue(underTest.ancSlice(1)) + val slice by collectLastValue(underTest.ancSlice(1, false, false)) runCurrent() assertThat(slice).isNull() @@ -86,7 +86,7 @@ class AncSliceRepositoryTest : SysuiTestCase() { testScope.runTest { localMediaRepository.updateCurrentConnectedDevice(createMediaDevice()) - val slice by collectLastValue(underTest.ancSlice(1)) + val slice by collectLastValue(underTest.ancSlice(1, false, false)) runCurrent() assertThat(slice).isNotNull() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt index 53f0bc9ddb51..81e6ac412404 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt @@ -24,6 +24,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.volume.panel.component.anc.FakeSliceFactory import com.android.systemui.volume.panel.component.anc.ancSliceRepository +import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent @@ -57,10 +58,10 @@ class AncSliceInteractorTest : SysuiTestCase() { FakeSliceFactory.createSlice(hasError = true, hasSliceItem = true) ) - val slice by collectLastValue(underTest.ancSlice) + val slice by collectLastValue(underTest.ancSlices) runCurrent() - assertThat(slice).isNull() + assertThat(slice).isInstanceOf(AncSlices.Unavailable::class.java) } } } @@ -74,10 +75,10 @@ class AncSliceInteractorTest : SysuiTestCase() { FakeSliceFactory.createSlice(hasError = false, hasSliceItem = false) ) - val slice by collectLastValue(underTest.ancSlice) + val slice by collectLastValue(underTest.ancSlices) runCurrent() - assertThat(slice).isNull() + assertThat(slice).isInstanceOf(AncSlices.Unavailable::class.java) } } } @@ -91,10 +92,10 @@ class AncSliceInteractorTest : SysuiTestCase() { FakeSliceFactory.createSlice(hasError = false, hasSliceItem = true) ) - val slice by collectLastValue(underTest.ancSlice) + val slice by collectLastValue(underTest.ancSlices) runCurrent() - assertThat(slice).isNotNull() + assertThat(slice).isInstanceOf(AncSlices.Ready::class.java) } } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt index 2cc1ad335535..27a813fb149e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt @@ -21,6 +21,8 @@ import android.content.Intent import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.internal.logging.uiEventLogger +import com.android.internal.logging.uiEventLoggerFake import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope @@ -29,6 +31,7 @@ import com.android.systemui.plugins.activityStarter import com.android.systemui.testKosmos import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import com.android.systemui.volume.panel.volumePanelViewModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -58,7 +61,10 @@ class BottomBarViewModelTest : SysuiTestCase() { private lateinit var underTest: BottomBarViewModel private fun initUnderTest() { - underTest = with(kosmos) { BottomBarViewModel(activityStarter, volumePanelViewModel) } + underTest = + with(kosmos) { + BottomBarViewModel(activityStarter, volumePanelViewModel, uiEventLogger) + } } @Test @@ -96,6 +102,8 @@ class BottomBarViewModelTest : SysuiTestCase() { /* userHandle = */ eq(null), ) assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_SOUND_SETTINGS) + assertThat(uiEventLoggerFake.eventId(0)) + .isEqualTo(VolumePanelUiEvent.VOLUME_PANEL_SOUND_SETTINGS_CLICKED.id) activityStartedCaptor.value.onActivityStarted(ActivityManager.START_SUCCESS) val volumePanelState by collectLastValue(volumePanelViewModel.volumePanelState) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt index 610195f5e87e..fdeded8422d6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.volume.panel.component.captioning.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.internal.logging.uiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope @@ -45,7 +46,12 @@ class CaptioningViewModelTest : SysuiTestCase() { fun setup() { underTest = with(kosmos) { - CaptioningViewModel(context, captioningInteractor, testScope.backgroundScope) + CaptioningViewModel( + context, + captioningInteractor, + testScope.backgroundScope, + uiEventLogger, + ) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt index ec55c75d4ae5..da0a2295143b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt @@ -46,7 +46,10 @@ class MediaOutputAvailabilityCriteriaTest : SysuiTestCase() { @Before fun setup() { - underTest = MediaOutputAvailabilityCriteria(kosmos.audioModeInteractor) + underTest = + MediaOutputAvailabilityCriteria( + kosmos.audioModeInteractor, + ) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt index 462f36d73138..30524d93dc02 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt @@ -22,6 +22,7 @@ import android.media.session.PlaybackState import android.testing.TestableLooper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.internal.logging.uiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope @@ -64,6 +65,7 @@ class MediaOutputViewModelTest : SysuiTestCase() { mediaOutputActionsInteractor, mediaDeviceSessionInteractor, mediaOutputInteractor, + uiEventLogger, ) with(context.orCreateTestableResources) { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt deleted file mode 100644 index 79d3fe9063b7..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.volume.panel.component.volume.domain.interactor - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.google.common.truth.Truth.assertThat -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class VolumeSliderInteractorTest : SysuiTestCase() { - - private val underTest = VolumeSliderInteractor() - - @Test - fun processVolumeToValue_returnsTranslatedVolume() { - assertThat(underTest.processVolumeToValue(2, volumeRange)).isEqualTo(20f) - } - - private companion object { - val volumeRange = 0..10 - } -} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt index 8e2bd9b2562b..79bf5f19997b 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt @@ -267,6 +267,9 @@ data class ClockConfig( /** True if the clock will react to tone changes in the seed color. */ val isReactiveToTone: Boolean = true, + + /** True if the clock is large frame clock, which will use weather in compose. */ + val useCustomClockScene: Boolean = false, ) /** Render configuration options for a clock face. Modifies the way SystemUI behaves. */ @@ -283,6 +286,9 @@ data class ClockFaceConfig( * animation will be used (e.g. a simple translation). */ val hasCustomPositionUpdatedAnimation: Boolean = false, + + /** True if the clock is large frame clock, which will use weatherBlueprint in compose. */ + val useCustomClockScene: Boolean = false, ) /** Structure for keeping clock-specific settings */ diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index 529d6090a501..b62e684b0105 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"መሣሪያ እንደገና ከጀመረ በኋላ ስርዓተ ጥለት ያስፈልጋል"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"መሣሪያ እንደገና ከጀመረ በኋላ ፒን ያስፈልጋል"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"መሣሪያ እንደገና ከጀመረ በኋላ የይለፍ ቃል ያስፈልጋል"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ለተጨማሪ ደህንነት በምትኩ ስርዓተ ጥለት ይጠቀሙ"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ለተጨማሪ ደህንነት በምትኩ ሥርዓተ ጥለት ይጠቀሙ"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ለተጨማሪ ደህንነት በምትኩ ፒን ይጠቀሙ"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ለተጨማሪ ደህንነት በምትኩ የይለፍ ቃል ይጠቀሙ"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"ፒን ለተጨማሪ ደህንነት ያስፈልጋል"</string> diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index d07c5b560d44..427373de8bcc 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -21,13 +21,13 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"أدخل رقم التعريف الشخصي (PIN)"</string> - <string name="keyguard_enter_pin" msgid="8114529922480276834">"أدخِل رقم التعريف الشخصي."</string> + <string name="keyguard_enter_pin" msgid="8114529922480276834">"أدخِل رقم التعريف الشخصي"</string> <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"أدخل النقش"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ارسم النقش."</string> <string name="keyguard_enter_your_password" msgid="7225626204122735501">"أدخل كلمة المرور"</string> <string name="keyguard_enter_password" msgid="6483623792371009758">"أدخِل كلمة المرور."</string> <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"بطاقة غير صالحة."</string> - <string name="keyguard_charged" msgid="5478247181205188995">"تم الشحن"</string> + <string name="keyguard_charged" msgid="5478247181205188995">"اكتمل الشحن"</string> <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن لاسلكيًا"</string> <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string> <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string> @@ -80,9 +80,9 @@ <string name="kg_face_locked_out" msgid="2751559491287575">"يتعذّر فتح القفل بالوجه. أجريت محاولات كثيرة جدًا."</string> <string name="kg_fp_locked_out" msgid="6228277682396768830">"يتعذّر الفتح ببصمة الإصبع. أجريت محاولات كثيرة جدًا."</string> <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"ميزة \"الوكيل المعتمد\" غير متاحة."</string> - <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"أجريت محاولات كثيرة جدًا بإدخال رقم تعريف شخصي خاطئ."</string> - <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"أجريت محاولات كثيرة جدًا برسم نقش خاطئ."</string> - <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"أجريت محاولات كثيرة جدًا بإدخال كلمة مرور خاطئة."</string> + <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"أجريت محاولات كثيرة جدًا باستخدام رقم تعريف شخصي خاطئ"</string> + <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"أجريت محاولات كثيرة جدًا باستخدام نقش خاطئ"</string> + <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"أجريت محاولات كثيرة جدًا باستخدام كلمة مرور خاطئة"</string> <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{أعِد المحاولة خلال ثانية واحدة.}zero{أعِد المحاولة خلال # ثانية.}two{أعِد المحاولة خلال ثانيتين.}few{أعِد المحاولة خلال # ثوانٍ.}many{أعِد المحاولة خلال # ثانية.}other{أعِد المحاولة خلال # ثانية.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"أدخل رقم التعريف الشخصي لشريحة SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"أدخل رقم التعريف الشخصي لشريحة SIM التابعة للمشغّل \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"يجب رسم النقش بعد إعادة تشغيل الجهاز."</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز."</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"يجب إدخال كلمة المرور بعد إعادة تشغيل الجهاز."</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"لمزيد من الأمان، استخدِم النقش بدلاً من ذلك."</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"لمزيد من الأمان، أدخِل رقم التعريف الشخصي بدلاً من ذلك."</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"لمزيد من الأمان، أدخِل كلمة المرور بدلاً من ذلك."</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"لمزيد من الأمان، يجب استخدام النقش"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"لمزيد من الأمان، يجب إدخال رقم التعريف الشخصي"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"لمزيد من الأمان، يجب إدخال كلمة المرور"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"يجب إدخال رقم التعريف الشخصي لمزيد من الأمان"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"يجب رسم النقش لمزيد من الأمان"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"يجب إدخال كلمة المرور لمزيد من الأمان"</string> diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml index ce8ebd3bf9e7..4ed7e27ff732 100644 --- a/packages/SystemUI/res-keyguard/values-as/strings.xml +++ b/packages/SystemUI/res-keyguard/values-as/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত আৰ্হিৰ আৱশ্যক"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পিনৰ আৱশ্যক"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পাছৱৰ্ডৰ আৱশ্যক"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"অতিৰিক্ত সুৰক্ষাৰ বাবে, ইয়াৰ পৰিৱৰ্তে আৰ্হি ব্যৱহাৰ কৰক"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"অতিৰিক্ত সুৰক্ষাৰ বাবে, আৰ্হি ব্যৱহাৰ কৰক"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"অতিৰিক্ত সুৰক্ষাৰ বাবে, ইয়াৰ পৰিৱৰ্তে পিন ব্যৱহাৰ কৰক"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"অতিৰিক্ত সুৰক্ষাৰ বাবে, ইয়াৰ পৰিৱৰ্তে পাছৱৰ্ড ব্যৱহাৰ কৰক"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"অতিৰিক্ত সুৰক্ষাৰ বাবে পিন দিয়াটো বাধ্যতামূলক"</string> diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index 96779450d55e..4a5e789cab8a 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Uzorak je potreban nakon ponovnog pokretanja uređaja"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN je potreban nakon ponovnog pokretanja uređaja"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Lozinka je potrebna nakon pokretanja uređaja"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Radi dodatne zaštite, umjesto toga koristite uzorak"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Radi dodatne zaštite, umjesto toga koristite PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Radi dodatne zašitite, umjesto toga koristite lozinku"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Za dodatnu sigurnost koristite uzorak"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Za dodatnu sigurnost koristite PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Za dodatnu sigurnost koristite lozinku"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN je potreban radi dodatne sigurnosti"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Uzorak je potreban radi dodatne sigurnosti"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Lozinka je potrebna radi dodatne sigurnosti"</string> diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index 8e97e84340d8..5a03cec97ce8 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -83,7 +83,7 @@ <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Příliš mnoho pokusů s nesprávným kódem PIN"</string> <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Příliš mnoho pokusů s nesprávným gestem"</string> <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Příliš mnoho pokusů s nesprávným heslem"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Zkuste to znovu za # sekundu.}few{Zkuste to znovu za # sekundy.}many{Zkuste to znovu za # sekundy.}other{Zkuste to znovu za # sekund.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Zkuste to znovu za # sekundu}few{Zkuste to znovu za # sekundy}many{Zkuste to znovu za # sekundy}other{Zkuste to znovu za # sekund}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Zadejte kód PIN SIM karty."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Zadejte kód PIN SIM karty <xliff:g id="CARRIER">%1$s</xliff:g>."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> eSIM kartu deaktivujte, chcete-li zařízení používat bez mobilních služeb."</string> diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml index 2245710a0a5e..195fdeff3275 100644 --- a/packages/SystemUI/res-keyguard/values-de/strings.xml +++ b/packages/SystemUI/res-keyguard/values-de/strings.xml @@ -20,7 +20,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Gib deine PIN ein"</string> + <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN eingeben"</string> <string name="keyguard_enter_pin" msgid="8114529922480276834">"Gib die PIN ein"</string> <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Muster eingeben"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Zeichne das Muster"</string> diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index ea1dd13c6848..c59bdc1604d5 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Kuvio tarvitaan uudelleenkäynnistyksen jälkeen"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN-koodi tarvitaan uudelleenkäynnistyksen jälkeen"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Salasana tarvitaan uudelleenkäynnistyksen jälkeen"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Lisäsuojaa saat, kun käytät sen sijaan kuviota"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Lisäsuojaa saat, kun käytät sen sijaan PIN-koodia"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Lisäsuojaa saat, kun käytät sen sijaan salasanaa"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Käytä kuviota, niin saat lisäsuojaa"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Käytä PIN-koodia, niin saat lisäsuojaa"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Käytä salasanaa, niin saat lisäsuojaa"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN-koodi vaaditaan suojauksen parantamiseksi."</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Kuvio vaaditaan suojauksen parantamiseksi."</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Salasana vaaditaan suojauksen parantamiseksi."</string> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 6b51ac26cd52..e5cd788200a9 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Requírese o padrón tras reiniciar o dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Requírese o PIN tras reiniciar o dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Requírese o contrasinal tras reiniciar o dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Utiliza un padrón para obter maior seguranza"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Utiliza un padrón para unha maior seguranza"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Utiliza un PIN para obter maior seguranza"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Utiliza un contrasinal para obter maior seguranza"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Utiliza un contrasinal para unha maior seguranza"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"É necesario poñer o PIN como medida de seguranza adicional"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"É necesario poñer o padrón como medida de seguranza adicional"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"É necesario poñer o contrasinal como medida de seguranza adicional"</string> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index dc5b0b8c8077..e2ac8b65288f 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -80,10 +80,10 @@ <string name="kg_face_locked_out" msgid="2751559491287575">"Tidak dapat membuka kunci dengan wajah. Terlalu banyak upaya gagal."</string> <string name="kg_fp_locked_out" msgid="6228277682396768830">"Tidak dapat membuka kunci dengan sidik jari. Terlalu banyak upaya gagal."</string> <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"Perangkat tepercaya tidak tersedia"</string> - <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Terlalu banyak upaya dengan PIN yang salah"</string> - <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Terlalu banyak upaya dengan pola yang salah"</string> - <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Terlalu banyak upaya dengan sandi yang salah"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Coba lagi dalam # detik.}other{Coba lagi dalam # detik.}}"</string> + <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Terlalu banyak pemakaian PIN yang salah"</string> + <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Terlalu banyak pemakaian pola yang salah"</string> + <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Terlalu banyak pemakaian sandi yang salah"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Coba lagi setelah # detik.}other{Coba lagi setelah # detik.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Masukkan PIN SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Masukkan PIN SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Nonaktifkan eSIM untuk menggunakan perangkat tanpa layanan seluler."</string> @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Pola diperlukan setelah perangkat dimulai ulang"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN diperlukan setelah perangkat dimulai ulang"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Sandi diperlukan setelah perangkat dimulai ulang"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Untuk keamanan tambahan, gunakan pola"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Untuk keamanan tambahan, gunakan PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Untuk keamanan tambahan, gunakan sandi"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Agar lebih aman, gunakan pola"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Agar lebih aman, gunakan PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Agar lebih aman, gunakan sandi"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN diperlukan untuk keamanan tambahan"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Pola diperlukan untuk keamanan tambahan"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Sandi diperlukan untuk keamanan tambahan"</string> diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml index 20808dbe4b0a..2deefd0b9643 100644 --- a/packages/SystemUI/res-keyguard/values-is/strings.xml +++ b/packages/SystemUI/res-keyguard/values-is/strings.xml @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Mynsturs er krafist eftir að tækið er endurræst"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN-númers er krafist eftir að tækið er endurræst"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Aðgangsorðs er krafist eftir að tækið er endurræst"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Fyrir aukið öryggi skaltu nota mynstur í staðinn"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Fyrir aukið öryggi skaltu nota PIN-númer í staðinn"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Fyrir aukið öryggi skaltu nota aðgangsorð í staðinn"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Til að auka öryggi skaltu nota mynstur í staðinn"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Til að auka öryggi skaltu nota PIN-númer í staðinn"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Til að auka öryggi skaltu nota aðgangsorð í staðinn"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN-númers er krafist af öryggisástæðum"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Mynsturs er krafist af öryggisástæðum"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Aðgangsorðs er krafist af öryggisástæðum"</string> diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml index 8d86a8df1d69..69154aedd1a0 100644 --- a/packages/SystemUI/res-keyguard/values-ko/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"기기가 다시 시작되어 패턴을 입력해야 합니다."</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"기기가 다시 시작되어 PIN을 입력해야 합니다."</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"기기가 다시 시작되어 비밀번호를 입력해야 합니다."</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"보안 강화를 위해 대신 패턴 사용"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"보안 강화를 위해 패턴 사용"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"보안 강화를 위해 대신 PIN 사용"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"보안 강화를 위해 대신 비밀번호 사용"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"보안 강화를 위해 PIN이 필요합니다."</string> diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml index 6bfbd64e5d53..6d2f0e508acf 100644 --- a/packages/SystemUI/res-keyguard/values-ky/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml @@ -49,7 +49,7 @@ <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM-картаны өчүрүү"</string> <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-картаны өчүрүүгө болбойт"</string> <string name="error_disable_esim_msg" msgid="2441188596467999327">"Катадан улам eSIM-картаны өчүрүүгө болбойт."</string> - <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Киргизүү"</string> + <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string> <string name="kg_wrong_pattern" msgid="5907301342430102842">"Графикалык ачкыч туура эмес"</string> <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"Графклк ачкч тура эмс. Кайтлап крүңз."</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Сырсөз туура эмес"</string> diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index 3e110b531ab1..6c57d89a36af 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -49,7 +49,7 @@ <string name="disable_carrier_button_text" msgid="7153361131709275746">"Оневозможи ја eSIM"</string> <string name="error_disable_esim_title" msgid="3802652622784813119">"Не може да се оневозможи eSIM"</string> <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM-картичката не може да се оневозможи поради грешка."</string> - <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Внеси"</string> + <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string> <string name="kg_wrong_pattern" msgid="5907301342430102842">"Погрешна шема"</string> <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"Погрешна шема. Обидете се повторно."</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Погрешна лозинка"</string> diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index 95d638e4c0d3..f74eb6697341 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"စက်ကို ပြန်စပြီးနောက် ပုံဖော်ခြင်းလိုအပ်သည်"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"စက်ကို ပြန်စပြီးနောက် ပင်နံပါတ်လိုအပ်သည်"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"စက်ကို ပြန်စပြီးနောက် စကားဝှက်လိုအပ်သည်"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ၎င်းအစား ပုံစံသုံးပါ"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ပုံစံကို အစားထိုးသုံးပါ"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ၎င်းအစား ပင်နံပါတ်သုံးပါ"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ၎င်းအစား စကားဝှက်သုံးပါ"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"ထပ်ဆောင်း လုံခြုံရေးအတွက် ပင်နံပါတ် လိုအပ်သည်"</string> diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index 219072b2bbb2..27856d6ba924 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -24,7 +24,7 @@ <string name="keyguard_enter_pin" msgid="8114529922480276834">"PIN हाल्नुहोस्"</string> <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"प्याटर्न हाल्नुहोस्"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"प्याटर्न कोर्नुहोस्"</string> - <string name="keyguard_enter_your_password" msgid="7225626204122735501">"पासवर्ड हाल्नुहोस्…"</string> + <string name="keyguard_enter_your_password" msgid="7225626204122735501">"पासवर्ड हाल्नुहोस्"</string> <string name="keyguard_enter_password" msgid="6483623792371009758">"पासवर्ड हाल्नुहोस्"</string> <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अमान्य कार्ड।"</string> <string name="keyguard_charged" msgid="5478247181205188995">"चार्ज भयो"</string> @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"डिभाइस रिस्टार्ट भएपछि प्याटर्न कोर्नु पर्ने हुन्छ"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"डिभाइस रिस्टार्ट भएपछि PIN हाल्नु पर्ने हुन्छ"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"डिभाइस रिस्टार्ट भएपछि पासवर्ड हाल्नु पर्ने हुन्छ"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"अतिरिक्त सुरक्षाका लागि यो प्रमाणीकरण विधिको साटो प्याटर्न प्रयोग गर्नुहोस्"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"अतिरिक्त सुरक्षाका लागि यो प्रमाणीकरण विधिको साटो पिन प्रयोग गर्नुहोस्"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"अतिरिक्त सुरक्षाका लागि यो प्रमाणीकरण विधिको साटो पासवर्ड प्रयोग गर्नुहोस्"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"अतिरिक्त सुरक्षाका लागि यसको साटो पासवर्ड प्रयोग गर्नुहोस्"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"अतिरिक्त सुरक्षाका लागि यसको साटो पासवर्ड प्रयोग गर्नुहोस्"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"अतिरिक्त सुरक्षाका लागि यसको साटो पासवर्ड प्रयोग गर्नुहोस्"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"अतिरिक्त सुरक्षाका लागि PIN चाहिन्छ"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"अतिरिक्त सुरक्षाका लागि प्याटर्न चाहिन्छ"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"अतिरिक्त सुरक्षाका लागि पासवर्ड चाहिन्छ"</string> diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml index 020640361e7f..9fb9e1bfe8a5 100644 --- a/packages/SystemUI/res-keyguard/values-nl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml @@ -22,7 +22,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Geef je pincode op"</string> <string name="keyguard_enter_pin" msgid="8114529922480276834">"Voer pincode in"</string> - <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Geef je patroon op"</string> + <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Voer je patroon in"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Teken het patroon"</string> <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Voer je wachtwoord in"</string> <string name="keyguard_enter_password" msgid="6483623792371009758">"Geef het wachtwoord op"</string> @@ -80,9 +80,9 @@ <string name="kg_face_locked_out" msgid="2751559491287575">"Kan niet ontgrendelen met gezicht. Te veel pogingen."</string> <string name="kg_fp_locked_out" msgid="6228277682396768830">"Niet ontgrendeld met vingerafdruk. Te veel pogingen."</string> <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"Trust agent is niet beschikbaar"</string> - <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Te veel pogingen met onjuiste pincode"</string> - <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Te veel pogingen met onjuist patroon"</string> - <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Te veel pogingen met onjuist wachtwoord"</string> + <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Pincode te vaak verkeerd ingevoerd"</string> + <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Patroon te vaak verkeerd getekend"</string> + <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Wachtwoord te vaak verkeerd ingevoerd"</string> <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Probeer het over # seconde opnieuw.}other{Probeer het over # seconden opnieuw.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Geef de pincode van de simkaart op."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Geef de pincode voor de simkaart van \'<xliff:g id="CARRIER">%1$s</xliff:g>\' op."</string> @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Patroon is vereist na opnieuw opstarten apparaat"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Pincode is vereist na opnieuw opstarten apparaat"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Wachtwoord is vereist na opnieuw opstarten apparaat"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Gebruik in plaats daarvan het patroon voor extra beveiliging"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Gebruik het patroon voor extra beveiliging"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Gebruik de pincode voor extra beveiliging"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Gebruik in plaats daarvan het wachtwoord voor extra beveiliging"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Gebruik het wachtwoord voor extra beveiliging"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Pincode vereist voor extra beveiliging"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Patroon vereist voor extra beveiliging"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Wachtwoord vereist voor extra beveiliging"</string> diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml index 4a8907031cbd..f25e9c5454ed 100644 --- a/packages/SystemUI/res-keyguard/values-pl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml @@ -83,7 +83,7 @@ <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Zbyt wiele nieudanych prób wpisania kodu PIN"</string> <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Zbyt wiele nieudanych prób narysowania wzoru"</string> <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Zbyt wiele nieudanych prób wpisania hasła"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Spróbuj ponownie za # sekundę.}few{Spróbuj ponownie za # sekundy.}many{Spróbuj ponownie za # sekund.}other{Spróbuj ponownie za # sekundy.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Spróbuj ponownie za # sekundę}few{Spróbuj ponownie za # sekundy}many{Spróbuj ponownie za # sekund}other{Spróbuj ponownie za # sekundy}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Wpisz kod PIN karty SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Wpisz kod PIN karty SIM „<xliff:g id="CARRIER">%1$s</xliff:g>”."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Wyłącz kartę eSIM, by używać urządzenia bez usługi sieci komórkowej."</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 1ae1aeba90cd..b29220476224 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -24,7 +24,7 @@ <string name="keyguard_enter_pin" msgid="8114529922480276834">"Introduza o PIN"</string> <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introduza o padrão"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Desenhe o padrão"</string> - <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduza a palavra-passe."</string> + <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduza a palavra-passe"</string> <string name="keyguard_enter_password" msgid="6483623792371009758">"Introduza a palavra-passe"</string> <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string> <string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string> @@ -108,9 +108,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Padrão necessário após reiniciar o dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN necessário após reiniciar o dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Palavra-passe necessária após reiniciar dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para uma segurança adicional, use antes o padrão"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para uma segurança adicional, use antes o PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para uma segurança adicional, use antes a palavra-passe"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para segurança adicional, use o padrão"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para segurança adicional, use o PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para segurança adicional, use a palavra-passe"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Para segurança adicional, é necessária um PIN"</string> <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Para segurança adicional, é necessário um padrão"</string> <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Para segurança adicional, é necessária uma palavra-passe"</string> diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml index 5725fe0408c7..9b0647afb614 100644 --- a/packages/SystemUI/res-keyguard/values-sk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Po reštarte zariadenia sa vyžaduje vzor"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Po reštarte zariadenia sa vyžaduje kód PIN"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Po reštarte zariadenia sa vyžaduje heslo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"V rámci zvýšenia zabezpečenia použite radšej vzor"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Z bezpečnostných dôvodov použite radšej vzor"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"V rámci zvýšenia zabezpečenia použite radšej PIN"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"V rámci zvýšenia zabezpečenia použite radšej heslo"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Zvýšenie zabezpečenia vyžaduje kód PIN"</string> diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml index bfe5ae09d154..cb17459c84c4 100644 --- a/packages/SystemUI/res-keyguard/values-tl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Kailangan ang pattern pagka-restart ng device"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Kailangan ang PIN pagka-restart ng device"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Kailangan ang password pagka-restart ng device"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para sa karagdagang seguridad, gumamit na lang ng pattern"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para sa karagdagang seguridad, gumamit ng pattern"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para sa karagdagang seguridad, gumamit na lang ng PIN"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para sa karagdagang seguridad, gumamit na lang ng password"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Kinakailangan ang PIN para sa karagdagang seguridad"</string> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index bbd319c3988a..72ea8500b746 100644 --- a/packages/SystemUI/res-keyguard/values-vi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Cần vẽ hình mở khoá sau khi khởi động lại thiết bị"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Cần nhập mã PIN sau khi khởi động lại thiết bị"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Cần nhập mật khẩu sau khi khởi động lại thiết bị"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Để tăng cường bảo mật, hãy sử dụng hình mở khoá"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Để tăng cường bảo mật, hãy dùng hình mở khoá"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Để tăng cường bảo mật, hãy sử dụng mã PIN"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Để tăng cường bảo mật, hãy sử dụng mật khẩu"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Yêu cầu mã PIN để tăng cường bảo mật"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index a316e8cc727f..7d74c9cb8224 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -22,7 +22,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"输入您的 PIN 码"</string> <string name="keyguard_enter_pin" msgid="8114529922480276834">"输入 PIN 码"</string> - <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"绘制您的图案"</string> + <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"绘制解锁图案"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"绘制图案"</string> <string name="keyguard_enter_your_password" msgid="7225626204122735501">"输入您的密码"</string> <string name="keyguard_enter_password" msgid="6483623792371009758">"输入密码"</string> @@ -108,7 +108,7 @@ <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"设备重启后,必须绘制图案才能解锁"</string> <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"设备重启后,必须输入 PIN 码才能解锁"</string> <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"设备重启后,必须输入密码才能解锁"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"为增强安全性,请改用图案"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"为增强安全性,请改用解锁图案"</string> <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"为增强安全性,请改用 PIN 码"</string> <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"为增强安全性,请改用密码"</string> <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"需要输入 PIN 码以进一步确保安全"</string> diff --git a/packages/SystemUI/res/drawable/ic_noise_aware.xml b/packages/SystemUI/res/drawable/ic_noise_aware.xml deleted file mode 100644 index 54826414f3f7..000000000000 --- a/packages/SystemUI/res/drawable/ic_noise_aware.xml +++ /dev/null @@ -1,26 +0,0 @@ -<!-- - ~ Copyright (C) 2024 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="960" - android:viewportHeight="960" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M440,82Q450,81 460,80.5Q470,80 480,80Q491,80 500.5,80.5Q510,81 520,82L520,162Q510,160 500.5,160Q491,160 480,160Q469,160 459.5,160Q450,160 440,162L440,82ZM272,138Q289,127 306.5,119Q324,111 343,104L378,176Q358,182 340.5,190.5Q323,199 306,210L272,138ZM654,210Q637,199 619.5,190.5Q602,182 582,176L617,104Q636,111 653.5,119Q671,127 688,138L654,210ZM753,311Q742,294 729,278.5Q716,263 702,249L765,199Q779,213 792,228.5Q805,244 816,261L753,311ZM143,263Q154,246 166.5,230.5Q179,215 193,201L256,251Q242,265 229.5,280.5Q217,296 206,313L143,263ZM83,428Q85,408 90,388.5Q95,369 101,350L180,368Q173,387 168.5,406.5Q164,426 162,446L83,428ZM799,449Q797,429 792.5,409Q788,389 781,370L859,352Q865,371 870,390.5Q875,410 877,430L799,449ZM781,590Q788,571 792,552Q796,533 798,513L877,531Q875,551 870,570.5Q865,590 859,609L781,590ZM162,514Q164,534 168.5,553.5Q173,573 180,592L101,610Q95,591 90,571.5Q85,552 83,532L162,514ZM705,708Q719,694 731,678.5Q743,663 754,646L818,696Q807,713 794.5,728.5Q782,744 768,758L705,708ZM194,760Q180,746 167.5,730Q155,714 144,697L206,647Q217,664 229.5,680Q242,696 256,710L194,760ZM583,783Q603,776 620,768Q637,760 654,749L689,821Q672,832 654.5,840.5Q637,849 618,856L583,783ZM344,857Q325,850 307,841.5Q289,833 272,822L307,750Q324,761 341.5,769.5Q359,778 379,784L344,857ZM480,880Q470,880 460,879.5Q450,879 440,878L440,798Q453,800 480,800Q491,800 500.5,800Q510,800 520,798L520,878Q510,879 500.5,879.5Q491,880 480,880ZM520,720Q482,720 450.5,697Q419,674 406,638Q403,629 399.5,620.5Q396,612 389,605L334,550Q308,524 294,490.5Q280,457 280,420Q280,345 332.5,292.5Q385,240 460,240Q529,240 580,285.5Q631,331 639,400L558,400Q551,365 523.5,342.5Q496,320 460,320Q418,320 389,349Q360,378 360,420Q360,440 368,459.5Q376,479 391,494L445,548Q459,562 467.5,578.5Q476,595 482,612Q487,625 497,632.5Q507,640 520,640Q537,640 548.5,628.5Q560,617 560,600L640,600Q640,650 605.5,685Q571,720 520,720ZM540,560Q515,560 497.5,542.5Q480,525 480,500Q480,474 497.5,457Q515,440 540,440Q566,440 583,457Q600,474 600,500Q600,525 583,542.5Q566,560 540,560Z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/shelf_action_chip_background.xml b/packages/SystemUI/res/drawable/shelf_action_chip_background.xml new file mode 100644 index 000000000000..63600beff126 --- /dev/null +++ b/packages/SystemUI/res/drawable/shelf_action_chip_background.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<ripple + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:color="@color/overlay_button_ripple"> + <item android:id="@android:id/background"> + <shape android:shape="rectangle"> + <solid android:color="?androidprv:attr/materialColorSecondary"/> + <corners android:radius="10000dp"/> <!-- fully-rounded radius --> + </shape> + </item> +</ripple> diff --git a/packages/SystemUI/res/layout/auth_biometric_icon.xml b/packages/SystemUI/res/drawable/shelf_action_chip_container_background.xml index b2df63dab700..bb8cece9203b 100644 --- a/packages/SystemUI/res/layout/auth_biometric_icon.xml +++ b/packages/SystemUI/res/drawable/shelf_action_chip_container_background.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2023 The Android Open Source Project + ~ Copyright (C) 2024 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -14,13 +14,10 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - -<com.airbnb.lottie.LottieAnimationView +<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/biometric_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:contentDescription="@null" - android:scaleType="fitXY"/>
\ No newline at end of file + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:shape="rectangle"> + <solid android:color="?androidprv:attr/materialColorSurfaceBright"/> + <corners android:radius="10000dp"/> <!-- fully-rounded radius --> +</shape> diff --git a/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml b/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml new file mode 100644 index 000000000000..a5b44e564157 --- /dev/null +++ b/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<shape xmlns:android = "http://schemas.android.com/apk/res/android"> + <size + android:width = "@dimen/overlay_action_chip_margin_start" + android:height = "0dp"/> +</shape> diff --git a/packages/SystemUI/res/drawable/shelf_action_container_clipping_shape.xml b/packages/SystemUI/res/drawable/shelf_action_container_clipping_shape.xml new file mode 100644 index 000000000000..76779f9f1b2c --- /dev/null +++ b/packages/SystemUI/res/drawable/shelf_action_container_clipping_shape.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <!-- We don't actually draw anything, just expressing the shape for clipping. --> + <solid android:color="#0000"/> + <corners android:radius="10000dp"/> <!-- fully-rounded radius --> +</shape> diff --git a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml index 13355f374dd6..76d10ccb8a25 100644 --- a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml +++ b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml @@ -47,7 +47,7 @@ android:layout_marginBottom="@dimen/bluetooth_dialog_layout_margin" android:ellipsize="end" android:gravity="center_vertical|center_horizontal" - android:maxLines="1" + android:maxLines="2" android:text="@string/quick_settings_bluetooth_tile_subtitle" android:textAppearance="@style/TextAppearance.Dialog.Body.Message" app:layout_constraintEnd_toEndOf="parent" @@ -256,6 +256,24 @@ app:constraint_referenced_ids="pair_new_device_button,bluetooth_auto_on_toggle_info_text" /> <Button + android:id="@+id/audio_sharing_button" + style="@style/Widget.Dialog.Button.BorderButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="9dp" + android:layout_marginBottom="@dimen/dialog_bottom_padding" + android:layout_marginEnd="@dimen/dialog_side_padding" + android:layout_marginStart="@dimen/dialog_side_padding" + android:ellipsize="end" + android:maxLines="1" + android:text="@string/quick_settings_bluetooth_audio_sharing_button" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@+id/barrier" + app:layout_constraintVertical_bias="1" + android:visibility="gone" /> + + <Button android:id="@+id/done_button" style="@style/Widget.Dialog.Button" android:layout_width="wrap_content" diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 1eb05bfd602d..e3c5a7d03d2e 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -36,8 +36,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent" - android:focusable="true" - android:accessibilityTraversalBefore="@android:id/edit" + android:focusable="false" + android:importantForAccessibility="yes" android:clipToPadding="false" android:clipChildren="false"> diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml index eeb64bd8460e..6a5b999f5444 100644 --- a/packages/SystemUI/res/layout/screenshot_shelf.xml +++ b/packages/SystemUI/res/layout/screenshot_shelf.xml @@ -20,39 +20,37 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> - <ImageView + <FrameLayout android:id="@+id/actions_container_background" android:visibility="gone" - android:layout_height="0dp" - android:layout_width="0dp" - android:elevation="4dp" - android:background="@drawable/action_chip_container_background" - android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal" - android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/actions_container" - app:layout_constraintEnd_toEndOf="@+id/actions_container" - app:layout_constraintBottom_toTopOf="@id/guideline"/> - <HorizontalScrollView - android:id="@+id/actions_container" - android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/overlay_action_container_margin_horizontal" - android:paddingHorizontal="@dimen/overlay_action_container_padding_end" - android:paddingVertical="@dimen/overlay_action_container_padding_vertical" + android:layout_width="wrap_content" android:elevation="4dp" - android:scrollbars="none" - app:layout_constraintHorizontal_bias="0" - app:layout_constraintWidth_percent="1.0" - app:layout_constraintWidth_max="wrap" + android:background="@drawable/shelf_action_chip_container_background" + android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal" + android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toBottomOf="@id/actions_container_background"> - <LinearLayout - android:id="@+id/screenshot_actions" + app:layout_constraintBottom_toTopOf="@id/guideline" + > + <HorizontalScrollView + android:id="@+id/actions_container" android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - </HorizontalScrollView> + android:layout_height="wrap_content" + android:layout_marginVertical="@dimen/overlay_action_container_padding_vertical" + android:layout_marginHorizontal="@dimen/overlay_action_chip_margin_start" + android:background="@drawable/shelf_action_container_clipping_shape" + android:clipToOutline="true" + android:scrollbars="none"> + <LinearLayout + android:id="@+id/screenshot_actions" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:showDividers="middle" + android:divider="@drawable/shelf_action_chip_divider" + android:animateLayoutChanges="true" + /> + </HorizontalScrollView> + </FrameLayout> <View android:id="@+id/screenshot_preview_border" android:layout_width="0dp" @@ -66,7 +64,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/screenshot_preview" app:layout_constraintEnd_toEndOf="@id/screenshot_preview" - app:layout_constraintBottom_toTopOf="@id/actions_container"/> + app:layout_constraintBottom_toTopOf="@id/actions_container_background"/> <ImageView android:id="@+id/screenshot_preview" android:layout_width="@dimen/overlay_x_scale" diff --git a/packages/SystemUI/res/layout/shelf_action_chip.xml b/packages/SystemUI/res/layout/shelf_action_chip.xml new file mode 100644 index 000000000000..c7606e404215 --- /dev/null +++ b/packages/SystemUI/res/layout/shelf_action_chip.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:theme="@style/FloatingOverlay" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingVertical="@dimen/overlay_action_chip_padding_vertical" + android:gravity="center" + android:background="@drawable/shelf_action_chip_background" + > + <ImageView + android:id="@+id/overlay_action_chip_icon" + android:tint="?androidprv:attr/materialColorOnSecondary" + android:layout_width="@dimen/overlay_action_chip_icon_size" + android:layout_height="@dimen/overlay_action_chip_icon_size"/> + <TextView + android:id="@+id/overlay_action_chip_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:fontFamily="@*android:string/config_headlineFontFamilyMedium" + android:textSize="@dimen/overlay_action_chip_text_size" + android:textColor="?androidprv:attr/materialColorOnSecondary"/> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/volume_ringer_drawer.xml b/packages/SystemUI/res/layout/volume_ringer_drawer.xml index 9b1fa23081b4..8f1e0610853f 100644 --- a/packages/SystemUI/res/layout/volume_ringer_drawer.xml +++ b/packages/SystemUI/res/layout/volume_ringer_drawer.xml @@ -67,8 +67,8 @@ android:layout_width="@dimen/volume_ringer_drawer_icon_size" android:layout_height="@dimen/volume_ringer_drawer_icon_size" android:layout_gravity="center" - android:tint="?android:attr/textColorPrimary" - android:src="@drawable/ic_volume_ringer_vibrate" /> + android:src="@drawable/ic_volume_ringer_vibrate" + android:tint="?android:attr/textColorPrimary" /> </FrameLayout> @@ -76,6 +76,7 @@ android:id="@+id/volume_drawer_mute" android:layout_width="@dimen/volume_ringer_drawer_item_size" android:layout_height="@dimen/volume_ringer_drawer_item_size" + android:accessibilityTraversalAfter="@id/volume_drawer_vibrate" android:contentDescription="@string/volume_ringer_hint_mute" android:gravity="center"> @@ -84,8 +85,8 @@ android:layout_width="@dimen/volume_ringer_drawer_icon_size" android:layout_height="@dimen/volume_ringer_drawer_icon_size" android:layout_gravity="center" - android:tint="?android:attr/textColorPrimary" - android:src="@drawable/ic_speaker_mute" /> + android:src="@drawable/ic_speaker_mute" + android:tint="?android:attr/textColorPrimary" /> </FrameLayout> @@ -93,6 +94,7 @@ android:id="@+id/volume_drawer_normal" android:layout_width="@dimen/volume_ringer_drawer_item_size" android:layout_height="@dimen/volume_ringer_drawer_item_size" + android:accessibilityTraversalAfter="@id/volume_drawer_mute" android:contentDescription="@string/volume_ringer_hint_unmute" android:gravity="center"> @@ -101,8 +103,8 @@ android:layout_width="@dimen/volume_ringer_drawer_icon_size" android:layout_height="@dimen/volume_ringer_drawer_icon_size" android:layout_gravity="center" - android:tint="?android:attr/textColorPrimary" - android:src="@drawable/ic_speaker_on" /> + android:src="@drawable/ic_speaker_on" + android:tint="?android:attr/textColorPrimary" /> </FrameLayout> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 2027d168e750..ccea0fcc11db 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -71,7 +71,7 @@ <string name="usb_port_enabled" msgid="531823867664717018">"USB-poort is geaktiveer om laaiers en bykomstighede te bespeur"</string> <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktiveer USB"</string> <string name="learn_more" msgid="4690632085667273811">"Kom meer te wete"</string> - <string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string> + <string name="global_action_screenshot" msgid="2760267567509131654">"Skermskoot"</string> <string name="global_action_smart_lock_disabled" msgid="6286551337177954859">"Hou Ontsluit is gedeaktiveer"</string> <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"het \'n prent gestuur"</string> <string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Neem kwessie op"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Begin"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Foutverslag"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Watter deel van jou toestelervaring is geraak?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Kies soort kwessie"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skermopname"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standaard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hoog"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Gehoortoestelle"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Gehoortoestelle"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Bind nuwe toestel saam"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nuwe toestel saam te bind"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokkeer toestelmikrofoon?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokkeer toestelkamera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblokkeer toestelkamera en mikrofoon?"</string> @@ -448,10 +445,8 @@ <string name="button_to_remove_widget" msgid="3948204829181214098">"Verwyder"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Voeg legstuk by"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Klaar"</string> - <!-- no translation found for label_for_button_in_empty_state_cta (7314975555382055823) --> - <skip /> - <!-- no translation found for title_for_empty_state_cta (6161654421223450530) --> - <skip /> + <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Voeg legstukke by"</string> + <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Kry kitstoegang tot jou gunstelingapplegstukke sonder om jou tablet te ontsluit."</string> <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Laat enige legstuk op die sluitskerm toe?"</string> <string name="button_text_to_open_settings" msgid="1987729256950941628">"Maak instellings oop"</string> <string name="work_mode_off_title" msgid="5794818421357835873">"Hervat werkapps?"</string> @@ -747,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Wissel sleutelborduitleg"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"of"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Maak soeknavraag skoon"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortpaaie"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Kortpadsleutels"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Soek kortpaaie"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen kortpaaie gevind nie"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Stelsel"</string> @@ -772,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Maak Assistent oop"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Sluit skerm"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Maak ’n nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Verrig veelvuldige stelseltake"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Gaan by verdeelde skerm in met huidige app aan die regterkant"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Gaan by verdeelde skerm in met huidige app aan die linkerkant"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Verrigting van veelvuldige take"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gebruik verdeelde skerm met huidige app aan die regterkant"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gebruik verdeelde skerm met huidige app aan die linkerkant"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Skakel oor van verdeelde skerm na volskerm"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skakel oor na app regs of onder terwyl jy verdeelde skerm gebruik"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skakel oor na app links of bo terwyl jy verdeelde skerm gebruik"</string> @@ -895,12 +890,12 @@ <string name="notification_channel_alerts" msgid="3385787053375150046">"Opletberigte"</string> <string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string> <string name="notification_channel_screenshot" msgid="7665814998932211997">"Skermkiekies"</string> - <string name="notification_channel_instant" msgid="7556135423486752680">"Kitsprogramme"</string> + <string name="notification_channel_instant" msgid="7556135423486752680">"Kitsapps"</string> <string name="notification_channel_setup" msgid="7660580986090760350">"Opstelling"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Berging"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Wenke"</string> <string name="notification_channel_accessibility" msgid="8956203986976245820">"Toeganklikheid"</string> - <string name="instant_apps" msgid="8337185853050247304">"Kitsprogramme"</string> + <string name="instant_apps" msgid="8337185853050247304">"Kitsapps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> loop tans"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Program is oopgemaak sonder dat dit geïnstalleer is."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Program is oopgemaak sonder dat dit geïnstalleer is. Tik om meer te wete te kom."</string> @@ -1195,8 +1190,8 @@ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kies gebruiker"</string> <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app is aktief}other{# apps is aktief}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nuwe inligting"</string> - <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktiewe programme"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Hierdie programme is aktief en werk, selfs wanneer jy hulle nie gebruik nie. Dit verbeter hul funksies, maar beïnvloed dalk ook batterylewe."</string> + <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktiewe apps"</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Hierdie apps is aktief en werk, selfs wanneer jy hulle nie gebruik nie. Dit verbeter hul funksies, maar beïnvloed dalk ook batterylewe."</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Stop"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Gestop"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Klaar"</string> diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml index 8f0532e00064..1b4781d24ebc 100644 --- a/packages/SystemUI/res/values-af/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Af"</item> <item msgid="5137565285664080143">"Aan"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nie beskikbaar nie"</item> + <item msgid="3079622119444911877">"Af"</item> + <item msgid="3028994095749238254">"Aan"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index a3700f2785d9..9e528e0c9ac0 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ችግርን ቅዳ"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ጀምር"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"አቁም"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"የሳንካ ሪፖርት"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"የትኛው የመሣሪያዎ ተሞክሮ ክፍል ተጎድቷል?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"የችግሩን አይነት ይምረጡ"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"የማያ መቅረጫ"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"መካከለኛ"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ከፍተኛ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"የመስሚያ መሣሪያዎች"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"የመስማት ችሎታ መሣሪያ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"አዲስ መሣሪያ ያጣምሩ"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"አዲስ መሣሪያ ለማጣመር ጠቅ ያድርጉ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"የመሣሪያ ማይክሮፎን እገዳ ይነሳ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"የመሣሪያ ካሜራ እገዳ ይነሳ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"የመሣሪያ ካሜራ እና ማይክሮፎን እገዳ ይነሳ?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"የቁልፍ ሰሌዳ ገጽታ ለውጥ"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ወይም"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"የፍለጋ መጠይቅን አጽዳ"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"አቋራጮች"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"የቁልፍ ሰሌዳ አቋራጮች"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"አቋራጮችን ይፈልጉ"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ምንም አቋራጮች አልተገኙም"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ሥርዓት"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"ረዳትን ክፈት"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ማያ ገፅ ቁልፍ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ማስታወሻ ይውሰዱ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"የሥርዓት ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"ለአርኤችኤስ በአሁኑ መተግበሪያ ወደ የተከፈለ ማያ ገጽ ግባ"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"ለኤልኤችኤስ በአሁኑ መተግበሪያ ወደ የተከፈለ ማያ ገጽ ይግቡ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"የአሁኑ መተግበሪያ በስተቀኝ ላይ ሆኖ የተከፈለ ማያ ገጽን ይጠቀሙ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"የአሁኑ መተግበሪያ በስተግራ ላይ ሆኖ የተከፈለ ማያ ገጽን ይጠቀሙ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"ከየተከፈለ ማያ ገጽ ወደ ሙሉ ገጽ ዕይታ ቀይር"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"የተከፈለ ማያ ገጽን ሲጠቀሙ በቀኝ ወይም ከታች ወዳለ መተግበሪያ ይቀይሩ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"የተከፈለ ማያ ገጽን ሲጠቀሙ በቀኝ ወይም ከላይ ወዳለ መተግበሪያ ይቀይሩ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 767e909de2ea..759f957c543a 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -120,7 +120,7 @@ <string name="screenrecord_stop_label" msgid="72699670052087989">"إيقاف"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"مشاركة"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"تم حفظ تسجيل الشاشة"</string> - <string name="screenrecord_save_text" msgid="3008973099800840163">"انقر لعرض التسجيل."</string> + <string name="screenrecord_save_text" msgid="3008973099800840163">"انقر لعرض التسجيل"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"حدث خطأ أثناء حفظ تسجيل محتوى الشاشة."</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"حدث خطأ في بدء تسجيل الشاشة"</string> <string name="issuerecord_title" msgid="286627115110121849">"مسجّلة المشاكل"</string> @@ -287,7 +287,7 @@ <string name="quick_settings_location_label" msgid="2621868789013389163">"الموقع الجغرافي"</string> <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"شاشة الاستراحة"</string> <string name="quick_settings_camera_label" msgid="5612076679385269339">"الوصول إلى الكاميرا"</string> - <string name="quick_settings_mic_label" msgid="8392773746295266375">"الوصول إلى الميكروفون"</string> + <string name="quick_settings_mic_label" msgid="8392773746295266375">"الوصول للميكروفون"</string> <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"متاح"</string> <string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"محظور"</string> <string name="quick_settings_media_device_label" msgid="8034019242363789941">"جهاز الوسائط"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"تسجيل المشكلة"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"بدء"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"إيقاف"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"تقرير خطأ"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ما هو الجانب الذي تأثّر في تجربة استخدام الجهاز؟"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"اختيار نوع المشكلة"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"تسجيل الشاشة"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"عادي"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"متوسط"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"مرتفع"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعات الأذن الطبية"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سماعات الأذن الطبية"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"إقران جهاز جديد"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"انقر لإقران جهاز جديد"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"هل تريد إزالة حظر ميكروفون الجهاز؟"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"هل تريد إزالة حظر كاميرا الجهاز؟"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"هل تريد إزالة حظر الكاميرا والميكروفون؟"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تبديل تنسيق لوحة المفاتيح"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"أو"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"محو طلب البحث"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"الاختصارات"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"اختصارات لوحة المفاتيح"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"البحث في الاختصارات"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"لم يُعثَر على اختصارات."</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"النظام"</string> @@ -770,14 +767,14 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"فتح \"مساعد Google\""</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"شاشة القفل"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"تدوين ملاحظة"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"تعدُّد المهام في النظام"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"تفعيل وضع \"تقسيم الشاشة\" مع عرض التطبيق الحالي على يسار الشاشة"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"تفعيل وضع \"تقسيم الشاشة\" مع عرض التطبيق الحالي على يمين الشاشة"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"تعدُّد المهام"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"استخدام \"وضع تقسيم الشاشة\" مع تثبيت التطبيق الحالي على اليمين"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"استخدام \"وضع تقسيم الشاشة\" مع تثبيت التطبيق الحالي على اليسار"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"التبديل من وضع \"تقسيم الشاشة\" إلى وضع \"ملء الشاشة\""</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"التبديل إلى التطبيق على اليسار أو الأسفل أثناء استخدام \"تقسيم الشاشة\""</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"التبديل إلى التطبيق على اليمين أو الأعلى أثناء استخدام \"تقسيم الشاشة\""</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"استبدال تطبيق بآخر في وضع \"تقسيم الشاشة\""</string> - <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"إدخال"</string> + <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"الإدخال"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"التبديل إلى اللغة التالية"</string> <string name="input_switch_input_language_previous" msgid="6043341362202336623">"التبديل إلى اللغة السابقة"</string> <string name="input_access_emoji" msgid="8105642858900406351">"الوصول إلى الرموز التعبيرية"</string> @@ -789,7 +786,7 @@ <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"البريد الإلكتروني"</string> <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"الرسائل القصيرة SMS"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"الموسيقى"</string> - <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"التقويم"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"تقويم Google"</string> <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"الآلة الحاسبة"</string> <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"خرائط Google"</string> <string name="volume_and_do_not_disturb" msgid="502044092739382832">"عدم الإزعاج"</string> @@ -802,7 +799,7 @@ <string name="data_saver" msgid="3484013368530820763">"توفير البيانات"</string> <string name="accessibility_data_saver_on" msgid="5394743820189757731">"تم تفعيل توفير البيانات"</string> <string name="switch_bar_on" msgid="1770868129120096114">"مفعّل"</string> - <string name="switch_bar_off" msgid="5669805115416379556">"متوقف"</string> + <string name="switch_bar_off" msgid="5669805115416379556">"غير مفعّل"</string> <string name="tile_unavailable" msgid="3095879009136616920">"غير متوفّر"</string> <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"مزيد من المعلومات"</string> <string name="nav_bar" msgid="4642708685386136807">"شريط التنقل"</string> @@ -830,7 +827,7 @@ <string name="left_icon" msgid="5036278531966897006">"رمز اليسار"</string> <string name="right_icon" msgid="1103955040645237425">"رمز اليمين"</string> <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة المربّعات"</string> - <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</string> + <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"اسحب هنا للإزالة"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"الحدّ الأدنى من عدد المربعات الذي تحتاج إليه هو <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string> <string name="qs_edit" msgid="5583565172803472437">"تعديل"</string> @@ -995,7 +992,7 @@ <string name="accessibility_floating_button_undo" msgid="511112888715708241">"تراجع"</string> <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"زر أدوات تسهيل الاستخدام مخفي"</string> <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"انقر لإظهار زر أدوات تسهيل الاستخدام."</string> - <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"تمت إزالة اختصار <xliff:g id="FEATURE_NAME">%s</xliff:g>."</string> + <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"تمت إزالة اختصار ميزة \"<xliff:g id="FEATURE_NAME">%s</xliff:g>\""</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{تمت إزالة اختصار واحد.}zero{تمت إزالة # اختصار.}two{تمت إزالة اختصارَين.}few{تمت إزالة # اختصارات.}many{تمت إزالة # اختصارًا.}other{تمت إزالة # اختصار.}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"النقل إلى أعلى يمين الشاشة"</string> <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"النقل إلى أعلى يسار الشاشة"</string> diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml index 307a26e8e611..a89650aa6e19 100644 --- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"الخيار غير مفعَّل"</item> <item msgid="5137565285664080143">"الخيار مفعَّل"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"غير متوفّرة"</item> + <item msgid="3079622119444911877">"غير مفعَّلة"</item> + <item msgid="3028994095749238254">"مفعَّلة"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 5a083abc0b50..1f859accbf55 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ৰেকৰ্ড সম্পৰ্কীয় সমস্যা"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"আৰম্ভ কৰক"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"বন্ধ কৰক"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"বাগ ৰিপ’ৰ্ট"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"আপোনাৰ ডিভাইচৰ অভিজ্ঞতাৰ কোনটো অংশ প্ৰভাৱিত হৈছিল?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"সমস্যাৰ প্ৰকাৰ বাছনি কৰক"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"স্ক্ৰীন ৰেকৰ্ড"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"মধ্যমীয়া"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"উচ্চ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"শুনাৰ ডিভাইচ"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"শুনাৰ ডিভাইচ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"নতুন ডিভাইচ পেয়াৰ কৰক"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইচ পেয়াৰ কৰিবলৈ ক্লিক কৰক"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইচৰ মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইচৰ কেমেৰা অৱৰোধৰ পৰা আঁতৰাবনে?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইচৰ কেমেৰা আৰু মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীব\'ৰ্ডৰ সজ্জা সলনি কৰক"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"অথবা"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"সন্ধান কৰা প্ৰশ্ন মচক"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শ্বৰ্টকাট"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"কীব’ৰ্ডৰ শ্বৰ্টকাট"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"সন্ধানৰ শ্বৰ্টকাট"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"কোনো শ্বৰ্টকাট বিচাৰি পোৱা নাই"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ছিষ্টেম"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant খোলক"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্ৰীন"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"টোকা লিখক"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ছিষ্টেম মাল্টিটাস্কিং"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"বৰ্তমানৰ এপৰ জৰিয়তে বিভাজিত স্ক্ৰীনৰ সোঁফালৰ স্ক্ৰীনখনত সোমাওক"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"বৰ্তমানৰ এপৰ জৰিয়তে বিভাজিত স্ক্ৰীনৰ বাওঁফালৰ স্ক্ৰীনখনত সোমাওক"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"মাল্টিটাস্কিং"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"বৰ্তমানৰ এপ্টোৰ সৈতে সোঁফালে বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰক"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"বৰ্তমানৰ এপ্টোৰ সৈতে বাওঁফালে বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰক"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"বিভাজিত স্ক্ৰীনৰ পৰা পূৰ্ণ স্ক্ৰীনলৈ সলনি কৰক"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰাৰ সময়ত সোঁফালে অথবা তলত থকা এপলৈ সলনি কৰক"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰাৰ সময়ত বাওঁফালে অথবা ওপৰত থকা এপলৈ সলনি কৰক"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 7faec8a1e174..dc095c9169a3 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Qeyd problemi"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Başlayın"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Dayandırın"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Baq hesabatı"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cihaz istifadəsinə necə təsir etdi?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Problem növü seçin"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekran qeydəalma"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standart"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Orta"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Yüksək"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eşitmə cihazları"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eşitmə cihazları"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yeni cihaz birləşdirin"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz birləşdirmək üçün klikləyin"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonu blokdan çıxarılsın?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerası blokdan çıxarılsın?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası və mikrofonu blokdan çıxarılsın?"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura düzümünü dəyişin"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"və ya"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Axtarış sorğusunu silin"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Qısayollar"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klaviatura qısayolları"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Qısayollar axtarın"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Qısayol tapılmadı"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistenti açın"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilid ekranı"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Qeyd götürün"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistemdə çoxsaylı tapşırıq icrası"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Cari tətbiq sağda olmaqla bölünmüş ekrana daxil olun"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Cari tətbiq solda olmaqla bölünmüş ekrana daxil olun"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Çoxsaylı tapşırıq icrası"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Cari tətbiq sağda olmaqla bölünmüş ekrandan istifadə edin"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Cari tətbiq solda olmaqla bölünmüş ekrandan istifadə edin"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Bölünmüş ekrandan tam ekrana keçin"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bölünmüş ekran istifadə edərkən sağda və ya aşağıda tətbiqə keçin"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bölünmüş ekran istifadə edərkən solda və ya yuxarıda tətbiqə keçin"</string> diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml index f39036946434..c24f4029e415 100644 --- a/packages/SystemUI/res/values-az/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Deaktiv"</item> <item msgid="5137565285664080143">"Aktiv"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Əlçatan deyil"</item> + <item msgid="3079622119444911877">"Deaktiv"</item> + <item msgid="3028994095749238254">"Aktiv"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index cd5dc2650b74..2f86ca4b3b8f 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Evidentirajte problem"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Pokreni"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zaustavi"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Izveštaj o grešci"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Na koji deo doživljaja na uređaju je ovo uticalo?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Izaberite tip problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje ekrana"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednje"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visoko"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Upari novi uređaj"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili nov uređaj"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite da odblokirate mikrofon uređaja?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite da odblokirate kameru uređaja?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite da odblokirate kameru i mikrofon uređaja?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promeni raspored tastature"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Obriši upit za pretragu"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tasterske prečice"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečice"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> @@ -768,10 +766,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvori podešavanja"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvori pomoćnika"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Napravite belešku"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Obavljanje više zadataka sistema istovremeno"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Pokreni podeljeni ekran za aktuelnu aplikaciju na desnoj strani"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Pokreni podeljeni ekran za aktuelnu aplikaciju na levoj strani"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Napravi belešku"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Obavljanje više zadataka istovremeno"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Koristite podeljeni ekran sa aktuelnom aplikacijom s desne strane"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Koristite podeljeni ekran sa aktuelnom aplikacijom s leve strane"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Pređi sa podeljenog ekrana na ceo ekran"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pređite u aplikaciju zdesna ili ispod dok koristite podeljeni ekran"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pređite u aplikaciju sleva ili iznad dok koristite podeljeni ekran"</string> @@ -1295,9 +1293,9 @@ <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Upravljaj pristupom"</string> <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Koristi telefonski poziv"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Nedavno korišćeno u telefonskom pozivu"</string> - <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> + <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index a76c38b54218..bc03d8c25213 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Запіс праблемы"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Пачынайце"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Спыніцеся"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"З чым была звязана праблема, якая вам сустрэлася?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Выберыце тып праблемы"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запіс экрана"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартная"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Сярэдняя"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Высокая"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слыхавыя апараты"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слыхавыя апараты"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Спалучыць новую прыладу"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Націсніце, каб спалучыць новую прыладу"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблакіраваць мікрафон прылады?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблакіраваць камеру прылады?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Разблакіраваць камеру і мікрафон прылады?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пераключыць раскладку клавіятуры"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"або"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ачысціць пошукавы запыт"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ярлыкі"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Спалучэнні клавіш"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пошук ярлыкоў"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ярлыкі не знойдзены"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Сістэма"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Выклікаць Памочніка"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Экран блакіроўкі"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Стварыць нататку"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Шматзадачнасць сістэмы"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Перайсці ў рэжым падзеленага экрана з бягучай праграмай справа"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Перайсці ў рэжым падзеленага экрана з бягучай праграмай злева"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Шматзадачнасць"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Падзяліць экран і памясціць гэту праграму справа"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Падзяліць экран і памясціць гэту праграму злева"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Пераключыцца з рэжыму падзеленага экрана на поўнаэкранны рэжым"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Пераключыцца на праграму справа або ўнізе на падзеленым экране"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Пераключыцца на праграму злева або ўверсе на падзеленым экране"</string> diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml index 32619ef03053..33e704cae0b1 100644 --- a/packages/SystemUI/res/values-be/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Выключана"</item> <item msgid="5137565285664080143">"Уключана"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Недаступна"</item> + <item msgid="3079622119444911877">"Выключана"</item> + <item msgid="3028994095749238254">"Уключана"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index f8793b3faeea..d80b8894dd18 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Записване на проблем"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Стартиране"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Спиране"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"С какво имахте проблем?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Изберете тип проблем"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запис на екрана"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартен"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Среден"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Висок"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухови апарати"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слухови апарати"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Сдвояване на ново устройство"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за сдвояване на ново устройство"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се отблокира ли микрофонът на устройството?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се отблокира ли камерата на устройството?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Да се отблокират ли камерата и микрофонът на устройството?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Превкл. на клавиат. подредба"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Изчистване на заявката за търсене"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Клавишни комбинации"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Клавишни комбинации"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Търсете комбинации"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Няма клавишни комбинации"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отваряне на Асистент"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Заключване на екрана"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Създаване на бележка"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Едновременно изпълняване на няколко задачи в системата"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Преминаване към разделен екран с текущото приложение отдясно"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Преминаване към разделен екран с текущото приложение отляво"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Изпълняване на няколко задачи едновременно"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Използване на разделен екран с текущото приложение вдясно"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Използване на разделен екран с текущото приложение вляво"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Превключване от разделен към цял екран"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Превключване към приложението вдясно/отдолу в режима на разделен екран"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Превключване към приложението вляво/отгоре в режима на разделен екран"</string> @@ -1285,7 +1283,7 @@ <string name="dismiss_dialog" msgid="2195508495854675882">"Отхвърляне"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"Свързан е екран"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string> - <string name="privacy_dialog_summary" msgid="2458769652125995409">"Скорошно използване на приложението"</string> + <string name="privacy_dialog_summary" msgid="2458769652125995409">"Скорошно използване от приложенията"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Вижте скорошния достъп"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Готово"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Разгъване и показване на опциите"</string> diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml index 381b0f0b2abb..e2fd65360020 100644 --- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Изключено"</item> <item msgid="5137565285664080143">"Включено"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Не е налице"</item> + <item msgid="3079622119444911877">"Изкл."</item> + <item msgid="3028994095749238254">"Вкл."</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index f6de0e38228b..36b57ee2975b 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -333,7 +333,7 @@ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"সূর্যোদয় পর্যন্ত"</string> <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> এ চালু হবে"</string> <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string> - <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"গাঢ় থিম"</string> + <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ডার্ক থিম"</string> <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ব্যাটারি সেভার"</string> <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূর্যাস্তে চালু হবে"</string> <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"রেকর্ডিংয়ে সমস্যা"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"শুরু করুন"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"বন্ধ করুন"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ডিভাইস ব্যবহার করার সময় কোথায় অসুবিধা হয়েছিল?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"সমস্যার প্রকার বেছে নিন"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"স্ক্রিন রেকর্ড"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"স্ট্যান্ডার্ড"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"মিডিয়াম"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"হাই"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"হিয়ারিং ডিভাইস"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"হিয়ারিং ডিভাইস"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"নতুন ডিভাইস পেয়ার করুন"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইস পেয়ার করতে ক্লিক করুন"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইসের মাইক্রোফোন আনব্লক করতে চান?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইসের ক্যামেরা আনব্লক করতে চান?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইসের ক্যামেরা এবং মাইক্রোফোন আনব্লক করতে চান?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীবোর্ড লে-আউট পাল্টান"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"অথবা"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"সার্চ কোয়েরি মুছুন"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শর্টকাট"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"কীবোর্ড শর্টকাট"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"শর্টকাট সার্চ করুন"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"কোনও শর্টকার্ট পাওয়া যায়নি"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"সিস্টেম"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant খুলুন"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্রিন"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"একটি নোট লিখুন"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"সিস্টেম মাল্টিটাস্কিং"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"ডানদিকে থাকা বর্তমান অ্যাপ ব্যবহার করে \'স্প্লিট স্ক্রিন\' যোগ করুন"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"বাঁদিকে থাকা বর্তমান অ্যাপ ব্যবহার করে \'স্প্লিট স্ক্রিন\' যোগ করুন"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"মাল্টিটাস্কিং"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ডানদিকে বর্তমান অ্যাপে স্প্লিট স্ক্রিন ব্যবহার করুন"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"বাঁদিকে বর্তমান অ্যাপে স্প্লিট স্ক্রিন ব্যবহার করুন"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"\'স্প্লিট স্ক্রিন\' থেকে ফুল স্ক্রিনে পাল্টান"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"স্প্লিট স্ক্রিন ব্যবহার করার সময় ডানদিকের বা নিচের অ্যাপে পাল্টে নিন"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"স্প্লিট স্ক্রিন ব্যবহার করার সময় বাঁদিকের বা উপরের অ্যাপে পাল্টে নিন"</string> diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml index 2eebd97088ab..6e4dfbfbf745 100644 --- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"বন্ধ আছে"</item> <item msgid="5137565285664080143">"চালু আছে"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"উপলভ্য নেই"</item> + <item msgid="3079622119444911877">"বন্ধ আছে"</item> + <item msgid="3028994095749238254">"চালু আছে"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 93477575571e..91acfa5b3a2b 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Snimite problem"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Pokrenite"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zaustavite"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Izvješće o pogrešci"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Koji dio uređaja je imao problem?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Odaberite vrstu problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje ekrana"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardno"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednje"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visoko"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uparite novi uređaj"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da uparite novi uređaj"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokirati mikrofon uređaja?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokirati kameru uređaja?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblokirati kameru i mikrofon uređaja?"</string> @@ -448,8 +445,8 @@ <string name="button_to_remove_widget" msgid="3948204829181214098">"Uklanjanje"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodajte vidžet"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gotovo"</string> - <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Dodaj widgete"</string> - <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Brzo pristupajte widgetima omiljenih aplikacija bez otključavanja tableta."</string> + <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Dodajte vidžet"</string> + <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Dobijte brz pristup omiljenim vidžetima aplikacija bez otključavanja tableta."</string> <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Dozvoliti bilo koji vidžet na zaključanom ekranu?"</string> <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otvori postavke"</string> <string name="work_mode_off_title" msgid="5794818421357835873">"Pokrenuti poslovne aplikacije?"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Zamijeni raspored tastature"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Brisanje upita za pretraživanje"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Prečice na tastaturi"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretraživanje prečica"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvaranje Asistenta"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Otvaranje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Otvaranje podijeljenog ekrana s trenutnom aplikacijom na lijevoj strani"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Korištenje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Korištenje podijeljenog ekrana s trenutnom aplikacijom na lijevoj strani"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prebacivanje s podijeljenog ekrana na prikaz preko cijelog ekrana"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pređite u aplikaciju desno ili ispod dok koristite podijeljeni ekran"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pređite u aplikaciju lijevo ili iznad dok koristite podijeljeni ekran"</string> diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml index e09cab50e9bb..df0b78664cba 100644 --- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Isključeno"</item> <item msgid="5137565285664080143">"Uključeno"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nedostupno"</item> + <item msgid="3079622119444911877">"Isključeno"</item> + <item msgid="3028994095749238254">"Uključeno"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 40532ca9f664..14456238cd63 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Registra el problema"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Inicia"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Atura"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"L\'experiència amb el dispositiu s\'ha vist afectada?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecciona el tipus de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravació de pantalla"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estàndard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mitjà"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alt"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audiòfons"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audiòfons"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincula un dispositiu nou"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fes clic per vincular un dispositiu nou"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vols desbloquejar el micròfon del dispositiu?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vols desbloquejar la càmera del dispositiu?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vols desbloquejar la càmera i el micròfon del dispositiu?"</string> @@ -745,12 +743,12 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Canvia disposició de teclat"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Esborra la consulta de cerca"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Dreceres"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tecles de drecera"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca dreceres"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No s\'ha trobat cap drecera"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Obre aplicacions"</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Aplicacions obertes"</string> <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplicació actual"</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"S\'estan mostrant els resultats de la cerca"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"S\'estan mostrant les dreceres del sistema"</string> @@ -768,11 +766,11 @@ <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Obre la llista d\'aplicacions"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Obre la configuració"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Obre l\'Assistent"</string> - <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueig"</string> + <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloqueja la pantalla"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Crea una nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasques del sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Entra al mode de pantalla dividida amb l\'aplicació actual a la dreta"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Entra al mode de pantalla dividida amb l\'aplicació actual a l\'esquerra"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasca"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utilitza la pantalla dividida amb l\'aplicació actual a la dreta"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utilitza la pantalla dividida amb l\'aplicació actual a l\'esquerra"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Canvia de pantalla dividida a pantalla completa"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Canvia a l\'aplicació de la dreta o de sota amb la pantalla dividida"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Canvia a l\'aplicació de l\'esquerra o de dalt amb la pantalla dividida"</string> diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml index 6a36b6f5b9d8..67eb853c9ee6 100644 --- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desactivat"</item> <item msgid="5137565285664080143">"Activat"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"No disponible"</item> + <item msgid="3079622119444911877">"Desactivat"</item> + <item msgid="3028994095749238254">"Activat"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 16c2914e32f7..7b766abc30b5 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Zaznamenat problém"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Spustit"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ukončit"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Co v zařízení bylo ovlivněno?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Vyberte druh problém"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Záznam obrazovky"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardní"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Střední"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Vysoká"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Naslouchátka"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Naslouchátka"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Spárovat nové zařízení"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zařízení"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokovat mikrofon zařízení?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokovat fotoaparát zařízení?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokovat fotoaparát a mikrofon zařízení?"</string> @@ -680,7 +678,7 @@ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny"</string> <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, deaktivuje režim Nerušit"</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny a deaktivuje režim Nerušit"</string> - <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string> + <string name="notification_priority_title" msgid="2079708866333537093">"Prioritní"</string> <string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string> <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tato oznámení nelze upravit."</string> <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornění na hovor nelze upravit."</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Přepnout rozložení klávesnice"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"nebo"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Vymazat vyhledávaný dotaz"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Zkratky"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klávesové zkratky"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Vyhledat zkratky"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Žádné zkratky nenalezeny"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systém"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otevřít Asistenta"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknout obrazovku"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Vytvořit poznámku"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systémový multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Přepnout na rozdělenou obrazovku s aktuálními aplikacemi napravo"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Přepnout na rozdělenou obrazovku s aktuálními aplikacemi nalevo"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Použít rozdělenou obrazovku se stávající aplikací vpravo"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Použít rozdělenou obrazovku se stávající aplikací vlevo"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Přepnout z rozdělené obrazovky na celou obrazovku"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Přechod na aplikaci vpravo nebo dole v režimu rozdělené obrazovky"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Přechod na aplikaci vlevo nebo nahoře v režimu rozdělené obrazovky"</string> @@ -1147,7 +1145,7 @@ <string name="audio_status" msgid="4237055636967709208">"Poslouchá"</string> <string name="game_status" msgid="1340694320630973259">"Hraji hru"</string> <string name="empty_user_name" msgid="3389155775773578300">"Přátelé"</string> - <string name="empty_status" msgid="5938893404951307749">"Proberem to večer?"</string> + <string name="empty_status" msgid="5938893404951307749">"Probereme to večer?"</string> <string name="status_before_loading" msgid="1500477307859631381">"Obsah se brzy zobrazí"</string> <string name="missed_call" msgid="4228016077700161689">"Zmeškaný hovor"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string> @@ -1269,7 +1267,7 @@ <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Nainstalovat pracovní telefonní aplikaci"</string> <string name="call_from_work_profile_close" msgid="5830072964434474143">"Zrušit"</string> <string name="lock_screen_settings" msgid="6152703934761402399">"Přizpůsobit obrazovku uzamčení"</string> - <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Pokud chcete upravit obrazovku uzamčení, odemkněte zařízení"</string> + <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Obrazovku uzamčení upravíte, když zařízení odemknete"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Síť Wi-Fi není dostupná"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokována"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofon jsou blokovány"</string> diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml index 02a0f5f792b0..ae533a8623ec 100644 --- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Vypnuto"</item> <item msgid="5137565285664080143">"Zapnuto"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Není k dispozici"</item> + <item msgid="3079622119444911877">"Vypnuto"</item> + <item msgid="3028994095749238254">"Zapnuto"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 4754dbb5cdb3..2100e275ed2a 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Optag problem"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Hvilken del af din enhedsoplevelse blev påvirket?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Vælg problemtype"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skærmoptagelse"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Middel"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Høj"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Høreapparater"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Par ny enhed"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik for at parre en ny enhed"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du fjerne blokeringen af enhedens mikrofon?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du fjerne blokeringen af enhedens kamera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vil du fjerne blokeringen af enhedens kamera og mikrofon?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skift tastaturlayout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ryd søgeforespørgsel"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Genveje"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tastaturgenveje"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søg efter genveje"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ingen genveje blev fundet"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Åbn Assistent"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skærm"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Skriv en note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systemmultitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Start opdelt skærm med aktuel app til højre"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Start opdelt skærm med aktuel app til venstre"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Brug opdelt skærm med aktuel app til højre"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Brug opdelt skærm med aktuel app til venstre"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Skift fra opdelt skærm til fuld skærm"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skift til en app til højre eller nedenfor, når du bruger opdelt skærm"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skift til en app til venstre eller ovenfor, når du bruger opdelt skærm"</string> diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml index 598fcfe40dc8..2c3b0535cb33 100644 --- a/packages/SystemUI/res/values-da/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Fra"</item> <item msgid="5137565285664080143">"Til"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Ikke tilgængelig"</item> + <item msgid="3079622119444911877">"Fra"</item> + <item msgid="3028994095749238254">"Til"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 2fd26bcd39b9..6c4f4b5f7c91 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problem aufnehmen"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Aufnahme starten"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Aufnahme beenden"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Welche Bereiche des Geräts waren betroffen?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Art des Problems auswählen"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Bildschirmaufnahme"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mittel"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hoch"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörgeräte"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hörgeräte"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Neues Gerät koppeln"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicken, um neues Gerät zu koppeln"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Blockierung des Gerätemikrofons aufheben?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Blockierung der Gerätekamera aufheben?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Blockierung von Gerätekamera und Gerätemikrofon aufheben?"</string> @@ -448,10 +446,8 @@ <string name="button_to_remove_widget" msgid="3948204829181214098">"Entfernen"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget hinzufügen"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Fertig"</string> - <!-- no translation found for label_for_button_in_empty_state_cta (7314975555382055823) --> - <skip /> - <!-- no translation found for title_for_empty_state_cta (6161654421223450530) --> - <skip /> + <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Widgets hinzufügen"</string> + <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Greife schnell auf deine App-Widgets zu, ohne das Tablet entsperren zu müssen."</string> <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Beliebige Widgets auf Sperrbildschirm zulassen?"</string> <string name="button_text_to_open_settings" msgid="1987729256950941628">"Einstellungen öffnen"</string> <string name="work_mode_off_title" msgid="5794818421357835873">"Geschäftliche Apps nicht mehr pausieren?"</string> @@ -747,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tastaturlayout wechseln"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"oder"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Suchanfrage löschen"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tastenkombinationen"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tastenkombinationen"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tastenkombinationen suchen"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Keine gefunden"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -772,16 +768,16 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant öffnen"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Sperrbildschirm"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Notiz machen"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System-Multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Splitscreen aktivieren, aktuelle App rechts"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Splitscreen aktivieren, aktuelle App links"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Splitscreen mit der aktuellen App auf der rechten Seite nutzen"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Splitscreen mit der aktuellen App auf der linken Seite nutzen"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Vom Splitscreen zum Vollbild wechseln"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Im Splitscreen-Modus rechts oder unten zu einer App wechseln"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Im Splitscreen-Modus links oder oben zu einer App wechseln"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Im Splitscreen-Modus zu einer App rechts oder unten wechseln"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Im Splitscreen-Modus zu einer App links oder oben wechseln"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Im Splitscreen: eine App durch eine andere ersetzen"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Eingabe"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Zur nächsten Sprache wechseln"</string> - <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Zu vorheriger Sprache wechseln"</string> + <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Zur vorherigen Sprache wechseln"</string> <string name="input_access_emoji" msgid="8105642858900406351">"Auf Emoji zugreifen"</string> <string name="input_access_voice_typing" msgid="7291201476395326141">"Auf Spracheingabe zugreifen"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Apps"</string> @@ -793,7 +789,7 @@ <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musik"</string> <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string> <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Rechner"</string> - <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Karten"</string> + <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string> <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Bitte nicht stören"</string> <string name="volume_dnd_silent" msgid="4154597281458298093">"Tastenkombination für Lautstärketasten"</string> <string name="battery" msgid="769686279459897127">"Akku"</string> diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml index 4b4eed53d1f4..0606cc79f2e9 100644 --- a/packages/SystemUI/res/values-de/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Aus"</item> <item msgid="5137565285664080143">"An"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nicht verfügbar"</item> + <item msgid="3079622119444911877">"Aus"</item> + <item msgid="3028994095749238254">"An"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 0c3f0d54caad..4c964de521fa 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Εγγραφή προβλήματος"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Έναρξη"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Διακοπή"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ποιο κομμάτι της εμπειρίας συσκευής επηρεάστηκε;"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Επιλογή τύπου προβλήματος"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Εγγραφή οθόνης"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Τυπική"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Μέτρια"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Υψηλή"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Συσκευές ακοής"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Συσκευές ακοής"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Σύζευξη νέας συσκευής"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Κάντε κλικ για σύζευξη νέας συσκευής"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Κατάργηση αποκλεισμού μικροφώνου συσκευής;"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Κατάργηση αποκλεισμού κάμερας συσκευής;"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Κατάργηση αποκλεισμού κάμερας και μικροφώνου συσκευής;"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Αλλαγή διάταξης πληκτρολογίου"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ή"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Διαγραφή ερωτήματος αναζήτησης"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Συντομεύσεις"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Συντομεύσ. πληκτρολογίου"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Αναζήτηση συντομεύσεων"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Δεν βρέθηκαν συντομεύσεις"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Σύστημα"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Άνοιγμα Βοηθού"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Κλείδωμα οθόνης"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Δημιουργία σημείωσης"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Πολυδιεργασία συστήματος"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Ενεργοποίηση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα δεξιά"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Ενεργοποίηση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα αριστερά"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Πολυδιεργασία"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Χρήση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα δεξιά"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Χρήση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα αριστερά"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Εναλλαγή από διαχωρισμό οθόνης σε πλήρη οθόνη"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Εναλλαγή στην εφαρμογή δεξιά ή κάτω κατά τη χρήση διαχωρισμού οθόνης"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Εναλλαγή σε εφαρμογή αριστερά ή επάνω κατά τη χρήση διαχωρισμού οθόνης"</string> diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml index e4c6854a2f30..d4545ffa6641 100644 --- a/packages/SystemUI/res/values-el/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Ανενεργό"</item> <item msgid="5137565285664080143">"Ενεργό"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Μη διαθέσιμη"</item> + <item msgid="3079622119444911877">"Ανενεργή"</item> + <item msgid="3028994095749238254">"Ενεργή"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index a8848a581386..fc27f16f7a88 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"High"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -551,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked, too many authentication attempts"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked – too many authentication attempts"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Device locked\nFailed authentication"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard shortcuts"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string> diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml index 304abe108492..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Off"</item> <item msgid="5137565285664080143">"On"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Unavailable"</item> + <item msgid="3079622119444911877">"Off"</item> + <item msgid="3028994095749238254">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 4b69255b6c96..088f75184889 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Record Issue"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bug Report"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string> @@ -741,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard Shortcuts"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -766,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to app on right or below while using split screen"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to app on left or above while using split screen"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index a8848a581386..fc27f16f7a88 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"High"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -551,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked, too many authentication attempts"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked – too many authentication attempts"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Device locked\nFailed authentication"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard shortcuts"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string> diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml index 304abe108492..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Off"</item> <item msgid="5137565285664080143">"On"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Unavailable"</item> + <item msgid="3079622119444911877">"Off"</item> + <item msgid="3028994095749238254">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index a8848a581386..fc27f16f7a88 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"High"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -551,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked, too many authentication attempts"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked – too many authentication attempts"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Device locked\nFailed authentication"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard shortcuts"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string> diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml index 304abe108492..39dd7c84b13e 100644 --- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Off"</item> <item msgid="5137565285664080143">"On"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Unavailable"</item> + <item msgid="3079622119444911877">"Off"</item> + <item msgid="3028994095749238254">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 3ed9fc5184df..958c6456cd6f 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Record Issue"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bug Report"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string> @@ -741,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard Shortcuts"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -766,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to app on right or below while using split screen"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to app on left or above while using split screen"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 3755fb6fde5a..b625dc5cfd09 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Grabar error"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Detener"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"¿Qué parte de tu exp. del disp. se vio afectada?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Seleccionar tipo de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Grabadora de pant."</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estándar"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular dispositivo nuevo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para vincular un dispositivo nuevo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Quieres desbloquear el micrófono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Quieres desbloquear la cámara del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Quieres desbloquear la cámara y el micrófono del dispositivo?"</string> @@ -668,7 +666,7 @@ <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string> <string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string> <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sin sonido ni vibración"</string> - <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en la parte inferior de la sección de conversaciones."</string> + <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en la parte inferior de la sección de conversaciones"</string> <string name="notification_channel_summary_default" msgid="777294388712200605">"Puede sonar o vibrar según la configuración del dispositivo"</string> <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Puede sonar o vibrar según la configuración del dispositivo. Conversaciones de la burbuja de <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string> <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Dejar que el sistema determine si esta notificación debe emitir un sonido o una vibración"</string> @@ -715,7 +713,7 @@ <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Flecha hacia arriba"</string> <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Flecha hacia abajo"</string> <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha a la izquierda"</string> - <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha hacia la derecha"</string> + <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha a la derecha"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centro"</string> <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Espacio"</string> @@ -743,10 +741,10 @@ <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificaciones"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ver combinaciones de teclas"</string> <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string> - <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o bien"</string> + <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar búsqueda"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string> - <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar comb. de teclas"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Combinaciones de teclas"</string> + <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar combinaciones de teclas"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No hay comb. de teclas"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string> @@ -770,12 +768,12 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Asistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloquear la pantalla"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Crear una nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Tareas múltiples del sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Activar pantalla dividida con la app actual en el lado derecho (RHS)"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Activar pantalla dividida con la app actual en el lado izquierdo (LHS)"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Tareas múltiples"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar la pantalla dividida con la app actual a la derecha"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar la pantalla dividida con la app actual a la izquierda"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Cambiar de pantalla dividida a pantalla completa"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ubica la app a la derecha o abajo cuando usas la pantalla dividida"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ubica la app a la izquierda o arriba cuando usas la pantalla dividida"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ubicar la app a la derecha o abajo cuando usas la pantalla dividida"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ubicar la app a la izquierda o arriba cuando usas la pantalla dividida"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Durante pantalla dividida: Reemplaza una app con otra"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Cambiar al próximo idioma"</string> @@ -1194,7 +1192,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está activa}many{# apps están activas}other{# apps están activas}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nueva información"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps activas"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas apps están activas y en ejecución, incluso mientras no las usas. Esto mejora su funcionalidad, pero también afecta la duración de batería."</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas apps están activas y en ejecución, incluso mientras no las usas. Esto mejora su funcionalidad, pero también afecta la duración de la batería."</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Detener"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Detenida"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Listo"</string> diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml index 71efef961b89..869efff07bdf 100644 --- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desactivado"</item> <item msgid="5137565285664080143">"Activado"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"No disponibles"</item> + <item msgid="3079622119444911877">"Desactivados"</item> + <item msgid="3028994095749238254">"Activados"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 01afa2903bf6..583a18116222 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problema de grabación"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Detener"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"¿Qué parte de tu experiencia se ha visto afectada?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecciona el tipo de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Grabar pantalla"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estándar"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audífonos"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audífonos"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Emparejar nuevo dispositivo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para emparejar un nuevo dispositivo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Desbloquear el micrófono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Desbloquear la cámara del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Desbloquear la cámara y el micrófono del dispositivo?"</string> @@ -714,8 +712,8 @@ <string name="keyboard_key_back" msgid="4185420465469481999">"Atrás"</string> <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Flecha hacia arriba"</string> <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Flecha hacia abajo"</string> - <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha hacia la izquierda"</string> - <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha hacia la derecha"</string> + <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha izquierda"</string> + <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha derecha"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centro"</string> <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabulador"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Espacio"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar la consulta de búsqueda"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Combinaciones de teclas"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar combinaciones de teclas"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ninguna encontrada"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -769,10 +767,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir ajustes"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir el Asistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Escribe una nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Función multitarea del sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Iniciar pantalla dividida con esta aplicación en el lado derecho"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Iniciar pantalla dividida con esta aplicación en el lado izquierdo"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Escribir una nota"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarea"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar la pantalla dividida con la aplicación actual a la derecha"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar la pantalla dividida con la aplicación actual a la izquierda"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Cambiar de pantalla dividida a pantalla completa"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Cambiar a la app de la derecha o de abajo en pantalla dividida"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Cambiar a la app de la izquierda o de arriba en pantalla dividida"</string> diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml index bd90056382e6..5dbb2c132f4c 100644 --- a/packages/SystemUI/res/values-es/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desactivado"</item> <item msgid="5137565285664080143">"Activado"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"No disponibles"</item> + <item msgid="3079622119444911877">"Desactivados"</item> + <item msgid="3028994095749238254">"Activados"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 52cbb0f56b2c..190c002fb033 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Probleemi salvestamine"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Alusta"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Peata"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Millist seadme kasutuskogemuse osa see mõjutas?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Valige probleemi tüüp"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekraanisalvestus"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Tavaline"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Keskmine"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Kõrge"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuuldeseadmed"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuuldeseadmed"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uue seadme sidumine"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Uue seadme sidumiseks klõpsake"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kas tühistada seadme mikrofoni blokeerimine?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kas tühistada seadme kaamera blokeerimine?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kas tühistada seadme kaamera ja mikrofoni blokeerimine?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatuuripaigutuse vahetus"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"või"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Otsingupäringu tühjendamine"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Otseteed"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klaviatuuri otseteed"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Otseteede otsing"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Otseteid ei leitud"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Süsteem"</string> @@ -769,10 +767,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Seadete avamine"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistendi avamine"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukustuskuva"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Kirjuta märkus"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Süsteemi multitegumtöö"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Ekraanikuva jagamine, nii et praegune rakendus on paremal"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Ekraanikuva jagamine, nii et praegune rakendus on vasakul"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Märkme tegemine"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitegumtöö"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Jagatud ekraanikuva kasutamine, praegune rakendus kuvatakse paremal"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Jagatud ekraanikuva kasutamine, praegune rakendus kuvatakse vasakul"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Jagatud ekraanikuvalt täisekraanile lülitamine"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Paremale või alumisele rakendusele lülitamine jagatud ekraani ajal"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vasakule või ülemisele rakendusele lülitamine jagatud ekraani ajal"</string> diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml index 55bff30d3071..704649e77b86 100644 --- a/packages/SystemUI/res/values-et/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Väljas"</item> <item msgid="5137565285664080143">"Sees"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Pole saadaval"</item> + <item msgid="3079622119444911877">"Välja lülitatud"</item> + <item msgid="3028994095749238254">"Sisse lülitatud"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index b0056f655ee1..b60df6f99b60 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -329,13 +329,13 @@ <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Laneko aplikazioak"</string> <string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"Pausatuta"</string> <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Gaueko argia"</string> - <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ilunabarrean"</string> + <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ilunabarrean aktibatuta"</string> <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Ilunabarrera arte"</string> <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string> <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> arte"</string> <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Gai iluna"</string> <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Bateria-aurreztailea"</string> - <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuko da"</string> + <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuta"</string> <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string> <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string> <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Desaktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Arazo bat dago grabaketarekin"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Hasi"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Gelditu"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Gailuaren erabileraren zer alderdiri eragin dio?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Hautatu arazo mota"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Pantaila-grabaketa"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Arrunta"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Tartekoa"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Altua"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Entzumen-gailuak"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Entzumen-gailuak"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parekatu beste gailu bat"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Egin klik beste gailu bat parekatzeko"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Gailuaren mikrofonoa desblokeatu nahi duzu?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Gailuaren kamera desblokeatu nahi duzu?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Gailuaren kamera eta mikrofonoa desblokeatu nahi dituzu?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"edo"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Garbitu bilaketa-kontsulta"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lasterbideak"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Lasterbideak"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Bilatu lasterbideak"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ez da aurkitu lasterbiderik"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ireki Laguntzailea"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Egin ohar bat"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Zereginen aldibereko sistemaren exekuzioa"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Sartu pantaila zatituaren eskuineko aldean oraingo aplikazioarekin"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Sartu pantaila zatituaren ezkerreko aldean oraingo aplikazioarekin"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Zeregin bat baino gehiago aldi berean exekutatzea"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Erabili pantaila zatitua eta ezarri aplikazio hau eskuinean"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Erabili pantaila zatitua eta ezarri aplikazio hau ezkerrean"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Aldatu pantaila zatitutik pantaila osora"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Aldatu eskuineko edo beheko aplikaziora pantaila zatitua erabiltzean"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Aldatu ezkerreko edo goiko aplikaziora pantaila zatitua erabiltzean"</string> @@ -790,8 +788,8 @@ <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMSak"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musika"</string> <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string> - <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Ireki Kalkulagailua"</string> - <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ireki Maps"</string> + <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulagailua"</string> + <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string> <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ez molestatzeko modua"</string> <string name="volume_dnd_silent" msgid="4154597281458298093">"Bolumen-botoietarako lasterbidea"</string> <string name="battery" msgid="769686279459897127">"Bateria"</string> @@ -1125,7 +1123,7 @@ <string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string> <string name="select_conversation_title" msgid="6716364118095089519">"Elkarrizketa-widgetak"</string> <string name="select_conversation_text" msgid="3376048251434956013">"Sakatu elkarrizketa bat orri nagusian gehitzeko"</string> - <string name="no_conversations_text" msgid="5354115541282395015">"Azken elkarrizketak agertuko dira hemen"</string> + <string name="no_conversations_text" msgid="5354115541282395015">"Azkenaldiko elkarrizketak agertuko dira hemen"</string> <string name="priority_conversations" msgid="3967482288896653039">"Lehentasunezko elkarrizketak"</string> <string name="recent_conversations" msgid="8531874684782574622">"Azken elkarrizketak"</string> <string name="days_timestamp" msgid="5821854736213214331">"Duela <xliff:g id="DURATION">%1$s</xliff:g> egun"</string> @@ -1151,7 +1149,7 @@ <string name="status_before_loading" msgid="1500477307859631381">"Laster agertuko da edukia"</string> <string name="missed_call" msgid="4228016077700161689">"Dei galdua"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string> - <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerari buruzko informazio eguneratua"</string> + <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerei buruzko informazio eguneratua"</string> <string name="people_tile_title" msgid="6589377493334871272">"Elkarrizketa"</string> <string name="paused_by_dnd" msgid="7856941866433556428">"Ez molestatzeko moduak pausatu du"</string> <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak mezu bat bidali du: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml index 7f38d4486600..13e14e0502c4 100644 --- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desaktibatuta"</item> <item msgid="5137565285664080143">"Aktibatuta"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Ez daude erabilgarri"</item> + <item msgid="3079622119444911877">"Desaktibatuta"</item> + <item msgid="3028994095749238254">"Aktibatuta"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index de97db354f37..0c53fa01d903 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ضبط مشکل"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"شروع"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"توقف"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"گزارش اشکال"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"کدام بخش تجربه استفاده از دستگاه تحتتأثیر قرار گرفت؟"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"انتخاب نوع مشکل"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ضبط صفحهنمایش"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"استاندارد"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"متوسط"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"بالا"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سمعک"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سمعک"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"جفت کردن دستگاه جدید"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"برای جفت کردن دستگاه جدید، کلیک کنید"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"میکروفون دستگاه لغو انسداد شود؟"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"دوربین دستگاه لغو انسداد شود؟"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"دوربین و میکروفون دستگاه لغو انسداد شود؟"</string> @@ -551,7 +548,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"این دستگاه را ولیتان مدیریت میکند. ولیتان میتواند اطلاعاتی مثل برنامههایی که استفاده میکنید، مکانتان، و مدت تماشای صفحهتان را ببیند و مدیریت کند."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"با TrustAgent قفل را باز نگهدارید"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"دستگاه قفل شد، تعداد تلاشها برای اصالتسنجی بسیار زیاد بود"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"بهدلیل تلاشهای بیشاز حد برای اصالتسنجی، دستگاه قفل شد"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"دستگاه قفل شد\nاصالتسنجی ناموفق بود"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"تنظیمات صدا"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر جانمایی صفحهکلید"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"یا"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"پاک کردن پُرسمان جستجو"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"میانبرها"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"میانبرهای صفحهکلید"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"جستجوی میانبرها"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"میانبری پیدا نشد"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"سیستم"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"باز کردن «دستیار»"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"قفل صفحه"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"یادداشتبرداری"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"چندوظیفگی سیستم"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"وارد شدن به صفحهٔ دونیمه با برنامه فعلی در سمت راست"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"وارد شدن به صفحهٔ دونیمه با برنامه فعلی در سمت چپ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"چندوظیفگی"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"استفاده از صفحهٔ دونیمه با برنامه فعلی در سمت راست"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"استفاده از صفحهٔ دونیمه با برنامه فعلی در سمت چپ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"جابهجایی از صفحهٔ دونیمه به تمام صفحه"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"رفتن به برنامه سمت راست یا پایین درحین استفاده از صفحهٔ دونیمه"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"رفتن به برنامه سمت چپ یا بالا درحین استفاده از صفحهٔ دونیمه"</string> diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml index 9a6b1af3ad6b..756b442f5fc4 100644 --- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"خاموش"</item> <item msgid="5137565285664080143">"روشن"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"دردسترس نیست"</item> + <item msgid="3079622119444911877">"خاموش"</item> + <item msgid="3028994095749238254">"روشن"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 55413a01695e..3c90847483cc 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -120,7 +120,7 @@ <string name="screenrecord_stop_label" msgid="72699670052087989">"Lopeta"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"Jaa"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"Näyttötallenne tallennettu"</string> - <string name="screenrecord_save_text" msgid="3008973099800840163">"Napauta näyttääksesi"</string> + <string name="screenrecord_save_text" msgid="3008973099800840163">"Katso napauttamalla"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"Virhe näyttötallenteen tallentamisessa"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Virhe näytön tallennuksen aloituksessa"</string> <string name="issuerecord_title" msgid="286627115110121849">"Ongelman tallentaja"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Tallenna ongelma"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Aloita"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Lopeta"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Mitä osaa käyttökokemuksesta ongelma koski?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Valitse ongelman tyyppi"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Näytön tallentaja"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Tavallinen"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Keskitaso"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Suuri"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuulolaitteet"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuulolaitteet"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Muodosta uusi laitepari"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Muodosta uusi laitepari klikkaamalla"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kumotaanko laitteen mikrofonin esto?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kumotaanko laitteen kameran esto?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kumotaanko laitteen kameran ja mikrofonin esto?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Vaihda näppäimistöasettelu"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"tai"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Tyhjennä hakulauseke"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pikanäppäimet"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Pikanäppäimet"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hae pikanäppäimiä"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Pikanäppäimiä ei löytynyt"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Järjestelmä"</string> @@ -770,17 +768,17 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Avaa Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukitusnäyttö"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Tee muistiinpano"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Järjestelmän monikäyttö"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Siirry jaettuun näyttöön (sovellus oikeanpuoleiseen näyttöön)"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Siirry jaettuun näyttöön (sovellus vasemmanpuoleiseen näyttöön)"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitaskaus"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Käytä jaettua näyttöä niin, että nyt käytettävä sovellus on oikealla"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Käytä jaettua näyttöä niin, että nyt käytettävä sovellus on vasemmalla"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Vaihda jaetusta näytöstä koko näyttöön"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Vaihda sovellukseen oikealla tai alapuolella jaetun näytön avulla"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vaihda sovellukseen vasemmalla tai yläpuolella jaetun näytön avulla"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Vaihda sovellukseen oikealla tai alapuolella jaetussa näytössä"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vaihda sovellukseen vasemmalla tai yläpuolella jaetussa näytössä"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Jaetun näytön aikana: korvaa sovellus toisella"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Syöttötapa"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Vaihda seuraavaan kieleen"</string> <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Vaihda aiempaan kieleen"</string> - <string name="input_access_emoji" msgid="8105642858900406351">"Emojin käyttö"</string> + <string name="input_access_emoji" msgid="8105642858900406351">"Emojien käyttö"</string> <string name="input_access_voice_typing" msgid="7291201476395326141">"Puhekirjoituksen käyttö"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Sovellukset"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Assistant"</string> @@ -1194,7 +1192,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# sovellus on aktiivinen}other{# sovellusta aktiivisena}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Uutta tietoa"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktiiviset sovellukset"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Nämä sovellukset ovat aktiivisia ja ne ovat käynnissä, vaikka et käyttäisi niitä. Näin sovellusten toimivuus paranee, mutta se voi vaikutta akunkestoon."</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Nämä sovellukset ovat aktiivisia ja käynnissä, vaikka et käyttäisi niitä. Näin sovellusten toimivuus paranee, mutta ne voivat vaikuttaa akunkestoon."</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Pysäytä"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Pysäytetty"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Valmis"</string> @@ -1269,7 +1267,7 @@ <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Asenna työpuhelinsovellus"</string> <string name="call_from_work_profile_close" msgid="5830072964434474143">"Peruuta"</string> <string name="lock_screen_settings" msgid="6152703934761402399">"Muokkaa lukitusnäyttöä"</string> - <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Avaa lukitus muokataksesi lukitusnäyttöä"</string> + <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Voit muokata lukitusnäyttöä, kun avaat lukituksen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi-yhteys ei ole käytettävissä"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera estetty"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ja mikrofoni estetty"</string> diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml index f1e3e614cb70..5ecc95956d1c 100644 --- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Pois päältä"</item> <item msgid="5137565285664080143">"Päällä"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Ei saatavilla"</item> + <item msgid="3079622119444911877">"Pois päältä"</item> + <item msgid="3028994095749238254">"Päällä"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-fr-feminine/strings.xml b/packages/SystemUI/res/values-fr-feminine/strings.xml index ebdc3fb236aa..16c16e149b9e 100644 --- a/packages/SystemUI/res/values-fr-feminine/strings.xml +++ b/packages/SystemUI/res/values-fr-feminine/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> - <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> + <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invitée"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-masculine/strings.xml b/packages/SystemUI/res/values-fr-masculine/strings.xml index 6b9497061c56..411af1fecda2 100644 --- a/packages/SystemUI/res/values-fr-masculine/strings.xml +++ b/packages/SystemUI/res/values-fr-masculine/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> - <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> + <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-neuter/strings.xml b/packages/SystemUI/res/values-fr-neuter/strings.xml index e9d01914a638..4a4ac5a61eeb 100644 --- a/packages/SystemUI/res/values-fr-neuter/strings.xml +++ b/packages/SystemUI/res/values-fr-neuter/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> - <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> + <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité·e"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 272e00e5c7b3..cb56ba93b2bd 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Rapporter le problème"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Commencer"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Arrêter"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Quelle composante de l\'appareil a été affectée?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Sélectionner un type"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Enregistrement écran"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Moyen"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Élevé"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquez ici pour associer un nouvel appareil"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le microphone de l\'appareil?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer l\'appareil photo de l\'appareil?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le microphone?"</string> @@ -448,10 +446,8 @@ <string name="button_to_remove_widget" msgid="3948204829181214098">"Retirer"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ajouter un widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Terminé"</string> - <!-- no translation found for label_for_button_in_empty_state_cta (7314975555382055823) --> - <skip /> - <!-- no translation found for title_for_empty_state_cta (6161654421223450530) --> - <skip /> + <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Ajouter des widgets"</string> + <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Accédez rapidement aux widgets de vos applications préférées sans déverrouiller votre tablette."</string> <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Autoriser n\'importe quel widget sur l\'écran de verrouillage?"</string> <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ouvrir les paramètres"</string> <string name="work_mode_off_title" msgid="5794818421357835873">"Réactiver les applis pros?"</string> @@ -553,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par ton parent. Ton parent peut voir et gérer de l\'information, comme les applications que tu utilises, ta position et ton temps d\'utilisation des écrans."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"RPV"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Maintenu déverrouillé par TrustAgent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"L\'appareil a été verrouillé, trop de tentatives d\'authentification"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"L\'appareil a été verrouillé : trop de tentatives d\'authentification"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Appareil verrouillé\nÉchec de l\'authentification"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Paramètres sonores"</string> @@ -747,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Effacez la requête de recherche"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Raccourcis-clavier"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Recherchez des raccourcis"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string> @@ -772,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ouvrir l\'Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Écran de verrouillage"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Prendre une note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Passer à l\'écran divisé avec l\'application actuelle à droite"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Passer à l\'écran divisé avec l\'application actuelle à gauche"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitâche"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utiliser l\'Écran divisé avec l\'application actuelle à droite"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utiliser l\'Écran divisé avec l\'application actuelle à gauche"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Passer de l\'écran divisé au plein écran"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passer à l\'application à droite ou en dessous avec l\'Écran divisé"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passer à l\'application à gauche ou au-dessus avec l\'Écran divisé"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml index dfea45ac8d84..52b763b4028d 100644 --- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Désactivée"</item> <item msgid="5137565285664080143">"Activée"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Non accessible"</item> + <item msgid="3079622119444911877">"Désactivé"</item> + <item msgid="3028994095749238254">"Activé"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 41f9249c0fbc..15235dee3724 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -286,7 +286,7 @@ <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotation automatique de l\'écran"</string> <string name="quick_settings_location_label" msgid="2621868789013389163">"Localisation"</string> <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Économiseur d\'écran"</string> - <string name="quick_settings_camera_label" msgid="5612076679385269339">"Accès à la caméra"</string> + <string name="quick_settings_camera_label" msgid="5612076679385269339">"Accès à l\'appareil photo"</string> <string name="quick_settings_mic_label" msgid="8392773746295266375">"Accès au micro"</string> <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponible"</string> <string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloqué"</string> @@ -298,7 +298,7 @@ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Réseaux non disponibles"</string> <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Aucun réseau Wi-Fi disponible"</string> <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Activation…"</string> - <string name="quick_settings_cast_title" msgid="2279220930629235211">"Diffusion de l\'écran"</string> + <string name="quick_settings_cast_title" msgid="2279220930629235211">"Diffusion écran"</string> <string name="quick_settings_casting" msgid="1435880708719268055">"Diffusion"</string> <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Appareil sans nom"</string> <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Aucun appareil disponible."</string> @@ -344,12 +344,14 @@ <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string> <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string> <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string> - <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Enregistrement de l\'écran"</string> + <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Enregistr. écran"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string> <string name="qs_record_issue_label" msgid="8166290137285529059">"Enregistrer le problème"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Début"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Arrêter"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Quel problème avez-vous rencontré avec votre appareil ?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Sélectionnez un type de problème"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Enregistrement de l\'écran"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Moyen"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Élevé"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Prothèses auditives"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquer pour associer un nouvel appareil"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le micro de l\'appareil ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer la caméra de l\'appareil ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le micro de l\'appareil ?"</string> @@ -400,7 +398,7 @@ <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'écran Récents"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> - <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> + <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personnaliser"</string> <string name="zen_silence_introduction_voice" msgid="853573681302712348">"Cette option permet de bloquer TOUS les sons et les vibrations, y compris pour les alarmes, la musique, les vidéos et les jeux. Vous pourrez encore passer des appels téléphoniques."</string> <string name="zen_silence_introduction" msgid="6117517737057344014">"Cette option permet de bloquer TOUS les sons et les vibrations, y compris pour les alarmes, la musique, les vidéos et les jeux."</string> @@ -637,7 +635,7 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string> - <string name="qr_code_scanner_title" msgid="1938155688725760702">"Lecteur de code QR"</string> + <string name="qr_code_scanner_title" msgid="1938155688725760702">"Lecteur code QR"</string> <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mise à jour"</string> <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string> @@ -745,8 +743,8 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer disposition du clavier"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Effacer la requête de recherche"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string> - <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Raccourcis de recherche"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Raccourcis clavier"</string> + <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Rechercher des raccourcis"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Saisie"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ouvrir l\'Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Verrouiller l\'écran"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Créer une note"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Passer en écran partagé avec l\'appli actuelle affichée à droite"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Passer en écran partagé avec l\'appli actuelle affichée à gauche"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitâche"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utiliser l\'écran partagé avec l\'appli actuelle sur la droite"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utiliser l\'écran partagé avec l\'appli actuelle sur la gauche"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Passer de l\'écran partagé au plein écran"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passez à l\'appli à droite ou en dessous avec l\'écran partagé"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passez à l\'appli à gauche ou au-dessus avec l\'écran partagé"</string> @@ -1247,7 +1245,7 @@ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="604424593994493281">"• Au moins un appareil ou un panneau de l\'appareil est disponible"</string> <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Sélectionnez une appli de notes par défaut pour utiliser le raccourci de prise de notes"</string> <string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Sélectionner une appli"</string> - <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur raccourci"</string> + <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur le raccourci"</string> <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string> <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Changer d\'écran maintenant"</string> <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Déplier le téléphone"</string> @@ -1269,7 +1267,7 @@ <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installer une appli professionnelle pour téléphoner"</string> <string name="call_from_work_profile_close" msgid="5830072964434474143">"Annuler"</string> <string name="lock_screen_settings" msgid="6152703934761402399">"Personnaliser écran verrouillage"</string> - <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouiller pour personnaliser l\'écran de verrouillage"</string> + <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouillez pour personnaliser l\'écran de verrouillage"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string> @@ -1284,7 +1282,7 @@ <string name="mirror_display" msgid="2515262008898122928">"Dupliquer l\'écran"</string> <string name="dismiss_dialog" msgid="2195508495854675882">"Fermer"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"Écran connecté"</string> - <string name="privacy_dialog_title" msgid="7839968133469098311">"Micro et caméra"</string> + <string name="privacy_dialog_title" msgid="7839968133469098311">"Micro et appareil photo"</string> <string name="privacy_dialog_summary" msgid="2458769652125995409">"Utilisation récente par les applis"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Consulter les accès récents"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"OK"</string> diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml index 34ccb7517615..23c124cce37a 100644 --- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml @@ -88,8 +88,8 @@ </string-array> <string-array name="tile_states_color_correction"> <item msgid="2840507878437297682">"Indisponible"</item> - <item msgid="1909756493418256167">"Désactivé"</item> - <item msgid="4531508423703413340">"Activé"</item> + <item msgid="1909756493418256167">"Désactivée"</item> + <item msgid="4531508423703413340">"Activée"</item> </string-array> <string-array name="tile_states_inversion"> <item msgid="3638187931191394628">"Indisponible"</item> @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Désactivé"</item> <item msgid="5137565285664080143">"Activé"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Non disponible"</item> + <item msgid="3079622119444911877">"Désactivé"</item> + <item msgid="3028994095749238254">"Activé"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 189f048a5c17..7f4ae81e6f6e 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Rexistrar problema"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Deter"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cal foi o problema na experiencia co dispositivo?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecciona o tipo de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravación de pant."</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Nivel estándar"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Nivel medio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Nivel alto"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular un dispositivo novo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic para vincular un novo dispositivo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Queres desbloquear o micrófono do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Queres desbloquear a cámara do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Queres desbloquear a cámara e o micrófono do dispositivo?"</string> @@ -632,7 +630,7 @@ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura un método de pago para comprar de xeito máis rápido e seguro co teléfono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Amosar todo"</string> - <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Tocar para abrir"</string> + <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Toca para abrir"</string> <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Actualizando"</string> <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar deseño do teclado"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar a busca"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atallos"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atallos de teclado"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar atallos"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Non se atoparon atallos"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Asistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Crear nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Activar pantalla dividida con esta aplicación no lado dereito"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Activar pantalla dividida con esta aplicación no lado esquerdo"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefa"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar pantalla dividida coa aplicación actual na dereita"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar pantalla dividida coa aplicación actual na esquerda"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Cambiar de pantalla dividida a pantalla completa"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Cambiar á aplicación da dereita ou de abaixo coa pantalla dividida"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Cambiar á aplicación da esquerda ou de arriba coa pantalla dividida"</string> diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml index de8ee63907aa..03b934eb9cb6 100644 --- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desactivado"</item> <item msgid="5137565285664080143">"Activado"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Non dispoñibles"</item> + <item msgid="3079622119444911877">"Desactivados"</item> + <item msgid="3028994095749238254">"Activados"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 54312e159c62..9425774f47c3 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -333,7 +333,7 @@ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"સૂર્યોદય સુધી"</string> <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે"</string> <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> સુધી"</string> - <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ઘેરી થીમ"</string> + <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ડાર્ક થીમ"</string> <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"બૅટરી સેવર"</string> <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"સૂર્યાસ્ત વખતે"</string> <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"રેકોર્ડિંગમાં સમસ્યા"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"શરૂ કરો"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"રોકો"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"બગ રિપોર્ટ"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ડિવાઇસ સંબંધી તમારા અનુભવના કયા ભાગને અસર થઈ હતી?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"સમસ્યાનો પ્રકાર પસંદ કરો"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"સ્ક્રીન રેકોર્ડ કરો"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"સ્ટૅન્ડર્ડ"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"મધ્યમ"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"વધુ"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"નવા ડિવાઇસ સાથે જોડાણ કરવા માટે ક્લિક કરો"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ડિવાઇસના માઇક્રોફોનને અનબ્લૉક કરીએ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ડિવાઇસના કૅમેરાને અનબ્લૉક કરીએ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ડિવાઇસના કૅમેરા અને માઇક્રોફોનને અનબ્લૉક કરીએ?"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"કીબોર્ડ લેઆઉટ સ્વિચ કરો"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"અથવા"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"શોધ ક્વેરી સાફ કરો"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"શૉર્ટકટ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"કીબોર્ડ શૉર્ટકટ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"શૉર્ટકટ શોધો"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"કોઈ શૉર્ટકટ મળ્યો નથી"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"સિસ્ટમ"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ખોલો"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"લૉક સ્ક્રીન"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"નોંધ લો"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"સિસ્ટમ દ્વારા એકથી વધુ કાર્યો કરવા"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"જમણી બાજુ પર હાલની ઍપ સાથે વિભાજિત સ્ક્રીનમાં દાખલ થાઓ"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"ડાબી બાજુ પર હાલની ઍપ સાથે વિભાજિત સ્ક્રીનમાં દાખલ થાઓ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"એકસાથે એકથી વધુ કાર્યો કરવા"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"જમણી બાજુએ વર્તમાન ઍપ સાથે વિભાજિત સ્ક્રીનનો ઉપયોગ કરો"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ડાબી બાજુએ વર્તમાન ઍપ સાથે વિભાજિત સ્ક્રીનનો ઉપયોગ કરો"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"વિભાજિત સ્ક્રીનથી પૂર્ણ સ્ક્રીન પર સ્વિચ કરો"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરતી વખતે જમણી બાજુ કે નીચેની ઍપ પર સ્વિચ કરો"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરતી વખતે ડાબી બાજુની કે ઉપરની ઍપ પર સ્વિચ કરો"</string> diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml index c6a86e550f7a..5c4a4784c13f 100644 --- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"બંધ"</item> <item msgid="5137565285664080143">"ચાલુ"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"અનુપલબ્ધ"</item> + <item msgid="3079622119444911877">"બંધ છે"</item> + <item msgid="3028994095749238254">"ચાલુ છે"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index ee3e40b7f6ac..e4291aca6c8a 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"समस्या रिकॉर्ड करें"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"शुरू करें"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"रोकें"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"गड़बड़ी की रिपोर्ट"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"आपके डिवाइस की कौनसी सुविधा पर असर पड़ा था?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"समस्या का टाइप चुनें"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"स्क्रीन रिकॉर्डर"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"स्टैंडर्ड"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"सामान्य"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ज़्यादा"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"कान की मशीनें"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"कान की मशीनें"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नया डिवाइस जोड़ें"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नया डिवाइस जोड़ने के लिए क्लिक करें"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आपको डिवाइस का माइक्रोफ़ोन अनब्लॉक करना है?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आपको डिवाइस का कैमरा अनब्लॉक करना है?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस का कैमरा और माइक्रोफ़ोन अनब्लॉक करना चाहते हैं?"</string> @@ -552,7 +549,7 @@ <string name="legacy_vpn_name" msgid="4174223520162559145">"वीपीएन"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent की वजह से अनलॉक रखा गया है"</string> <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"कई बार पुष्टि करने की कोशिश की वजह से, डिवाइस लॉक है"</string> - <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"डिवाइस लॉक है\nपुष्टि नहीं की जा सकी."</string> + <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"डिवाइस लॉक हो गया है\nपुष्टि नहीं की जा सकी"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"साउंड सेटिंग"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ऑडियो-वीडियो से अपने-आप कैप्शन बनना"</string> @@ -678,7 +675,7 @@ <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>स्थिति:</b> रैंकिंग में नीचे किया गया"</string> <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"यह कई तरीकों से दिखती है, जैसे कि लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर और बातचीत वाली सूचनाओं में सबसे ऊपर"</string> <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"यह कई तरीकों से दिखती है, जैसे कि बातचीत वाली सूचनाओं में सबसे ऊपर, बबल के तौर पर, और लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर"</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"यह कई तरीकों से दिखती है, जैसे कि लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर और बातचीत वाली सूचनाओं में सबसे ऊपर. साथ ही, इसकी वजह से, \'परेशान न करें\' सुविधा में भी रुकावट आती है"</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"यह लॉक स्क्रीन पर, बातचीत वाली सूचनाओं में सबसे ऊपर और प्रोफ़ाइल फ़ोटो के साथ दिखती है. साथ ही, यह \'परेशान न करें\' मोड को बायपास कर सकती है."</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"यह कई तरीकों से दिखती है, जैसे कि बातचीत वाली सूचनाओं में सबसे ऊपर, बबल के तौर पर, और लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर. साथ ही, यह \'परेशान न करें\' मोड को बायपास कर सकती है"</string> <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string> <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर बातचीत की सुविधाएं काम नहीं करतीं"</string> @@ -745,12 +742,12 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट बदलें"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"या"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"सर्च क्वेरी साफ़ करें"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"कीबोर्ड शॉर्टकट"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"शॉर्टकट खोजें"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"कोई शॉर्टकट नहीं मिला"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"सिस्टम"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"खुले हुए ऐप्लिकेशन"</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ऐप्लिकेशन खोलने के लिए"</string> <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"मौजूदा ऐप्लिकेशन"</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"खोज के नतीजे दिखाए जा रहे हैं"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"सिस्टम के शॉर्टकट दिखाए जा रहे हैं"</string> @@ -759,8 +756,8 @@ <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"मौजूदा ऐप्लिकेशन के लिए शॉर्टकट दिखाए जा रहे हैं"</string> <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचनाएं देखने के लिए"</string> <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रीनशॉट लेने के लिए"</string> - <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट दिखाने के लिए"</string> - <string name="group_system_go_back" msgid="2730322046244918816">"वापस पीछे जाने के लिए"</string> + <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट देखने के लिए"</string> + <string name="group_system_go_back" msgid="2730322046244918816">"वापस जाने के लिए"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"होम स्क्रीन पर जाने के लिए"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने के लिए"</string> <string name="group_system_cycle_forward" msgid="5478663965957647805">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन के अगले पेज पर जाने के लिए"</string> @@ -768,11 +765,11 @@ <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"ऐप्लिकेशन की सूची खोलने के लिए"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"सेटिंग खोलने के लिए"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Google Assistant खोलने के लिए"</string> - <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट करें"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टम मल्टीटास्किंग"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"स्प्लिट स्क्रीन का इस्तेमाल करके, मौजूदा ऐप्लिकेशन को दाईं ओर ले जाएं"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"स्प्लिट स्क्रीन का इस्तेमाल करके, मौजूदा ऐप्लिकेशन को बाईं ओर ले जाएं"</string> + <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रीन लॉक करने के लिए"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट करने के लिए"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टीटास्किंग (एक साथ कई काम करना)"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"मौजूदा ऐप्लिकेशन को दाईं ओर दिखाने वाली स्प्लिट स्क्रीन इस्तेमाल करें"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"मौजूदा ऐप्लिकेशन को बाईं ओर दिखाने वाली स्प्लिट स्क्रीन इस्तेमाल करें"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"स्प्लिट स्क्रीन से फ़ुल स्क्रीन मोड पर स्विच करने के लिए"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन इस्तेमाल करते समय दाईं ओर या नीचे के ऐप पर स्विच करें"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन इस्तेमाल करते समय बाईं ओर या ऊपर के ऐप पर स्विच करें"</string> @@ -829,7 +826,7 @@ <string name="right_keycode" msgid="2480715509844798438">"दायां कुंजी कोड"</string> <string name="left_icon" msgid="5036278531966897006">"बायां आइकॉन"</string> <string name="right_icon" msgid="1103955040645237425">"दायां आइकॉन"</string> - <string name="drag_to_add_tiles" msgid="8933270127508303672">"टाइल जोड़ने के लिए दबाएं और खींचें"</string> + <string name="drag_to_add_tiles" msgid="8933270127508303672">"टाइल जोड़ने के लिए दबाकर खींचे और छोड़ें"</string> <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"टाइल का क्रम फिर से बदलने के लिए उन्हें दबाकर रखें और खींचें"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"हटाने के लिए यहां खींचें और छोड़ें"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"आपके पास कम से कम <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> टाइलें होनी चाहिए"</string> @@ -1123,7 +1120,7 @@ <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string> <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string> <string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string> - <string name="select_conversation_title" msgid="6716364118095089519">"बातचीत विजेट"</string> + <string name="select_conversation_title" msgid="6716364118095089519">"बातचीत वाला विजेट"</string> <string name="select_conversation_text" msgid="3376048251434956013">"किसी बातचीत को होम स्क्रीन पर जोड़ने के लिए, उस बातचीत पर टैप करें"</string> <string name="no_conversations_text" msgid="5354115541282395015">"हाल ही में हुई बातचीत यहां दिखेंगी"</string> <string name="priority_conversations" msgid="3967482288896653039">"अहम बातचीत"</string> @@ -1286,7 +1283,7 @@ <string name="connected_display_icon_desc" msgid="6373560639989971997">"डिसप्ले कनेक्ट किया गया"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"माइक्रोफ़ोन और कैमरा"</string> <string name="privacy_dialog_summary" msgid="2458769652125995409">"हाल ही में इस्तेमाल करने वाला ऐप्लिकेशन"</string> - <string name="privacy_dialog_more_button" msgid="7610604080293562345">"हाल में ऐक्सेस करने वाले ऐप"</string> + <string name="privacy_dialog_more_button" msgid="7610604080293562345">"हाल में ऐक्सेस करने वाला ऐप"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"हो गया"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"बड़ा करें और विकल्प दिखाएं"</string> <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"छोटा करें"</string> diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml index 0cb06c001671..b89eeb3c0f0f 100644 --- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"बंद है"</item> <item msgid="5137565285664080143">"चालू है"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"उपलब्ध नहीं हैं"</item> + <item msgid="3079622119444911877">"बंद हैं"</item> + <item msgid="3028994095749238254">"चालू हैं"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index a1d885a30991..e0d2478206c4 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -119,7 +119,7 @@ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Prikaz dodira na zaslonu"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"Dijeli"</string> - <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimanje zaslona spremljeno"</string> + <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimanje zaslona je spremljeno"</string> <string name="screenrecord_save_text" msgid="3008973099800840163">"Dodirnite za prikaz"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"Pogreška prilikom spremanja snimke zaslona"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Pogreška prilikom pokretanja snimanja zaslona"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Zabilježi poteškoću"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Pokreni"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zaustavi"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Izvješće o pogrešci"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Na koji dio doživljaja na uređaju to utjecalo?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Odaberite vrstu problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje zaslona"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardni"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednji"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visoki"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušna pomagala"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni uređaji"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uparivanje novog uređaja"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili novi uređaj"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite li deblokirati mikrofon uređaja?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite li deblokirati kameru uređaja?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite li deblokirati kameru i mikrofon uređaja?"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promjena rasporeda tipkovnice"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Brisanje upita za pretraživanje"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečaci"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tipkovni prečaci"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečace"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nema nijednog prečaca"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sustav"</string> @@ -757,29 +754,29 @@ <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Prikazuju se prečaci za unos"</string> <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Prikazuju se prečaci koji otvaraju aplikacije"</string> <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Prikazuju se prečaci za trenutačnu aplikaciju"</string> - <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaži obavijesti"</string> - <string name="group_system_full_screenshot" msgid="5742204844232667785">"Snimi zaslon"</string> + <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaz obavijesti"</string> + <string name="group_system_full_screenshot" msgid="5742204844232667785">"Snimanje zaslona"</string> <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Prikaži prečace"</string> <string name="group_system_go_back" msgid="2730322046244918816">"Natrag"</string> - <string name="group_system_access_home_screen" msgid="4130366993484706483">"Idi na početni zaslon"</string> - <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Prikaži nedavne aplikacije"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Kruži unaprijed kroz nedavne aplikacije"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Kruži unatrag kroz nedavne aplikacije"</string> - <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvori popis aplikacija"</string> - <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvori postavke"</string> - <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvori Asistenta"</string> + <string name="group_system_access_home_screen" msgid="4130366993484706483">"Otvaranje početnog zaslona"</string> + <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Prikaz nedavnih aplikacija"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Kruženje unaprijed kroz nedavne aplikacije"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Kruženje unatrag kroz nedavne aplikacije"</string> + <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvaranje popisa aplikacija"</string> + <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvaranje postavki"</string> + <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvaranje asistenta"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje zaslona"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Zapišite bilješku"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Obavljanje više zadataka sustava"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Otvori podijeljeni zaslon s trenutačnom aplikacijom s desne strane"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Otvori podijeljeni zaslon s trenutačnom aplikacijom s lijeve strane"</string> - <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prijeđi s podijeljenog zaslona na cijeli zaslon"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Obavljanje više zadataka"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Koristite podijeljeni zaslon s trenutačnom aplikacijom s desne strane"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Koristite podijeljeni zaslon s trenutačnom aplikacijom s lijeve strane"</string> + <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prelazak s podijeljenog zaslona na cijeli zaslon"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prijeđite na aplikaciju zdesna ili ispod uz podijeljeni zaslon"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prijeđite na aplikaciju slijeva ili iznad uz podijeljeni zaslon"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Tijekom podijeljenog zaslona: zamijeni aplikaciju drugom"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Unos"</string> - <string name="input_switch_input_language_next" msgid="3782155659868227855">"Prijeđi na sljedeći jezik"</string> - <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Prijeđi na prethodni jezik"</string> + <string name="input_switch_input_language_next" msgid="3782155659868227855">"Prelazak na sljedeći jezik"</string> + <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Prelazak na prethodni jezik"</string> <string name="input_access_emoji" msgid="8105642858900406351">"Pristupanje emojijima"</string> <string name="input_access_voice_typing" msgid="7291201476395326141">"Pristupanje unosu teksta govorom"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacije"</string> @@ -1297,7 +1294,7 @@ <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Koristi telefonski poziv"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Nedavno korišteno tijekom telefonskog poziva"</string> <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koristi: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno je koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koristi: <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Koristi: <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml index e09cab50e9bb..df0b78664cba 100644 --- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Isključeno"</item> <item msgid="5137565285664080143">"Uključeno"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nedostupno"</item> + <item msgid="3079622119444911877">"Isključeno"</item> + <item msgid="3028994095749238254">"Uključeno"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index baea2404664e..7acfbe62e950 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Probléma rögzítése"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Indítás"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Leállítás"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Az eszközhasználati élmény mely része érintett?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Problématípus kiválasztása"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Képernyőrögzítés"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Normál"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Közepes"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Nagy"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hallókészülékek"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hallókészülékek"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Új eszköz párosítása"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kattintson új eszköz párosításához"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Feloldja az eszköz mikrofonjának letiltását?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Feloldja az eszköz kamerájának letiltását?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Feloldja az eszköz kamerájának és mikrofonjának letiltását?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Billentyűzetkiosztás váltása"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"vagy"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Keresőkifejezés törlése"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Billentyűparancsok"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Billentyűparancsok"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Billentyűparancs keresése"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nincs billentyűparancs"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Rendszer"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"A Segéd megnyitása"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lezárási képernyő"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Jegyzetelés"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Rendszermultitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Osztott képernyő aktiválása; az aktuális alkalmazás kerüljön jobbra"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Osztott képernyő aktiválása; az aktuális alkalmazás kerüljön balra"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Osztott képernyő használata, a jelenlegi alkalmazás legyen jobb oldalt"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Osztott képernyő használata, a jelenlegi alkalmazás legyen bal oldalt"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Váltás osztott képernyőről teljes képernyőre"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Váltás a jobb oldalt, illetve lent lévő appra osztott képernyő esetén"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Váltás a bal oldalt, illetve fent lévő appra osztott képernyő esetén"</string> diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml index 8f75dc6ebe5c..bbd6bc0ebbbb 100644 --- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Ki"</item> <item msgid="5137565285664080143">"Be"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nem áll rendelkezésre"</item> + <item msgid="3079622119444911877">"Ki"</item> + <item msgid="3028994095749238254">"Be"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 3f88746abf4c..7dc33b604b83 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Ձայնագրել"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Սկսել"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Կանգնեցնել"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Սարքի ո՞ր մասի հետ է կապված խնդիրը։"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Ընտրեք խնդրի տեսակը"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Էկրանի տեսագրում"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Սովորական"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Միջին"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Բարձր"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Լսողական սարքեր"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Լսողական սարքեր"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Նոր սարքի զուգակցում"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Սեղմեք՝ նոր սարք զուգակցելու համար"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Արգելահանե՞լ սարքի խոսափողը"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Արգելահանե՞լ սարքի տեսախցիկը"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Արգելահանե՞լ սարքի տեսախցիկը և խոսափողը"</string> @@ -720,7 +718,7 @@ <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Բացատ"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Մուտք"</string> - <string name="keyboard_key_backspace" msgid="4095278312039628074">"Հետշարժ"</string> + <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string> <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Նվագարկում/դադար"</string> <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Կանգնեցնել"</string> <string name="keyboard_key_media_next" msgid="8502476691227914952">"Հաջորդը"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Դասավորության փոխարկում"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"կամ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ջնջել որոնման հարցումը"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Դյուրանցումներ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Ստեղնային դյուրանցումներ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Դյուրանցումների որոնում"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Դյուրանցումներ չեն գտնվել"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Համակարգ"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Բացել Օգնականը"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Կողպէկրան"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Ստեղծել նշում"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Համակարգի բազմախնդրության ռեժիմ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Միացնել էկրանի տրոհումը՝ ընթացիկ հավելվածն աջ կողմում"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Միացնել էկրանի տրոհումը՝ ընթացիկ հավելվածը ձախ կողմում"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Բազմախնդրություն"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Աջ մասում օգտագործեք տրոհված էկրանն այս հավելվածի հետ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Ձախ մասում օգտագործեք տրոհված էկրանն այս հավելվածի հետ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Տրոհված էկրանից անցնել լիաէկրան ռեժիմ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Անցեք աջ կողմի կամ ներքևի հավելվածին տրոհված էկրանի միջոցով"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Անցեք աջ կողմի կամ վերևի հավելվածին տրոհված էկրանի միջոցով"</string> diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml index 118915d03612..eb77ccf8c1fc 100644 --- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Անջատված է"</item> <item msgid="5137565285664080143">"Միացված է"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Հասանելի չէ"</item> + <item msgid="3079622119444911877">"Անջատված է"</item> + <item msgid="3028994095749238254">"Միացված է"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 0b07a32d7017..3da9a9024612 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -119,7 +119,7 @@ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Tampilkan lokasi sentuhan pada layar"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"Bagikan"</string> - <string name="screenrecord_save_title" msgid="1886652605520893850">"Perekaman layar disimpan"</string> + <string name="screenrecord_save_title" msgid="1886652605520893850">"Rekaman layar disimpan"</string> <string name="screenrecord_save_text" msgid="3008973099800840163">"Ketuk untuk melihat"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"Terjadi error saat menyimpan rekaman layar"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Terjadi error saat memulai perekaman layar"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Mencatat Masalah"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Mulai"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Berhenti"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Laporan Bug"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Bagian pengalaman perangkat mana yang terpengaruh?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Pilih jenis masalah"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Perekaman layar"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standar"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Sedang"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Tinggi"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Alat bantu dengar"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Alat bantu dengar"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sambungkan perangkat baru"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menyambungkan perangkat baru"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Berhenti memblokir mikrofon perangkat?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Berhenti memblokir kamera perangkat?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Berhenti memblokir kamera dan mikrofon perangkat?"</string> @@ -594,7 +591,7 @@ <string name="stream_accessibility" msgid="3873610336741987152">"Aksesibilitas"</string> <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Dering"</string> <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Getar"</string> - <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Nonaktifkan"</string> + <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Bisukan"</string> <string name="media_device_cast" msgid="4786241789687569892">"Transmisi"</string> <string name="stream_notification_unavailable" msgid="4313854556205836435">"Tidak tersedia - Volume dering dibisukan"</string> <string name="stream_alarm_unavailable" msgid="4059817189292197839">"Tidak tersedia - Fitur Jangan Ganggu aktif"</string> @@ -638,7 +635,7 @@ <string name="wallet_error_generic" msgid="257704570182963611">"Terjadi error saat mendapatkan kartu Anda, coba lagi nanti"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string> <string name="qr_code_scanner_title" msgid="1938155688725760702">"Pemindai kode QR"</string> - <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mengupdate"</string> + <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Update berlangsung"</string> <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string> @@ -745,8 +742,8 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ganti tata letak keyboard"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"atau"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Hapus kueri penelusuran"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string> - <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pintasan penelusuran"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Pintasan Keyboard"</string> + <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Telusuri pintasan"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tidak ditemukan pintasan"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string> @@ -763,16 +760,16 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Kembali"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Buka layar utama"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Lihat aplikasi terbaru"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Menavigasi maju pada aplikasi terbaru"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Menavigasi mundur pada aplikasi terbaru"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Berpindah-pindah aplikasi terbaru ke arah kanan"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Berpindah-pindah aplikasi terbaru ke arah kiri"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Buka daftar aplikasi"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Buka setelan"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Buka Asisten"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci layar"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Buat catatan"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking sistem"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Masuk ke layar terpisah dengan aplikasi saat ini ke RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Masuk ke layar terpisah dengan aplikasi saat ini ke LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gunakan layar terpisah dengan aplikasi saat ini di sebelah kanan"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gunakan layar terpisah dengan aplikasi saat ini di sebelah kiri"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Beralih dari layar terpisah ke layar penuh"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Beralih ke aplikasi di bagian kanan atau bawah saat menggunakan layar terpisah"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Beralih ke aplikasi di bagian kiri atau atas saat menggunakan layar terpisah"</string> diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml index bd429c147784..a415f644fb48 100644 --- a/packages/SystemUI/res/values-in/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Nonaktif"</item> <item msgid="5137565285664080143">"Aktif"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Tidak tersedia"</item> + <item msgid="3079622119444911877">"Nonaktif"</item> + <item msgid="3028994095749238254">"Aktif"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 56ea0d50705a..b400f8cec8c0 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Vandamál tengt upptöku"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Byrja"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stöðva"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Villutilkynning"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Hvað í tækjaupplifuninni varð fyrir áhrifum?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Veldu gerð vandamáls"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skjáupptaka"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Staðlað"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Miðlungs"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Mikið"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Heyrnartæki"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Heyrnartæki"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Para nýtt tæki"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Smelltu til að para nýtt tæki"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Opna fyrir hljóðnema tækisins?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Opna fyrir myndavél tækisins?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Opna fyrir myndavél og hljóðnema tækisins?"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skipta um lyklaskipan"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eða"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Hreinsa leitarfyrirspurn"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Flýtileiðir"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Flýtilyklar"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Leita að flýtileiðum"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Engar flýtileiðir fundust"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Kerfi"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Opna Hjálpara"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lásskjár"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Skrifa glósu"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Fjölvinnsla kerfis"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Opna skjáskiptingu hægra megin með núverandi forriti"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Opna skjáskiptingu vinstra megin með núverandi forriti"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Fjölvinnsla"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Notaðu skjáskiptingu með núverandi forriti til hægri"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Notaðu skjáskiptingu með núverandi forriti til vinstri"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Skipta úr skjáskiptingu yfir á allan skjáinn"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skiptu í forrit til hægri eða fyrir neðan þegar skjáskipting er notuð"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skiptu í forrit til vinstri eða fyrir ofan þegar skjáskipting er notuð"</string> diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml index abdc3e7610b1..c9befd6574c4 100644 --- a/packages/SystemUI/res/values-is/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Slökkt"</item> <item msgid="5137565285664080143">"Kveikt"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Ekki tiltækt"</item> + <item msgid="3079622119444911877">"Slökkt"</item> + <item msgid="3028994095749238254">"Kveikt"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 08f07efb07c8..aa7f15229c95 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Registra problema"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Avvia"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Interrompi"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Quali problemi ha l\'esperienza del dispositivo?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Seleziona il tipo di problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Regis. dello schermo"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Apparecchi acustici"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Protesi uditive"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Accoppia nuovo dispositivo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic per accoppiare un nuovo dispositivo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vuoi sbloccare il microfono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vuoi sbloccare la fotocamera del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vuoi sbloccare la fotocamera e il microfono del dispositivo?"</string> @@ -550,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Questo dispositivo è gestito da uno dei tuoi genitori, il quale può visualizzare e gestire informazioni come le app che usi, la tua posizione e il tuo tempo di utilizzo."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Sbloccato da TrustAgent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Dispositivo bloccato, troppi tentativi di autenticazione"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Dispositivo bloccato: troppi tentativi di autenticazione"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Dispositivo bloccato\nAutenticazione non riuscita"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Impostazioni audio"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambia layout della tastiera"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"oppure"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Cancella la query di ricerca"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Scorciatoie"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Scorciatoie da tastiera"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca scorciatoie"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Scorciatoie non trovate"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Apri l\'assistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Blocca lo schermo"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Scrivi una nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking di sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Attiva lo schermo diviso con l\'app corrente a destra"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Attiva lo schermo diviso con l\'app corrente a sinistra"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utilizza schermo diviso con l\'app corrente a destra"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utilizza schermo diviso con l\'app corrente a sinistra"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Passa da schermo diviso a schermo intero"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passa all\'app a destra o sotto mentre usi lo schermo diviso"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passa all\'app a sinistra o sopra mentre usi lo schermo diviso"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 24ec7853c399..a804271054f9 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"תיעוד הבעיה"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"התחלה"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"עצירה"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"איזה חלק בחוויית השימוש שלך במכשיר הושפע?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"בחירה בסוג הבעיה"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"הקלטת המסך"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"רגילה"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"בינונית"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"גבוהה"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"מכשירי שמיעה"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"מכשירי שמיעה"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"התאמה של מכשיר חדש"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"צריך ללחוץ כדי להתאים מכשיר חדש"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"לבטל את חסימת המיקרופון של המכשיר?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"לבטל את חסימת המצלמה של המכשיר?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"לבטל את חסימת המצלמה והמיקרופון של המכשיר?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"החלפה של פריסת מקלדת"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"או"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ניקוי שאילתת החיפוש"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"מקשי קיצור"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"מקשי קיצור"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"חיפוש מקשי קיצור"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"לא נמצאו מקשי קיצור"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"מערכת"</string> @@ -757,7 +755,7 @@ <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"מוצגים: קיצורי הדרך של הקלט"</string> <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"מוצגים: קיצורי הדרך לפתיחת אפליקציות"</string> <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"מוצגים: קיצורי הדרך של האפליקציה הנוכחית"</string> - <string name="group_system_access_notification_shade" msgid="1619028907006553677">"הצגת הודעות"</string> + <string name="group_system_access_notification_shade" msgid="1619028907006553677">"הצגת התראות"</string> <string name="group_system_full_screenshot" msgid="5742204844232667785">"צילום המסך"</string> <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"הצגת מקשי הקיצור"</string> <string name="group_system_go_back" msgid="2730322046244918816">"חזרה"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"לפתיחת Google Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"מסך הנעילה"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"כתיבת הערה"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ריבוי משימות מערכת"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"כניסה למסך מפוצל עם האפליקציה הנוכחית ל-RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"כניסה למסך מפוצל עם האפליקציה הנוכחית ל-LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ריבוי משימות"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"שימוש במסך מפוצל כשהאפליקציה הנוכחית בצד ימין"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"שימוש במסך מפוצל כשהאפליקציה הנוכחית בצד שמאל"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"החלפה ממסך מפוצל למסך מלא"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"מעבר לאפליקציה משמאל או למטה בזמן שימוש במסך מפוצל"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"מעבר לאפליקציה מימין או למעלה בזמן שימוש במסך מפוצל"</string> diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml index 196a6c270593..b5cb476484b2 100644 --- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"מושבת"</item> <item msgid="5137565285664080143">"מופעל"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"לא זמינים"</item> + <item msgid="3079622119444911877">"מצב מושבת"</item> + <item msgid="3028994095749238254">"מצב פעיל"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 6e2ca403392a..6cd1dcb1cbd7 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"録音に関する問題"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"開始"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"デバイスのどの部分が影響を受けましたか?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"問題の種類を選択する"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"スクリーン レコード"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"補聴器"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"補聴器"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"新しいデバイスとペア設定"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"クリックすると、新しいデバイスをペア設定できます"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"デバイスのマイクのブロックを解除しますか?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"デバイスのカメラのブロックを解除しますか?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"デバイスのカメラとマイクのブロックを解除しますか?"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"キーボード レイアウトの切り替え"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"または"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"検索クエリをクリア"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ショートカット"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"キーボード ショートカット"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ショートカットの検索"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ショートカットがありません"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"システム"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"アシスタントを開く"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"画面をロック"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"メモを入力する"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"システム マルチタスク"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"分割画面にして現在のアプリを右側に設定する"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"分割画面にして現在のアプリを左側に設定する"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"マルチタスク"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"分割画面の使用(現在のアプリを右側に表示)"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"分割画面の使用(現在のアプリを左側に表示)"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"分割画面から全画面に切り替える"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"分割画面の使用時に右側または下部のアプリに切り替える"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"分割画面の使用時に左側または上部のアプリに切り替える"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index b2295f324a45..15bb4fcc0134 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ჩაწერასთან დაკავშირებული პრობლემა"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"დაწყება"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"გაჩერება"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"თქვენი მოწყობილობის გამოცდილების რა ნაწილზე მოხდა ზეგავლენა?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"აირჩიეთ პრობლემის ტიპი"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ეკრანის ჩანაწერი"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"საშუალო"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"მაღალი"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"სმენის აპარატები"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"სმენის აპარატები"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ახალი მოწყობილობის დაწყვილება"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"დააწკაპუნეთ ახალი მოწყობილობის დასაწყვილებლად"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"გსურთ მოწყობილობის მიკროფონის განბლოკვა?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"გსურთ მოწყობილობის კამერის განბლოკვა?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"გსურთ მოწყობილობის კამერის და მიკროფონის განბლოკვა?"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"კლავიატურის განლაგების გადართვა"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ან"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"საძიებო ფრაზის გასუფთავება"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"მალსახმობები"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"კლავიატურის მალსახმობები"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"მალსახმობების ძიება"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"მალსახმობები ვერ მოიძებნა"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"სისტემა"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"ასისტენტის გახსნა"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ჩაკეტილი ეკრანი"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ჩაინიშნეთ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"სისტემის მრავალამოცანიანი რეჟიმი"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"ეკრანის გაყოფის შეყვანა მიმდინარე აპით RHS-ში"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"ეკრანის გაყოფის შეყვანა მიმდინარე აპით LHS-ში"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"მრავალამოცანიანი რეჟიმი"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ეკრანის გაყოფის გამოყენება მიმდინარე აპზე მარჯვნივ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ეკრანის გაყოფის გამოყენება მიმდინარე აპზე მარცხნივ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"გადართვა ეკრანის გაყოფიდან სრულ ეკრანზე"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ეკრანის გაყოფის გამოყენებისას აპზე მარჯვნივ ან ქვემოთ გადართვა"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ეკრანის გაყოფის გამოყენებისას აპზე მარცხნივ ან ზემოთ გადართვა"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 127e81e19ae4..835a0cabfceb 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -281,7 +281,7 @@ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string> <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Кіріс"</string> <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Есту аппараттары"</string> - <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Қосылуда…"</string> + <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Қосылып жатыр…"</string> <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматты түрде бұру"</string> <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматты айналатын экран"</string> <string name="quick_settings_location_label" msgid="2621868789013389163">"Локация"</string> @@ -297,7 +297,7 @@ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Желілер бар"</string> <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Желілер қолжетімді емес."</string> <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Қолжетімді Wi-Fi желілері жоқ"</string> - <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Қосылуда…"</string> + <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Қосылып жатыр…"</string> <string name="quick_settings_cast_title" msgid="2279220930629235211">"Экранды трансляциялау"</string> <string name="quick_settings_casting" msgid="1435880708719268055">"Трансляциялануда"</string> <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Атаусыз құрылғы"</string> @@ -312,9 +312,9 @@ <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Жабу"</string> <string name="quick_settings_connected" msgid="3873605509184830379">"Қосылды"</string> <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Қосылды, батарея деңгейі: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> - <string name="quick_settings_connecting" msgid="2381969772953268809">"Қосылуда…"</string> + <string name="quick_settings_connecting" msgid="2381969772953268809">"Қосылып жатыр…"</string> <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Хотспот"</string> - <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Қосылуда…"</string> + <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Қосылып жатыр…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Трафикті үнемдеу режимі қосулы"</string> <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# құрылғы}other{# құрылғы}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Қолшам"</string> @@ -331,13 +331,13 @@ <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Түнгі жарық"</string> <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Күн батқанда қосу"</string> <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Күн шыққанға дейін"</string> - <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string> + <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Қосылатын уақыты: <xliff:g id="TIME">%s</xliff:g>"</string> <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> дейін"</string> <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Қараңғы режим"</string> <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батареяны үнемдеу режимі"</string> <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батқанда қосу"</string> <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string> - <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string> + <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылатын уақыты: <xliff:g id="TIME">%s</xliff:g>"</string> <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> дейін"</string> <string name="quick_settings_dark_mode_secondary_label_on_at_bedtime" msgid="2274300599408864897">"Ұйқы режимінде"</string> <string name="quick_settings_dark_mode_secondary_label_until_bedtime_ends" msgid="1790772410777123685">"Ұйқы режимі аяқталғанға дейін"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Ақауды жазу"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Бастау"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Тоқтату"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Құрылғы қызметінің қандай түріне әсер етті?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Мәселе түрін таңдаңыз."</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Экранды жазу"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Орташа"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Жоғары"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Есту құрылғылары"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Есту құрылғылары"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Жаңа құрылғыны жұптау"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңа құрылғыны жұптау үшін басыңыз."</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Құрылғы микрофонын блоктан шығару керек пе?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Құрылғы камерасын блоктан шығару керек пе?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Құрылғы камерасы мен микрофонын блоктан шығару керек пе?"</string> @@ -636,7 +635,7 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string> - <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR кодының сканері"</string> + <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR сканері"</string> <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Жаңартылып жатыр"</string> <string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пернетақта форматын ауыстыру"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"немесе"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Іздеу сұрауын өшіру"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Перне тіркесімдері"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Перне тіркесімдері"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Перне тіркесімдерін іздеу"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Перне тіркесімдері табылмады."</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Жүйе"</string> @@ -762,19 +761,19 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Артқа"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Негізгі экранға өту"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Соңғы қолданбаларды көру"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Соңғы қолданбаларға алға өту"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Соңғы қолданбаларға артқа өту"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Соңғы қолданбалар тізімінде алға өту"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Соңғы қолданбалар тізімінде артқа өту"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Қолданбалар тізімін ашу"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Параметрлерді ашу"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant-ті ашу"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды құлыптау"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Ескертпе жазу"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Жүйе мультитаскингі"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Бөлінген экран режиміне кіру (ағымдағы қолданбаны оңға орналастыру)"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Бөлінген экран режиміне кіру (ағымдағы қолданбаны солға орналастыру)"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Мультитаскинг"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Ағымдағы қолданба оң жақта тұратын бөлінген экранды пайдаланыңыз"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Ағымдағы қолданба сол жақта тұратын бөлінген экранды пайдаланыңыз"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Бөлінген экран режимінен толық экран режиміне ауысу"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Экранды бөлуді қолданғанда, оң не жоғары жақтағы қолданбаға ауысыңыз"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Экранды бөлуді қолданғанда, сол не жоғары жақтағы қолданбаға ауысыңыз"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Бөлінген экранда оң не төмен жақтағы қолданбаға ауысу"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Бөлінген экранда сол не жоғары жақтағы қолданбаға ауысу"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Экранды бөлу кезінде: бір қолданбаны басқасымен алмастыру"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Енгізу"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Келесі тілге ауысу"</string> @@ -1261,7 +1260,7 @@ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Қалған батарея заряды: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Стилусты зарядтағышқа жалғаңыз."</string> <string name="stylus_battery_low" msgid="7134370101603167096">"Стилус батареясының заряды аз"</string> - <string name="video_camera" msgid="7654002575156149298">"Бейнекамера"</string> + <string name="video_camera" msgid="7654002575156149298">"Бейнекамера"</string> <string name="call_from_work_profile_title" msgid="5418253516453177114">"Жеке қолданбадан қоңырау шалу мүмкін емес"</string> <string name="call_from_work_profile_text" msgid="2856337395968118274">"Ұйымыңыз тек жұмыс қолданбаларынан қоңырау шалуға рұқсат етеді."</string> <string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string> @@ -1284,7 +1283,7 @@ <string name="dismiss_dialog" msgid="2195508495854675882">"Жабу"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"Дисплей қосылды"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон және камера"</string> - <string name="privacy_dialog_summary" msgid="2458769652125995409">"Соңғы рет қолданбаның датчикті пайдалануы"</string> + <string name="privacy_dialog_summary" msgid="2458769652125995409">"Қолданбалардың соңғы рет пайдалануы"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Соңғы рет пайдаланғандар"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Дайын"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Опцияларды көрсету және жаю"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index f2596dbf5897..d56c20de4692 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"កត់ត្រាបញ្ហា"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ចាប់ផ្ដើម"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"បញ្ឈប់"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"របាយការណ៍អំពីបញ្ហា"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"តើផ្នែកអ្វីនៃបទពិសោធប្រើប្រាស់ឧបករណ៍របស់អ្នកបានរងការប៉ះពាល់?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ជ្រើសរើសប្រភេទបញ្ហា"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ការថតវីដេអូអេក្រង់"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"មធ្យម"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ខ្ពស់"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ឧបករណ៍ជំនួយការស្ដាប់"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ឧបករណ៍ជំនួយការស្ដាប់"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ចុច ដើម្បីផ្គូផ្គងឧបករណ៍ថ្មី"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ឈប់ទប់ស្កាត់មីក្រូហ្វូនរបស់ឧបករណ៍ឬ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ឈប់ទប់ស្កាត់កាមេរ៉ារបស់ឧបករណ៍ឬ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ឈប់ទប់ស្កាត់កាមេរ៉ា និងមីក្រូហ្វូនរបស់ឧបករណ៍ឬ?"</string> @@ -607,7 +605,7 @@ <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"សំឡេងលំហ"</string> <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"បិទ"</string> <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"ថេរ"</string> - <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"ការតាមដានក្បាល"</string> + <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"រេតាមក្បាល"</string> <string name="volume_ringer_change" msgid="3574969197796055532">"ចុចដើម្បីប្ដូរមុខងាររោទ៍"</string> <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"បិទសំឡេង"</string> <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"បើកសំឡេង"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ប្ដូរប្លង់ក្ដារចុច"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ឬ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"សម្អាតសំណួរស្វែងរក"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ផ្លូវកាត់"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ផ្លូវកាត់ក្ដារចុច"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ស្វែងរកផ្លូវកាត់"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"រកផ្លូវកាត់មិនឃើញទេ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ប្រព័ន្ធ"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"បើកជំនួយការ"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ចាក់សោអេក្រង់"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"កត់ចំណាំ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ការដំណើរការបានច្រើននៃប្រព័ន្ធ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"ចូលក្នុងមុខងារបំបែកអេក្រង់ដោយប្រើកម្មវិធីបច្ចុប្បន្ននៅខាងស្ដាំដៃ"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"ចូលក្នុងមុខងារបំបែកអេក្រង់ដោយប្រើកម្មវិធីបច្ចុប្បន្ននៅខាងឆ្វេងដៃ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ការដំណើរការបានច្រើន"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ប្រើមុខងារបំបែកអេក្រង់ជាមួយកម្មវិធីបច្ចុប្បន្ននៅខាងស្ដាំ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ប្រើមុខងារបំបែកអេក្រង់ជាមួយកម្មវិធីបច្ចុប្បន្ននៅខាងឆ្វេង"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"ប្ដូរពីមុខងារបំបែកអេក្រង់ទៅជាអេក្រង់ពេញ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ប្ដូរទៅកម្មវិធីនៅខាងស្ដាំ ឬខាងក្រោម ពេលកំពុងប្រើមុខងារបំបែកអេក្រង់"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ប្ដូរទៅកម្មវិធីនៅខាងឆ្វេង ឬខាងលើ ពេលកំពុងប្រើមុខងារបំបែកអេក្រង់"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 73234507bbce..23bde222e11a 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -329,7 +329,7 @@ <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳು"</string> <string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ನೈಟ್ ಲೈಟ್"</string> - <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ಸೂರ್ಯಾಸ್ತದಲ್ಲಿ"</string> + <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ಸೂರ್ಯಾಸ್ತಕ್ಕೆ ಆನ್"</string> <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string> <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string> <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ರೆಕಾರ್ಡ್ ದೋಷ"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ಪ್ರಾರಂಭಿಸಿ"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"ನಿಲ್ಲಿಸಿ"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ಸಾಧನ ಬಳಸುವಾಗ ನೀವು ಯಾವ ರೀತಿಯ ಸಮಸ್ಯೆ ಎದುರಿಸುತ್ತೀರಿ?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ಸಮಸ್ಯೆಯ ಪ್ರಕಾರವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ಪ್ರಮಾಣಿತ"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ಮಧ್ಯಮ"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ಹೆಚ್ಚು"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ಹಿಯರಿಂಗ್ ಸಾಧನಗಳು"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ಹಿಯರಿಂಗ್ ಸಾಧನಗಳು"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ಸಾಧನದ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಅನ್ಬ್ಲಾಕ್ ಮಾಡಬೇಕೇ?"</string> @@ -551,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ. ನೀವು ಬಳಸುವ ಆ್ಯಪ್ಗಳು, ನಿಮ್ಮ ಸ್ಥಳ ಮತ್ತು ನಿಮ್ಮ ವೀಕ್ಷಣಾ ಅವಧಿಯಂತಹ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನೋಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ನಿಂದ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ, ಹಲವಾರು ದೃಢೀಕರಣ ಪ್ರಯತ್ನಗಳು"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"ಹಲವಾರು ದೃಢೀಕರಣ ಪ್ರಯತ್ನಗಳನ್ನು ಮಾಡಿರುವ ಕಾರಣ ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ\nದೃಢೀಕರಣ ವಿಫಲವಾಗಿದೆ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ಸೌಂಡ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಬದಲಾಯಿಸಿ"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ಅಥವಾ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ಹುಡುಕಾಟದ ಪ್ರಶ್ನೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ಶಾರ್ಟ್ಕಟ್ಗಳು"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್ಕಟ್ಗಳು"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಹುಡುಕಿ"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ಯಾವುದೇ ಶಾರ್ಟ್ಕಟ್ಗಳಿಲ್ಲ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ಸಿಸ್ಟಂ"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"assistant ಅನ್ನು ತೆರೆಯಿರಿ"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಮಾಡಿ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ಟಿಪ್ಪಣಿಯನ್ನು ತೆಗೆದುಕೊಳ್ಳಿ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ಸಿಸ್ಟಂ ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHS ಗೆ ಇರುವ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಸಹಾಯದಿಂದ ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ನಮೂದಿಸಿ"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHS ಗೆ ಇರುವ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಸಹಾಯದಿಂದ ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ನಮೂದಿಸಿ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ಬಲಭಾಗದಲ್ಲಿ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಮೂಲಕ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಿ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ಎಡಭಾಗದಲ್ಲಿ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಮೂಲಕ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಿ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ನಿಂದ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ಗೆ ಬದಲಿಸಿ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಬಳಸುವಾಗ ಬಲಭಾಗ ಅಥವಾ ಕೆಳಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್ಗೆ ಬದಲಿಸಿ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಬಳಸುವಾಗ ಎಡಭಾಗ ಅಥವಾ ಮೇಲ್ಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್ಗೆ ಬದಲಿಸಿ"</string> diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml index 9628323a595f..afc7c1a10e0e 100644 --- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"ಆಫ್ ಆಗಿದೆ"</item> <item msgid="5137565285664080143">"ಆನ್ ಆಗಿದೆ"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"ಲಭ್ಯವಿಲ್ಲ"</item> + <item msgid="3079622119444911877">"ಆಫ್ ಆಗಿದೆ"</item> + <item msgid="3028994095749238254">"ಆನ್"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 9a4c60bc67fe..8f8246522b7e 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"문제 기록"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"시작"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"중지"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"기기 경험의 어떤 부분에 영향이 있었나요?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"문제 유형 선택"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"화면 녹화"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"표준"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"보통"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"높음"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"청각 보조 기기"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"청각 보조 기기"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"새 기기와 페어링"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"새 기기와 페어링하려면 클릭하세요"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"기기 마이크를 차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"기기 카메라를 차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"기기 카메라 및 마이크를 차단 해제하시겠습니까?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"키보드 레이아웃 전환"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"또는"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"검색어 삭제"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"단축키"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"단축키"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"단축키 검색"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"단축키 없음"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"시스템"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"어시스턴트 열기"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"메모 작성"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"시스템 멀티태스킹"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"현재 앱을 오른쪽으로 보내는 화면 분할 입력"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"현재 앱을 왼쪽으로 보내는 화면 분할 입력"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"멀티태스킹"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"현재 앱이 오른쪽에 오도록 화면 분할 사용"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"현재 앱이 왼쪽에 오도록 화면 분할 사용"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"화면 분할에서 전체 화면으로 전환"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"화면 분할을 사용하는 중에 오른쪽 또는 아래쪽에 있는 앱으로 전환하기"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"화면 분할을 사용하는 중에 왼쪽 또는 위쪽에 있는 앱으로 전환하기"</string> diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml index d30aff2073f1..bc4740dbc23a 100644 --- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"사용 안함"</item> <item msgid="5137565285664080143">"사용"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"사용 불가"</item> + <item msgid="3079622119444911877">"사용 안함"</item> + <item msgid="3028994095749238254">"사용"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index d893887469e9..40a427cebcb8 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -212,7 +212,7 @@ <string name="accessibility_bluetooth_device_icon" msgid="9163840051642587982">"Bluetooth түзмөгүнүн сүрөтчөсү"</string> <string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"Түзмөктүн чоо-жайын конфигурациялоо үчүн чыкылдатыңыз"</string> <string name="accessibility_bluetooth_device_settings_see_all" msgid="9111952496905423543">"Бардык түзмөктөрдү көрүү үчүн чыкылдатыңыз"</string> - <string name="accessibility_bluetooth_device_settings_pair_new_device" msgid="2435184865793496966">"Жаңы түзмөктү жупташтыруу үчүн чыкылдатыңыз"</string> + <string name="accessibility_bluetooth_device_settings_pair_new_device" msgid="2435184865793496966">"Жаңы түзмөк кошуу үчүн чыкылдатыңыз"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея кубатынын деңгээли белгисиз."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string> <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> менен туташты."</string> @@ -266,7 +266,7 @@ <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string> <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Жупташкан түзмөктөр жок"</string> <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Түзмөктү туташтыруу же ажыратуу үчүн таптаңыз"</string> - <string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Жаңы түзмөктү жупташтыруу"</string> + <string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Жаңы түзмөк кошуу"</string> <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Баарын көрүү"</string> <string name="turn_on_bluetooth" msgid="5681370462180289071">"Иштетүү"</string> <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Туташты"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Маселени жаздыруу"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Баштоо"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Токтотуу"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Мүчүлүштүк тууралуу кабарлоо"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Түзмөгүңүздүн кайсы бөлүгүнө кедергиси тийди?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Маселенин түрүн тандоо"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Экрандан видео жаздырып алуу"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Кадимки"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Орточо"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Жогору"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Угуу аппараттары"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Угуу аппараттары"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Жаңы түзмөк кошуу"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңы түзмөк кошуу үчүн басыңыз"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Түзмөктүн микрофонун бөгөттөн чыгарасызбы?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Түзмөктүн камерасын бөгөттөн чыгарасызбы?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Түзмөктүн камерасы менен микрофону бөгөттөн чыгарылсынбы?"</string> @@ -551,7 +548,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Бул түзмөктү ата-энең башкарат. Ата-энең сен иштеткен колдонмолорду, кайда жүргөнүңдү жана түзмөктү канча убакыт колдонгонуңду көрүп, башкарып турат."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ишеним агенти кулпусун ачты"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Түзмөк кулпуланды. Аутентификациядан өтүүгө өтө көп аракет жасалды"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Аутентификациядан өтө албай койгонуңуздан улам, түзмөк кулпуланды"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Түзмөк кулпуланды\nАутентификациядан өткөн жоксуз"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Добуштун параметрлери"</string> @@ -719,7 +716,7 @@ <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Ортолотуу"</string> <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Боштук"</string> - <string name="keyboard_key_enter" msgid="8633362970109751646">"Киргизүү"</string> + <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Артка өчүрүү"</string> <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Ойнотуу/Тындыруу"</string> <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Токтотуу"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Баскычтоп калыбын которуштуруу"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"же"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Изделген суроону тазалоо"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ыкчам баскычтар"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Ыкчам баскычтар"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ыкчам баскычтарды издөө"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ыкчам баскычтар жок"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Жардамчыны ачуу"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды кулпулоо"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Кыска жазуу түзүү"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Системанын бир нече тапшырма аткаруусу"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Учурда оң жактагы колдонмо менен экранды бөлүүнү иштетүү"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Учурда сол жактагы колдонмо менен экранды бөлүүнү иштетүү"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Бир нече тапшырма аткаруу"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Учурдагы колдонмону оңго жылдырып, экранды бөлүү"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Учурдагы колдонмону солго жылдырып, экранды бөлүү"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Экранды бөлүү режиминен толук экранга которулуу"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Бөлүнгөн экранды колдонуп жатканда сол же төмөн жактагы колдонмого которулуңуз"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Бөлүнгөн экранды колдонуп жатканда сол же жогору жактагы колдонмого которулуңуз"</string> @@ -1286,21 +1283,21 @@ <string name="connected_display_icon_desc" msgid="6373560639989971997">"Экран туташтырылды"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон жана камера"</string> <string name="privacy_dialog_summary" msgid="2458769652125995409">"Жакында колдонмолордо иштетилген"</string> - <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Акыркы пайдалануусун көрүү"</string> + <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Соңку маалыматты көрүү"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Бүттү"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Параметрлерди жайып көрсөтүү"</string> <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"Жыйыштыруу"</string> <string name="privacy_dialog_close_app_button" msgid="8006250171305878606">"Бул колдонмону жабуу"</string> <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"<xliff:g id="APP_NAME">%1$s</xliff:g> жабылды"</string> <string name="privacy_dialog_manage_service" msgid="8320590856621823604">"Кызматты тескөө"</string> - <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Кирүү мүмкүнчүлүгүн тескөө"</string> + <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Жеткиликтүүлүгүн башкаруу"</string> <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Телефон чалууда колдонулуп жатат"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Акыркы жолу телефон чалууда колдонулду"</string> - <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилип жатат"</string> + <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат"</string> <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Акыркы жолу <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилди"</string> - <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилип жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> + <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Акыркы жолу <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) колдонмосунда иштетилди"</string> - <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилип жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> + <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Акыркы жолу <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) колдонмосунда иштетилди"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ичинен %1$d-деңгээл"</string> diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml index 35795b77a32e..694967e3d8d6 100644 --- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Өчүк"</item> <item msgid="5137565285664080143">"Күйүк"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Жеткиликсиз"</item> + <item msgid="3079622119444911877">"Өчүк"</item> + <item msgid="3028994095749238254">"Күйүк"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 873d75eddc8d..f7dfc7e1c5a1 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ບັນຫາກ່ຽວກັບການບັນທຶກ"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ເລີ່ມ"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"ຢຸດ"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ລາຍງານຂໍ້ຜິດພາດ"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ສ່ວນໃດຂອງປະສົບການອຸປະກອນຂອງທ່ານໄດ້ຮັບຜົນກະທົບ?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ເລືອກປະເພດບັນຫາ"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ບັນທຶກໜ້າຈໍ"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ປານກາງ"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ສູງ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ອຸປະກອນຊ່ວຍຟັງ"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ອຸປະກອນຊ່ວຍຟັງ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ຄລິກເພື່ອຈັບຄູ່ອຸປະກອນໃໝ່"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ປົດບລັອກໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ປົດບລັອກກ້ອງຖ່າຍຮູບອຸປະກອນບໍ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ຍົກເລີກການບລັອກກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string> @@ -652,7 +650,7 @@ <string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string> <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string> <string name="tuner_persistent_warning" msgid="230466285569307806">"ຄຸນສົມບັດທົດລອງໃຊ້ງານເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການອອກຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງສືບຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string> - <string name="got_it" msgid="477119182261892069">"ໄດ້ແລ້ວ"</string> + <string name="got_it" msgid="477119182261892069">"ເຂົ້າໃຈແລ້ວ"</string> <string name="tuner_toast" msgid="3812684836514766951">"ຍິນດີດ້ວຍ! System UI Tuner ໄດ້ຖືກເພີ່ມໃສ່ການຕັ້ງຄ່າແລ້ວ"</string> <string name="remove_from_settings" msgid="633775561782209994">"ເອົາອອກຈາກການຕັ້ງຄ່າ"</string> <string name="remove_from_settings_prompt" msgid="551565437265615426">"ເອົາ System UI Tuner ອອກຈາກການຕັ້ງຄ່າ ແລະຢຸດການໃຊ້ທຸກຄຸນສົມບັດໃຊ້ງານຂອງມັນ?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ສະຫຼັບແປ້ນພິມ"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ຫຼື"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ລຶບລ້າງຄຳຊອກຫາ"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ທາງລັດ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ຄີລັດ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ທາງລັດການຊອກຫາ"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ບໍ່ພົບທາງລັດ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ລະບົບ"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"ເປີດຜູ້ຊ່ວຍ"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ໜ້າຈໍລັອກ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ຈົດບັນທຶກ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນຂອງລະບົບ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"ເຂົ້າສູ່ແບ່ງໜ້າຈໍດ້ວຍແອັບປັດຈຸບັນໄປຫາ RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"ເຂົ້າສູ່ແບ່ງໜ້າຈໍດ້ວຍແອັບປັດຈຸບັນໄປຫາ LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນ"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ໃຊ້ການແບ່ງໜ້າຈໍກັບແອັບປັດຈຸບັນຢູ່ເບື້ອງຂວາ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ໃຊ້ການແບ່ງໜ້າຈໍກັບແອັບປັດຈຸບັນຢູ່ເບື້ອງຊ້າຍ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"ສະຫຼັບຈາກແບ່ງໜ້າຈໍໄປເປັນເຕັມຈໍ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ສະຫຼັບໄປໃຊ້ແອັບຢູ່ຂວາ ຫຼື ທາງລຸ່ມໃນຂະນະທີ່ໃຊ້ແບ່ງໜ້າຈໍ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ສະຫຼັບໄປໃຊ້ແອັບຢູ່ຊ້າຍ ຫຼື ທາງເທິງໃນຂະນະທີ່ໃຊ້ແບ່ງໜ້າຈໍ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index d5d7929b9c41..734daf892d63 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Įrašyti problemą"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Pradėti"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stabdyti"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Kuri įrenginio funkcija buvo paveikta?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Pasirinkite problemos tipą"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekrano įrašas"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Įprastas"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Vidutinis"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Aukštas"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Klausos įrenginiai"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Klausos įrenginiai"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Susieti naują įrenginį"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Spustelėkite, kad susietumėte naują įrenginį"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Panaikinti įrenginio mikrofono blokavimą?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Panaikinti įrenginio fotoaparato blokavimą?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Panaikinti įrenginio fotoaparato ir mikrofono blokavimą?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Perjungti klaviat. išdėstymą"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"arba"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Išvalyti paieškos užklausą"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Spartieji klavišai"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Spartieji klavišai"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ieškoti sparčiųjų klavišų"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Sparčiųjų klavišų nerasta"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -770,16 +768,16 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Atidaryti Padėjėją"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Užrakinti ekraną"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Sukurti pastabą"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Kelių užduočių atlikimas sistemoje"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Eiti į išskaidyto ekrano režimą su dabartine programa dešinėje"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Eiti į išskaidyto ekrano režimą su dabartine programa kairėje"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Kelių užduočių atlikimas"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Naudoti išskaidyto ekrano režimą su dabartine programa dešinėje"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Naudoti išskaidyto ekrano režimą su dabartine programa kairėje"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Perjungti iš išskaidyto ekrano režimo į viso ekrano režimą"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Perjunkite į programą dešinėje arba apačioje išskaidyto ekrano režimu"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Perjunkite į programą kairėje arba viršuje išskaidyto ekrano režimu"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Išskaidyto ekrano režimu: pakeisti iš vienos programos į kitą"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Įvestis"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Perjungti į kitą kalbą"</string> - <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Perjungti ankstesnę kalbą"</string> + <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Perjungti į ankstesnę kalbą"</string> <string name="input_access_emoji" msgid="8105642858900406351">"Pasiekti jaustuką"</string> <string name="input_access_voice_typing" msgid="7291201476395326141">"Pasiekti rašymą balsu"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Programos"</string> @@ -1297,7 +1295,7 @@ <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Naudotojo telefono skambučio programa"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Neseniai naudojo telefono skambučio programa"</string> <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Naudoja <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Neseniai naudojo „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string> + <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Neseniai naudojo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Naudoja <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Neseniai naudojo „<xliff:g id="APP_NAME">%1$s</xliff:g>“ (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Naudoja <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml index cfa55522cbf3..c975e7e3cc80 100644 --- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Išjungta"</item> <item msgid="5137565285664080143">"Įjungta"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nepasiekiama"</item> + <item msgid="3079622119444911877">"Išjungta"</item> + <item msgid="3028994095749238254">"Įjungta"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 4413780f684c..74a9239c288a 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problēmas ierakstīšana"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Sākt"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Apturēt"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Kuras ierīces funkcijas tika ietekmētas?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Atlasiet problēmas veidu"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekrāna ierakstīšana"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standarta"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Vidējs"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Augsts"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dzirdes aparāti"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dzirdes aparāti"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Savienojiet pārī jaunu ierīci"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Noklikšķiniet, lai savienotu pārī jaunu ierīci"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vai atbloķēt ierīces mikrofonu?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vai vēlaties atbloķēt ierīces kameru?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vai atbloķēt ierīces kameru un mikrofonu?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Mainīt tastatūras izkārtojumu"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"vai"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Notīrīt meklēšanas vaicājumu"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Īsinājumtaustiņi"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Īsinājumtaustiņi"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Meklēt īsinājumtaustiņus"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nav atrasti"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistēma"</string> @@ -769,10 +767,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Atvērt iestatījumus"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Atvērt Asistentu"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloķēt ekrānu"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Piezīmes izveide"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistēmas vairākuzdevumu režīms"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Pāriet ekrāna sadalīšanas režīmā ar pašreizējo lietotni pa labi"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Pāriet ekrāna sadalīšanas režīmā ar pašreizējo lietotni pa kreisi"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Izveidot piezīmi"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Vairākuzdevumu režīms"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Izmantot ekrāna sadalīšanu ar pašreizējo lietotni labajā pusē"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Izmantot ekrāna sadalīšanu ar pašreizējo lietotni kreisajā pusē"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Pārslēgties no ekrāna sadalīšanas režīma uz pilnekrāna režīmu"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pāriet uz lietotni pa labi/lejā, kamēr izmantojat sadalīto ekrānu."</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pāriet uz lietotni pa kreisi/augšā, kamēr izmantojat sadalīto ekrānu."</string> diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml index e6b4deab07ea..c65a1d429492 100644 --- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Izslēgts"</item> <item msgid="5137565285664080143">"Ieslēgts"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nav pieejams"</item> + <item msgid="3079622119444911877">"Izslēgts"</item> + <item msgid="3028994095749238254">"Ieslēgts"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 4f5bf6cfd833..36d49e4241e1 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -276,7 +276,7 @@ <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматски вклучи повторно утре"</string> <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Функциите како „Брзо споделување“, „Најди го мојот уред“ и локација на уредот користат Bluetooth"</string> <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ќе се вклучи утре во 5:00"</string> - <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батерија"</string> + <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Слушалки"</string> <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Влез"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Евидентирајте проблем"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Започнете"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Сопрете"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Кој дел од доживувањето на уредот беше засегнат?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Изберете тип проблем"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Снимање екран"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандарден"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Среден"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Висок"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Спари нов уред"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за да спарите нов уред"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се одблокира пристапот до микрофонот на уредот?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се одблокира пристапот до камерата на уредот?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Да се одблокира пристапот до камерата и микрофонот на уредот?"</string> @@ -669,7 +667,7 @@ <string name="notification_automatic_title" msgid="3745465364578762652">"Автоматски"</string> <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звук или вибрации"</string> <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звук или вибрации и се појавува подолу во делот со разговори"</string> - <string name="notification_channel_summary_default" msgid="777294388712200605">"Може да ѕвони или вибрира во зависност од поставките на уредот"</string> + <string name="notification_channel_summary_default" msgid="777294388712200605">"Може да ѕвони или вибрира во зависност од поставките за уредот"</string> <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Може да ѕвони или вибрира во зависност од поставките на уредот. Стандардно, разговорите од <xliff:g id="APP_NAME">%1$s</xliff:g> се во балончиња."</string> <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Дозволете системот да определи дали известувањево треба да испушти звук или да вибрира"</string> <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Статус:</b> поставено на „Стандардно“"</string> @@ -719,7 +717,7 @@ <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Центар"</string> <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string> - <string name="keyboard_key_enter" msgid="8633362970109751646">"Внеси"</string> + <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Бришење наназад"</string> <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Пушти/Паузирај"</string> <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Сопри"</string> @@ -745,13 +743,13 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени јазик на тастатура"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Бришење поим за пребарување"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Кратенки"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Кратенки од тастатура"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пребарувајте кратенки"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Не се пронајдени кратенки"</string> - <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Системски"</string> + <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Систем"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Внесување"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворени аплик."</string> - <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Тековна аплик."</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворање апликации"</string> + <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Тековна апликација"</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Се прикажуваат резултати од пребарувањето"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Се прикажуваат системски кратенки"</string> <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Се прикажуваат кратенки за внесување"</string> @@ -768,14 +766,14 @@ <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Отворете го списокот со апликации"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Отворете „Поставки“"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отворете го „Помошникот“"</string> - <string name="group_system_lock_screen" msgid="7391191300363416543">"Заклучен екран"</string> + <string name="group_system_lock_screen" msgid="7391191300363416543">"Заклучете го екранот"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Фатете белешка"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Системски мултитаскинг"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Активирајте поделен екран со тековната апликација десно"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Активирајте поделен екран со тековната апликација лево"</string> - <string name="system_multitasking_full_screen" msgid="336048080383640562">"Префрлете од поделен екран во цел екран"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Префрлете на апликацијата десно или долу при користењето поделен екран"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Префрлете на апликацијата лево или горе при користењето поделен екран"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Мултитаскинг"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Користете поделен екран со тековната апликација оддесно"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Користете поделен екран со тековната апликација одлево"</string> + <string name="system_multitasking_full_screen" msgid="336048080383640562">"Префрлете се од поделен екран на цел екран"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Префрлете се на апликацијата десно или долу при користењето поделен екран"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Префрлете се на апликацијата лево или горе при користењето поделен екран"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"При поделен екран: префрлете ги аплик. од едната на другата страна"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Внесување"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Префрлете на следниот јазик"</string> @@ -1285,7 +1283,7 @@ <string name="dismiss_dialog" msgid="2195508495854675882">"Отфрли"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"Екранот е поврзан"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string> - <string name="privacy_dialog_summary" msgid="2458769652125995409">"Неодамнешно користење на апликација"</string> + <string name="privacy_dialog_summary" msgid="2458769652125995409">"Неодамнешно користење од апликациите"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Видете го скорешниот пристап"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Готово"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Проширување и прикажување на опциите"</string> diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml index 0d811206a766..a8d96950b6f8 100644 --- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Исклучено"</item> <item msgid="5137565285664080143">"Вклучено"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Недостапно"</item> + <item msgid="3079622119444911877">"Исклучено"</item> + <item msgid="3028994095749238254">"Вклучено"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 8ce379627d9c..b20faa9af6e4 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"പ്രശ്നം റെക്കോർഡ് ചെയ്യുക"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ആരംഭിക്കുക"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"നിർത്തുക"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ബഗ് റിപ്പോർട്ട്"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"നിങ്ങളുടെ ഉപകരണ അനുഭവത്തിന്റെ ഏത് ഭാഗമാണ് ബാധിച്ചത്?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"പ്രശ്ന തരം തിരഞ്ഞെടുക്കുക"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"സ്ക്രീൻ റെക്കോർഡ്"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ഇടത്തരം"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"കൂടുതൽ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"പുതിയ ഉപകരണം ജോടിയാക്കുക"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"പുതിയ ഉപകരണം ജോടിയാക്കാൻ ക്ലിക്ക് ചെയ്യുക"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ഉപകരണ മൈക്രോഫോൺ അൺബ്ലോക്ക് ചെയ്യണോ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ഉപകരണ ക്യാമറ അൺബ്ലോക്ക് ചെയ്യണോ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ഉപകരണ ക്യാമറയോ മൈക്രോഫോണോ അൺബ്ലോക്ക് ചെയ്യണോ?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"കീബോർഡ് ലേഔട്ട് മാറുക"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"അല്ലെങ്കിൽ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"തിരയൽ ചോദ്യം മായ്ക്കുക"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"കുറുക്കുവഴികൾ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"കീബോർഡ് കുറുക്കുവഴികൾ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"കുറുക്കുവഴികൾ തിരയുക"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"കുറുക്കുവഴി കണ്ടെത്തിയില്ല"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"സിസ്റ്റം"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant തുറക്കുക"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ലോക്ക് സ്ക്രീൻ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ഒരു കുറിപ്പെടുക്കുക"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"സിസ്റ്റം മൾട്ടിടാസ്കിംഗ്"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"നിലവിലെ ആപ്പ് വലതുവശത്ത് വരുന്ന രീതിയിൽ സ്ക്രീൻ വിഭജന മോഡിൽ കടക്കുക"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"നിലവിലെ ആപ്പ് ഇടതുവശത്ത് വരുന്ന രീതിയിൽ സ്ക്രീൻ വിഭജന മോഡിൽ കടക്കുക"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"മൾട്ടിടാസ്കിംഗ്"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"വലതുവശത്തുള്ള നിലവിലെ ആപ്പിനൊപ്പം സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുക"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ഇടതുവശത്തുള്ള നിലവിലെ ആപ്പിനൊപ്പം സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുക"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"സ്ക്രീൻ വിഭജന മോഡിൽ നിന്ന് പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറുക"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുമ്പോൾ വലതുവശത്തെ/താഴത്തെ ആപ്പിലേക്ക് മാറൂ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുമ്പോൾ ഇടതുവശത്തെ/മുകളിലെ ആപ്പിലേക്ക് മാറൂ"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 1a2e4b1f8c78..333ab55b6485 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Асуудлыг бичих"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Эхлүүлэх"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Зогсоох"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Таны төхөөрөмжийн хэрэглээний аль хэсэгт нөлөөлсөн бэ?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Асуудлын төрөл сонгоно уу"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Дэлгэцийн бичлэг"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандарт"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Дунд зэрэг"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Өндөр"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Сонсголын төхөөрөмжүүд"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Сонсголын төхөөрөмжүүд"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Шинэ төхөөрөмж хослуулах"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Шинэ төхөөрөмж хослуулахын тулд товшино уу"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Төхөөрөмжийн микрофоныг блокоос гаргах уу?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Төхөөрөмжийн камерыг блокоос гаргах уу?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Төхөөрөмжийн камер болон микрофоныг блокоос гаргах уу?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Гарын бүдүүвч рүү сэлгэх"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"эсвэл"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Хайлтын асуулгыг арилгах"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Товчлолууд"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Товчлуурын шууд холбоос"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Товчлолууд хайх"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ямар ч товчлол олдсонгүй"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Систем"</string> @@ -770,12 +768,12 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Туслахыг нээх"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Түгжээтэй дэлгэц"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Тэмдэглэл хөтлөх"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Систем олон ажил зэрэг хийх"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Одоогийн аппаар баруун гар талд дэлгэц хуваахад орох"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Одоогийн аппаар зүүн гар талд дэлгэц хуваахад орох"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Олон ажил зэрэг хийх"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Одоогийн аппыг баруун талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Одоогийн аппыг зүүн талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Дэлгэц хуваахаас бүтэн дэлгэц рүү сэлгэх"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Дэлгэц хуваахыг ашиглаж байхдаа баруун эсвэл доор байх апп руу сэлгэ"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Дэлгэц хуваахыг ашиглаж байхдаа зүүн эсвэл дээр байх апп руу сэлгэ"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Дэлгэц хуваахыг ашиглаж байхдаа баруун талд эсвэл доор байх апп руу сэлгэ"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Дэлгэц хуваахыг ашиглаж байхдаа зүүн талд эсвэл дээр байх апп руу сэлгэ"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Дэлгэц хуваах үеэр: аппыг нэгээс нөгөөгөөр солих"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Оролт"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Дараагийн хэл рүү сэлгэх"</string> @@ -1268,7 +1266,7 @@ <string name="call_from_work_profile_action" msgid="2937701298133010724">"Ажлын профайл руу сэлгэх"</string> <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Ажлын гар утасны апп суулгах"</string> <string name="call_from_work_profile_close" msgid="5830072964434474143">"Цуцлах"</string> - <string name="lock_screen_settings" msgid="6152703934761402399">"Түгжигдсэн дэлгэцийг өөрчлөх"</string> + <string name="lock_screen_settings" msgid="6152703934761402399">"Түгжээтэй дэлгэцийг өөрчлөх"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Түгжээтэй дэлгэцийг өөрчлөхийн тулд түгжээг тайлна уу"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi боломжгүй байна"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерыг блоклосон"</string> diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml index cfaf693ccd4c..a3f54541880d 100644 --- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Унтраалттай"</item> <item msgid="5137565285664080143">"Асаалттай"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Боломжгүй"</item> + <item msgid="3079622119444911877">"Унтраалттай"</item> + <item msgid="3028994095749238254">"Асаалттай"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 2e21fd078785..5bed1b432909 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"समस्या रेकॉर्ड करा"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"सुरुवात करा"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"थांबवा"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"तुमच्या डिव्हाइसबाबत कोणत्या अनुभवावर परिणाम झाला?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"समस्येचा प्रकार निवडा"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"स्क्रीन रेकॉर्ड"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"साधारण"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"मध्यम"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"उच्च"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"श्रवणयंत्रे"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"श्रवणयंत्रे"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नवीन डिव्हाइस पेअर करा"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नवीन डिव्हाइस पेअर करण्यासाठी क्लिक करा"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिव्हाइसचा मायक्रोफोन अनब्लॉक करायचा आहे का?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिव्हाइसचा कॅमेरा अनब्लॉक करायचा आहे का?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"डिव्हाइसचा कॅमेरा आणि मायक्रोफोन अनब्लॉक करायचा आहे का?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट स्विच करा"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"किंवा"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"शोध क्वेरी साफ करा"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"कीबोर्ड शॉर्टकट"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"शॉर्टकट शोधा"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"एकही शॉर्टकट आढळला नाहीत"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"सिस्टीम"</string> @@ -757,7 +755,7 @@ <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"इनपुट शॉर्टकट दाखवत आहे"</string> <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ॲप्स उघडणारे शॉर्टकट दाखवत आहे"</string> <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"सद्य अॅपसाठी शॉर्टकट दाखवत आहे"</string> - <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचना पहा"</string> + <string name="group_system_access_notification_shade" msgid="1619028907006553677">"नोटिफिकेशन पहा"</string> <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रीनशॉट घ्या"</string> <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट दाखवा"</string> <string name="group_system_go_back" msgid="2730322046244918816">"मागे जा"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant उघडा"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"नोंद घ्या"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टीम मल्टिटास्किंग"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"उजव्या बाजूला सध्याचे अॅप असलेल्या स्प्लिट स्क्रीनवर जा"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"डाव्या बाजूला सध्याचे अॅप असलेल्या स्प्लिट स्क्रीनवर जा"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टिटास्किंग"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"सद्य ॲप उजवीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"सद्य ॲप डावीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"स्प्लिट स्क्रीनवरून फुल स्क्रीनवर स्विच करा"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन वापरताना उजवीकडील किंवा खालील अॅपवर स्विच करा"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन वापरताना डावीकडील किंवा वरील अॅपवर स्विच करा"</string> diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml index abb7aceec4e2..54c320c953d5 100644 --- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"बंद आहे"</item> <item msgid="5137565285664080143">"सुरू आहे"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"उपलब्ध नाही"</item> + <item msgid="3079622119444911877">"बंद आहे"</item> + <item msgid="3028994095749238254">"सुरू आहे"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 9ae774f511f9..4df6540c617e 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Rekodkan masalah"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Mula"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Hentikan"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Laporan Pepijat"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Pengalaman peranti yang manakah yang terjejas?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Pilih jenis masalah"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rakam skrin"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Sederhana"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Tinggi"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Peranti pendengaran"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Peranti pendengaran"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Gandingkan peranti baharu"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menggandingkan peranti baharu"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Nyahsekat mikrofon peranti?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Nyahsekat kamera peranti?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Nyahsekat kamera dan mikrofon peranti?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tukar reka letak papan kekunci"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"atau"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Kosongkan pertanyaan carian"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Pintasan Papan Kekunci"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cari pintasan"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tiada pintasan ditemukan"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> @@ -762,16 +760,16 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Kembali"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Akses skrin utama"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Lihat apl terbaharu"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Kitar ke hadapan menerusi apl terbaharu"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Kitar ke belakang menerusi apl terbaharu"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Navigasi apl terbaharu ke arah kanan"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Navigasi apl terbaharu ke arah kiri"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Buka senarai apl"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Buka tetapan"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Buka Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci skrin"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Catat nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Berbilang tugas sistem"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Masuk skrin pisah dengan apl semasa pada sisi kanan"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Masuk skrin pisah dengan apl semasa pada sisi kiri"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Berbilang tugas"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gunakan skrin pisah dengan apl semasa pada sebelah kanan"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gunakan skrin pisah dengan apl semasa pada sebelah kiri"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Beralih daripada skrin pisah kepada skrin penuh"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Tukar kepada apl di sebelah kanan/bawah semasa menggunakan skrin pisah"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Tukar kepada apl di sebelah kiri/atas semasa menggunakan skrin pisah"</string> @@ -1124,7 +1122,7 @@ <string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string> <string name="select_conversation_title" msgid="6716364118095089519">"Widget perbualan"</string> <string name="select_conversation_text" msgid="3376048251434956013">"Ketik perbualan untuk menambahkan perbualan itu pada skrin Utama anda"</string> - <string name="no_conversations_text" msgid="5354115541282395015">"Perbualan terbaharu anda akan dipaparkan di sini"</string> + <string name="no_conversations_text" msgid="5354115541282395015">"Perbualan terbaharu akan dipaparkan di sini"</string> <string name="priority_conversations" msgid="3967482288896653039">"Perbualan keutamaan"</string> <string name="recent_conversations" msgid="8531874684782574622">"Perbualan terbaharu"</string> <string name="days_timestamp" msgid="5821854736213214331">"<xliff:g id="DURATION">%1$s</xliff:g> hari lalu"</string> @@ -1193,7 +1191,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# apl aktif}other{# apl aktif}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Maklumat baharu"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apl aktif"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Apl ini aktif dan berfungsi walaupun anda tidak menggunakannya. Ini meningkatkan kefungsian apl tetapi mungkin akan memberikan kesan kepada hayat bateri."</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Apl ini aktif dan berfungsi walaupun anda tidak menggunakannya. Hal ini meningkatkan kefungsian apl tetapi akan memberikan kesan kepada hayat bateri."</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Berhenti"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Dihentikan"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Selesai"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 12498851a449..a1894b04277b 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -235,7 +235,7 @@ <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"အကြောင်းကြားစာအကွက်"</string> <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"အမြန်လုပ် အပြင်အဆင်"</string> <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‘အမြန်ဆက်တင်များ’ နှင့် ‘အကြောင်းကြားစာအကွက်’။"</string> - <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"မျက်နှာပြင် သော့ပိတ်ရန်"</string> + <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"လော့ခ်မျက်နှာပြင်"</string> <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string> <string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string> <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"လုံးဝ အသံပိတ်ထားရန်"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ပြဿနာကို မှတ်တမ်းတင်ခြင်း"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"စတင်ပါ"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"ရပ်ပါ"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"စက်အသုံးပြုမှု၏ မည်သည့်အပိုင်းကို သက်ရောက်သလဲ။"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ပြဿနာအမျိုးအစား ရွေးရန်"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ဖန်သားပြင်ရိုက်ကူးရန်"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"အသင့်အတင့်"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"များ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"နားကြားကိရိယာ"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"နားကြားကိရိယာ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"စက်အသစ်တွဲချိတ်ရန်"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"စက်အသစ် တွဲချိတ်ရန် နှိပ်ပါ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"စက်၏မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"စက်၏ကင်မရာကို ပြန်ဖွင့်မလား။"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"စက်၏ကင်မရာနှင့် မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string> @@ -550,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်။ သင့်မိဘက သင်သုံးသောအက်ပ်များ၊ သင်၏တည်နေရာနှင့် အသုံးပြုချိန် ကဲ့သို့သော အချက်အလက်များကို မြင်နိုင်ပြီး စီမံခန့်ခွဲနိုင်သည်။"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ဖြင့် ဆက်ဖွင့်ထားရန်"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"စက်လော့ခ်ကျနေသည်၊ အထောက်အထားစိစစ်ရန် ကြိုးပမ်းမှုအကြိမ်ရေ များလွန်းသည်"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"လော့ခ်ကျနေသည်၊ အထောက်အထားစိစစ်ရန် ကြိုးပမ်းကြိမ် များလွန်းသည်"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"စက်လော့ခ်ကျနေသည်\nအထောက်အထားစိစစ်၍ မရပါ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>။ <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"အသံဆက်တင်များ"</string> @@ -593,7 +592,7 @@ <string name="stream_accessibility" msgid="3873610336741987152">"အများသုံးနိုင်မှု"</string> <string name="volume_ringer_status_normal" msgid="1339039682222461143">"အသံမြည်သည်"</string> <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"တုန်ခါသည်"</string> - <string name="volume_ringer_status_silent" msgid="3691324657849880883">"အသံတိတ်သည်"</string> + <string name="volume_ringer_status_silent" msgid="3691324657849880883">"အသံပိတ်ရန်"</string> <string name="media_device_cast" msgid="4786241789687569892">"ကာစ်လုပ်ရန်"</string> <string name="stream_notification_unavailable" msgid="4313854556205836435">"ဖုန်းမြည်သံပိတ်ထားသဖြင့် မရနိုင်ပါ"</string> <string name="stream_alarm_unavailable" msgid="4059817189292197839">"‘မနှောင့်ယှက်ရ’ ဖွင့်ထားသောကြောင့် မရနိုင်ပါ"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ကီးဘုတ်အပြင်အဆင် ပြောင်းခြင်း"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"သို့မဟုတ်"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ရှာဖွေစာလုံး ရှင်းထုတ်ရန်"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ဖြတ်လမ်းလင့်ခ်များ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"လက်ကွက်ဖြတ်လမ်းများ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ဖြတ်လမ်းလင့်ခ်များ ရှာပါ"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ဖြတ်လမ်းလင့်ခ် မတွေ့ပါ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"စနစ်"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ဖွင့်ရန်"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"လော့ခ်မျက်နှာပြင်"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"မှတ်စုရေးရန်"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"စနစ်က တစ်ပြိုင်နက် များစွာလုပ်ခြင်း"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"လက်ရှိအက်ပ်ကို မျက်နှာပြင် ခွဲ၍ပြသမှု၏ ညာဘက်တွင်ထည့်ရန်"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"လက်ရှိအက်ပ်ကို မျက်နှာပြင် ခွဲ၍ပြသမှု၏ ဘယ်ဘက်တွင်ထည့်ရန်"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"တစ်ပြိုင်နက် များစွာလုပ်ခြင်း"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"လက်ရှိအက်ပ်ကို ညာ၌ထားကာ မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံးရန်"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"လက်ရှိအက်ပ်ကို ဘယ်၌ထားကာ မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံးရန်"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"မျက်နှာပြင် ခွဲ၍ပြသမှုမှ မျက်နှာပြင်အပြည့်သို့ ပြောင်းရန်"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"မျက်နှာပြင်ခွဲ၍ပြသခြင်း သုံးစဉ် ညာ (သို့) အောက်ရှိအက်ပ်သို့ ပြောင်းရန်"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးစဉ် ဘယ် (သို့) အထက်ရှိအက်ပ်သို့ ပြောင်းရန်"</string> @@ -867,7 +866,7 @@ <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ဆက်တင်များ၏ အစီအစဉ်ကို တည်းဖြတ်ပါ။"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ပါဝါမီနူး"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string> - <string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်ချထားချိန် မျက်နှာပြင်"</string> + <string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်မျက်နှာပြင်"</string> <string name="finder_active" msgid="7907846989716941952">"ပါဝါပိတ်ထားသော်လည်း Find My Device ဖြင့် ဤဖုန်းကို ရှာနိုင်သည်"</string> <string name="shutdown_progress" msgid="5464239146561542178">"စက်ပိတ်နေသည်…"</string> <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 0f9bb464f21f..5039150d06eb 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Registrer problem"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stopp"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Hvilken del av enhetsopplevelsen din ble påvirket?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Velg problemtype"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skjermopptak"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Middels"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Høy"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Høreapparater"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Koble til en ny enhet"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klikk for å koble til en ny enhet"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du oppheve blokkeringen av enhetsmikrofonen?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du oppheve blokkeringen av enhetskameraet?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vil du oppheve blokkeringen av enhetskameraet og -mikrofonen?"</string> @@ -551,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enheten administreres av forelderen din. Forelderen din kan se og administrere informasjon, for eksempel appene du bruker, posisjonen din og skjermtiden din."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Holdes opplåst med TrustAgent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Enheten var låst – for mange autentiseringsforsøk"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Enheten er låst – for mange autentiseringsforsøk"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Enheten er låst\nKunne ikke autentisere"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Lydinnstillinger"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Bytt tastaturoppsett"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Fjern søket"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Hurtigtaster"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Hurtigtaster"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søk etter hurtigtaster"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Fant ingen hurtigtaster"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Åpne assistenten"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Låseskjerm"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Ta et notat"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking på systemet"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Åpne delt skjerm med den aktive appen til høyre"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Åpne delt skjerm med den aktive appen til venstre"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Bruk delt skjerm med den nåværende appen til høyre"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Bruk delt skjerm med den nåværende appen til venstre"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Bytt fra delt skjerm til fullskjerm"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bytt til appen til høyre eller under mens du bruker delt skjerm"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bytt til appen til venstre eller over mens du bruker delt skjerm"</string> diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml index af0042395127..a9efd1d95a7d 100644 --- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Av"</item> <item msgid="5137565285664080143">"På"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Ikke tilgjengelig"</item> + <item msgid="3079622119444911877">"Av"</item> + <item msgid="3028994095749238254">"På"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 5f51a9136a3f..28c7b05a290f 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -62,7 +62,7 @@ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi सेयर गर्नुहोस्"</string> <string name="wifi_debugging_title" msgid="7300007687492186076">"यस नेटवर्कमा वायरलेस डिबगिङ सेवा प्रयोग गर्न दिने हो?"</string> <string name="wifi_debugging_message" msgid="5461204211731802995">"नेटवर्कको नाम (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi ठेगाना (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string> - <string name="wifi_debugging_always" msgid="2968383799517975155">"यस नेटवर्कमा सधैँ अनुमति दिइयोस्"</string> + <string name="wifi_debugging_always" msgid="2968383799517975155">"यस नेटवर्कमा सधैँ अनुमति दिनुहोस्"</string> <string name="wifi_debugging_allow" msgid="4573224609684957886">"अनुमति दिनुहोस्"</string> <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"वायरलेस डिबगिङ सेवालाई अनुमति दिइएको छैन"</string> <string name="wifi_debugging_secondary_user_message" msgid="9085779370142222881">"हालैमा यस डिभाइसमा साइन इन भएका प्रयोगकर्ताले USB डिबगिङ सक्रिय गर्न सक्दैनन्। यो सुविधा प्रयोग गर्न कृपया खाताका एड्मिनका रूपमा साइन इन गर्नुहोस्।"</string> @@ -108,7 +108,7 @@ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"तपाईंले रेकर्ड गर्दै गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"तपाईंले कुनै एप रेकर्ड गर्दै गर्दा Android ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"रेकर्ड गर्न थाल्नुहोस्"</string> - <string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गरियोस्"</string> + <string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गर्नुहोस्"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिभाइसको अडियो"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तपाईंको डिभाइसका सङ्गीत, कल र रिङटोन जस्ता साउन्ड"</string> <string name="screenrecord_mic_label" msgid="2111264835791332350">"माइक्रोफोन"</string> @@ -116,7 +116,7 @@ <string name="screenrecord_continue" msgid="4055347133700593164">"सुरु गर्नुहोस्"</string> <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"स्क्रिन रेकर्ड गरिँदै छ"</string> <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"स्क्रिन र अडियो रेकर्ड गरिँदै छ"</string> - <string name="screenrecord_taps_label" msgid="1595690528298857649">"स्पर्श गरिएका स्थानहरू देखाइयोस्"</string> + <string name="screenrecord_taps_label" msgid="1595690528298857649">"स्पर्श गरिएका स्थानहरू देखाउनुहोस्"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"रोक्नुहोस्"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"सेयर गर्नुहोस्"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"स्क्रिन रेकर्डिङ सेभ गरियो"</string> @@ -273,14 +273,14 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेभ गरिएको छ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट गर्नुहोस्"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"एक्टिभेट गर्नुहोस्"</string> - <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"भोलि फेरि स्वतः अन गरियोस्"</string> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"भोलि फेरि स्वतः अन गर्नुहोस्"</string> <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"क्विक सेयर, Find My Device र डिभाइसको लोकेसन जस्ता सुविधाहरूले ब्लुटुथ प्रयोग गर्छन्"</string> <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ब्लुटुथ भोलि बिहान ५ बजे अन हुने छ"</string> <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ब्याट्री"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"अडियो"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string> <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"इनपुट"</string> - <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"श्रवण यन्त्रहरू"</string> + <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"हियरिङ डिभाइसहरू"</string> <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"सक्रिय गर्दै…"</string> <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अटो रोटेट"</string> <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्क्रिन स्वतःघुम्ने"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"समस्या रेकर्ड गर्नुहोस्"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"सुरु गर्नुहोस्"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"रोक्नुहोस्"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"त्रुटिको रिपोर्ट"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"तपाईंको डिभाइसको कुन चाहिँ सुविधा प्रभावित भएको छ?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"समस्याको प्रकार चयन गर्नुहोस्"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"स्क्रिन रेकर्ड"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"डिफल्ट"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"मध्यम"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"उच्च"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"हियरिङ डिभाइसहरू"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"हियरिङ डिभाइसहरू"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नयाँ डिभाइस कनेक्ट गर्नुहोस्"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नयाँ डिभाइसमा कनेक्ट गर्न क्लिक गर्नुहोस्"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिभाइसको माइक्रोफोन अनब्लक गर्ने हो?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिभाइसको क्यामेरा अनब्लक गर्ने हो?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"डिभाइसको क्यामेरा र माइक्रोफोन अनब्लक गर्ने हो?"</string> @@ -551,7 +548,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"यो डिभाइस तपाईंका अभिभावक व्यवस्थापन गर्नुहुन्छ। तपाईंका अभिभावक तपाईंले प्रयोग गर्ने एप, तपाईंको स्थान र तपाईंले यन्त्र चलाएर बिताउने समय जस्ता जानकारी हेर्न तथा व्यवस्थापन गर्न सक्नुहुन्छ।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ले खुला राखेको"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"डिभाइस लक गरिएको छ, प्रमाणीकरण गर्ने निकै धेरै प्रयास गरिएका छन्"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"डिभाइस लक गरिएको छ, निकै धेरै पटक प्रमाणीकरण गर्ने प्रयास भएको छ"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"डिभाइस लक गरिएको छ\nप्रमाणीकरण गर्न सकिएन"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ध्वनिसम्बन्धी सेटिङहरू"</string> @@ -631,7 +628,7 @@ <string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"फोनमार्फत अझ छिटो र थप सुरक्षित तरिकाले खरिद गर्न भुक्तानी विधि सेटअप गर्नुहोस्"</string> - <string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाइयोस्"</string> + <string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाउनुहोस्"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"खोल्न ट्याप गर्नुहोस्"</string> <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"अपडेट गरिँदै छ"</string> <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"किबोर्डको लेआउट बदल्नुहोस्"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"वा"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"किवर्ड हटाउनुहोस्"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"सर्टकटहरू"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"किबोर्डका सर्टकटहरू"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"सर्टकटहरू खोज्नुहोस्"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"कुनै पनि सर्टकट भेटिएन"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"सिस्टम"</string> @@ -759,7 +756,7 @@ <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"हालको एपका लागि सर्टकटहरू देखाइँदै छ"</string> <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचनाहरू हेर्नुहोस्"</string> <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रिनसट खिच्नुहोस्"</string> - <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"सर्टकटहरू देखाइऊन्"</string> + <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"सर्टकटहरू देखाउनुहोस्"</string> <string name="group_system_go_back" msgid="2730322046244918816">"पछाडि जानुहोस्"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"होम स्क्रिनमा जानुहोस्"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"हालसालै चलाइएका एपहरू हेर्ने तरिका"</string> @@ -769,10 +766,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"सेटिङ खोल्नुहोस्"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"एसिस्टेन्ट खोल्नुहोस्"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रिन लक गर्नुहोस्"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट लेख"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टम मल्टिटास्किङ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"हालको एप दायाँतर्फ रहने गरी स्प्लिट स्क्रिन मोड सुरु गर्नुहोस्"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"हालको एप बायाँतर्फ रहने गरी स्प्लिट स्क्रिन मोड सुरु गर्नुहोस्"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट लेख्नुहोस्"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"एकै पटक एकभन्दा बढी एप चलाउन मिल्ने सुविधा"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"हालको एप दायाँ भागमा पारेर स्प्लिट स्क्रिन प्रयोग गर्नुहोस्"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"हालको एप बायाँ भागमा पारेर स्प्लिट स्क्रिन प्रयोग गर्नुहोस्"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"स्प्लिट स्क्रिनको साटो फुल स्क्रिन प्रयोग गर्नुहोस्"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रिन प्रयोग गर्दै गर्दा दायाँ वा तलको एप चलाउनुहोस्"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रिन प्रयोग गर्दै गर्दा बायाँ वा माथिको एप चलाउनुहोस्"</string> @@ -1288,7 +1285,7 @@ <string name="privacy_dialog_summary" msgid="2458769652125995409">"एपको हालसालैको प्रयोग"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"हालसालै एक्सेस गर्ने एप हेर्नुहोस्"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"पूरा भयो"</string> - <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"एक्स्पान्ड गरियोस् र विकल्पहरू देखाइयोस्"</string> + <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"एक्स्पान्ड गर्नुहोस् र विकल्पहरू देखाउनुहोस्"</string> <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"कोल्याप्स गर्नुहोस्"</string> <string name="privacy_dialog_close_app_button" msgid="8006250171305878606">"यो एप बन्द गर्नुहोस्"</string> <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"<xliff:g id="APP_NAME">%1$s</xliff:g> बन्द गरिएको छ"</string> diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml index 005a473a79c1..c1b2f3420a40 100644 --- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"अफ छ"</item> <item msgid="5137565285664080143">"अन छ"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"उपलब्ध छैन"</item> + <item msgid="3079622119444911877">"अफ छ"</item> + <item msgid="3028994095749238254">"अन छ"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 1f780b3bff4e..d0500c04568e 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -145,7 +145,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Spraakassistent"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portemonnee"</string> - <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-codescanner"</string> + <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-codescanner"</string> <string name="accessibility_unlock_button" msgid="3613812140816244310">"Ontgrendeld"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Apparaat vergrendeld"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gezicht scannen"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Probleem vastleggen"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Starten"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stoppen"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Op welk onderdeel van de apparaatfunctionaliteit had dit effect?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Probleemtype selecteren"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Schermopname"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standaard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Gemiddeld"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hoog"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hoortoestellen"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hoortoestellen"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Nieuw apparaat koppelen"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nieuw apparaat te koppelen"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Microfoon van apparaat niet meer blokkeren?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Apparaatcamera niet meer blokkeren?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Blokkeren van apparaatcamera en -microfoon opheffen?"</string> @@ -551,7 +549,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dit apparaat wordt beheerd door je ouder. Je ouder kan informatie bekijken en beheren, zoals de apps die je gebruikt, je locatie en je schermtijd."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ontgrendeld gehouden door TrustAgent"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Het apparaat is vergrendeld na te veel verificatiepogingen"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Te veel pogingen. Apparaat vergrendeld."</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Apparaat vergrendeld\nVerificatie mislukt"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Geluidsinstellingen"</string> @@ -637,7 +635,7 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontgrendelen om te gebruiken"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Instellingen voor vergrendelscherm"</string> - <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR-codescanner"</string> + <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR-codescanner"</string> <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Updaten"</string> <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Toetsenbordindeling wisselen"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"of"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Zoekopdracht wissen"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Sneltoetsen"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Sneltoetsen"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sneltoetsen zoeken"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen sneltoetsen gevonden"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systeem"</string> @@ -770,12 +768,12 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistent openen"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Scherm vergrendelen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Notitie maken"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systeem-multitasking"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Gesplitst scherm openen met huidige app rechts"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Gesplitst scherm openen met huidige app links"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasken"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gesplitst scherm gebruiken met de huidige app aan de rechterkant"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gesplitst scherm gebruiken met de huidige app aan de linkerkant"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Van gesplitst scherm naar volledig scherm schakelen"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ga naar de app rechts of onderaan als je een gesplitst scherm gebruikt"</string> - <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ga naar de app links of bovenaan als je een gesplitst scherm gebruikt"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Naar de app rechts of onderaan gaan als je een gesplitst scherm gebruikt"</string> + <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Naar de app links of bovenaan gaan als je een gesplitst scherm gebruikt"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Tijdens gesplitst scherm: een app vervangen door een andere"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Invoer"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Overschakelen naar volgende taal"</string> @@ -829,8 +827,8 @@ <string name="right_keycode" msgid="2480715509844798438">"Toetscode rechts"</string> <string name="left_icon" msgid="5036278531966897006">"Icoon links"</string> <string name="right_icon" msgid="1103955040645237425">"Icoon rechts"</string> - <string name="drag_to_add_tiles" msgid="8933270127508303672">"Houd vast en sleep om tegels toe te voegen"</string> - <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Houd vast en sleep om tegels opnieuw in te delen"</string> + <string name="drag_to_add_tiles" msgid="8933270127508303672">"Houd een tegel ingedrukt en sleep om die toe te voegen"</string> + <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Houd een tegel ingedrukt en sleep om die te verplaatsen"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Sleep hier naartoe om te verwijderen"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"Je hebt minimaal <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tegels nodig"</string> <string name="qs_edit" msgid="5583565172803472437">"Bewerken"</string> @@ -1262,7 +1260,7 @@ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Nog <xliff:g id="PERCENTAGE">%s</xliff:g> batterijlading"</string> <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Verbind je stylus met een oplader"</string> <string name="stylus_battery_low" msgid="7134370101603167096">"Batterij van stylus bijna leeg"</string> - <string name="video_camera" msgid="7654002575156149298">"Videocamera"</string> + <string name="video_camera" msgid="7654002575156149298">"Videocamera"</string> <string name="call_from_work_profile_title" msgid="5418253516453177114">"Kan niet bellen vanuit een app voor persoonlijke doeleinden"</string> <string name="call_from_work_profile_text" msgid="2856337395968118274">"Je organisatie staat je alleen toe om te bellen vanuit werk-apps"</string> <string name="call_from_work_profile_action" msgid="2937701298133010724">"Overschakelen naar werkprofiel"</string> diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml index 1b286f33d583..c5d93610fb87 100644 --- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Uit"</item> <item msgid="5137565285664080143">"Aan"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Niet beschikbaar"</item> + <item msgid="3079622119444911877">"Uit"</item> + <item msgid="3028994095749238254">"Aan"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 9a602b86bf33..eb6865ea4111 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ସମସ୍ୟାର ରେକର୍ଡ କରନ୍ତୁ"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"ବନ୍ଦ କରନ୍ତୁ"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ବଗ୍ ରିପୋର୍ଟ୍"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ଆପଣଙ୍କ ଡିଭାଇସ ଅନୁଭୂତିର କେଉଁ ଅଂଶ ପ୍ରଭାବିତ ହୋଇଛି?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ସମସ୍ୟାର ପ୍ରକାର ଚୟନ କରନ୍ତୁ"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ସ୍କ୍ରିନ ରେକର୍ଡ"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ଷ୍ଟାଣ୍ଡାର୍ଡ"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ମଧ୍ୟମ"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ଅଧିକ"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ନୂଆ ଡିଭାଇସ ପେୟାର କର"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ନୂଆ ଡିଭାଇସ ପେୟାର କରିବାକୁ କ୍ଲିକ କରନ୍ତୁ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ କରିବେ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ଡିଭାଇସର କେମେରାକୁ ଅନବ୍ଲକ କରିବେ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ଡିଭାଇସର କ୍ୟାମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ୍ କରିବେ?"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"କୀ\'ବୋର୍ଡ୍ର ଲେଆଉଟ୍କୁ ବଦଳାନ୍ତୁ"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"କିମ୍ବା"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ସର୍ଚ୍ଚ କ୍ୱେରୀକୁ ଖାଲି କରନ୍ତୁ"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ସର୍ଟକଟଗୁଡ଼ିକ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"କୀବୋର୍ଡ ସର୍ଟକଟ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ସର୍ଟକଟ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"କୌଣସି ସର୍ଟକଟ ମିଳିଲା ନାହିଁ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ସିଷ୍ଟମ"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ଖୋଲନ୍ତୁ"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ଲକ ସ୍କ୍ରିନ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ଏକ ନୋଟ ଲେଖନ୍ତୁ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ସିଷ୍ଟମ ମଲ୍ଟିଟାସ୍କିଂ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHSରେ ବର୍ତ୍ତମାନର ଆପ ସହ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ପ୍ରବେଶ କରାନ୍ତୁ"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHSରେ ବର୍ତ୍ତମାନର ଆପ ସହ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ପ୍ରବେଶ କରାନ୍ତୁ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ମଲ୍ଟିଟାସ୍କିଂ"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ଡାହାଣରେ ବର୍ତ୍ତମାନର ଆପ ସହିତ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ବାମରେ ବର୍ତ୍ତମାନର ଆପ ସହିତ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନରୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସୁଇଚ କରନ୍ତୁ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବା ସମୟରେ ଡାହାଣପଟର ବା ତଳର ଆପକୁ ସୁଇଚ କରନ୍ତୁ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବା ସମୟରେ ବାମପଟର ବା ଉପରର ଆପକୁ ସୁଇଚ କରନ୍ତୁ"</string> diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml index fd727bfbfe07..fe187c2ff082 100644 --- a/packages/SystemUI/res/values-or/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"ବନ୍ଦ ଅଛି"</item> <item msgid="5137565285664080143">"ଚାଲୁ ଅଛି"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"ଅନୁପଲବ୍ଧ"</item> + <item msgid="3079622119444911877">"ବନ୍ଦ ଅଛି"</item> + <item msgid="3028994095749238254">"ଚାଲୁ ଅଛି"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 40efd0bd716a..3066c1d3e00a 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -328,7 +328,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string> <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ"</string> <string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"ਰੋਕਿਆ ਗਿਆ"</string> - <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ਰਾਤ ਦੀ ਰੋਸ਼ਨੀ"</string> + <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ਨਾਈਟ ਲਾਈਟ"</string> <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string> <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string> <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ਸਮੱਸਿਆ ਰਿਕਾਰਡ ਕਰੋ"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ਸ਼ੁਰੂ ਕਰੋ"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"ਬੰਦ ਕਰੋ"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਿਹੜੀ ਸੁਵਿਧਾ ਪ੍ਰਭਾਵਿਤ ਹੋਈ ਸੀ?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ਸਮੱਸਿਆ ਦੀ ਕਿਸਮ ਚੁਣੋ"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ਮਿਆਰੀ"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ਦਰਮਿਆਨਾ"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ਜ਼ਿਆਦਾ"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"\'ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ\' \'ਤੇ ਕਲਿੱਕ ਕਰੋ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ਕੀ-ਬੋਰਡ ਖਾਕਾ ਬਦਲੋ"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ਜਾਂ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ਖੋਜ ਪੁੱਛਗਿੱਛ ਕਲੀਅਰ ਕਰੋ"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ਸ਼ਾਰਟਕੱਟ"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਖੋਜੋ"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਨਹੀਂ ਮਿਲਿਆ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ਸਿਸਟਮ"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ਖੋਲ੍ਹੋ"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ਲਾਕ ਸਕ੍ਰੀਨ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"ਨੋਟ ਲਿਖੋ"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ਸਿਸਟਮ ਮਲਟੀਟਾਸਕਿੰਗ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHS ਲਈ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHS ਲਈ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ਮਲਟੀਟਾਸਕਿੰਗ"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ਸੱਜੇ ਪਾਸੇ ਦਿੱਤੀ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ਖੱਬੇ ਪਾਸੇ ਦਿੱਤੀ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਤੋਂ ਪੂਰੀ ਸਕ੍ਰੀਨ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਸੱਜੇ ਜਾਂ ਹੇਠਾਂ ਮੌਜੂਦ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਖੱਬੇ ਜਾਂ ਉੱਪਰ ਮੌਜੂਦ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string> diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml index afb1e8bb3695..62dc05ad67bb 100644 --- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"ਬੰਦ"</item> <item msgid="5137565285664080143">"ਚਾਲੂ"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"ਉਪਲਬਧ ਨਹੀਂ"</item> + <item msgid="3079622119444911877">"ਬੰਦ ਹੈ"</item> + <item msgid="3028994095749238254">"ਚਾਲੂ ਹੈ"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 48262a0de391..6ff18b9319ee 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Zarejestruj problem"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Rozpocznij"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zatrzymaj"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Raport o błędzie"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Którego aspektu korzystania z urządzenia dotyczył problem?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Wybierz typ problemu"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Nagrywanie ekranu"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardowy"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Średni"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Wysoki"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Urządzenia słuchowe"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Urządzenia słuchowe"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sparuj nowe urządzenie"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknij, aby sparować nowe urządzenie"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokować mikrofon urządzenia?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokować aparat urządzenia?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokować aparat i mikrofon urządzenia?"</string> @@ -670,15 +667,15 @@ <string name="notification_channel_summary_low" msgid="4860617986908931158">"Bez dźwięku i wibracji"</string> <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Brak dźwięku i wibracji, wyświetlają się niżej w sekcji rozmów"</string> <string name="notification_channel_summary_default" msgid="777294388712200605">"Mogą włączać dzwonek lub wibracje w zależności od ustawień urządzenia"</string> - <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Mogą włączyć dzwonek lub wibracje w zależności od ustawień urządzenia. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string> + <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Mogą włączać dzwonek lub wibracje w zależności od ustawień urządzenia. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string> <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Pozwól systemowi decydować, czy o powiadomieniu powinien informować dźwięk czy wibracja"</string> <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Stan:</b> zmieniony na Domyślny"</string> <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Stan:</b> zmieniono na Ciche"</string> <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Stan:</b> podniesiono ważność"</string> <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Stan:</b> obniżono ważność"</string> - <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady"</string> - <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek"</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, przerywa działanie trybu Nie przeszkadzać"</string> + <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Wyświetlają się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady"</string> + <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Wyświetlają się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek"</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetlają się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, przerywają działanie trybu Nie przeszkadzać"</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string> <string name="notification_priority_title" msgid="2079708866333537093">"Priorytetowe"</string> <string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Przełącz układ klawiatury"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"lub"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Wyczyść wyszukiwanie hasło"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skróty"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Skróty klawiszowe"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Wyszukiwanie skrótów"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nie znaleziono skrótów"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -757,29 +754,29 @@ <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Pokazuję skróty dotyczące danych wejściowych"</string> <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Pokazuję skróty otwierające aplikacje"</string> <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Pokazuję skróty dotyczące bieżącej aplikacji"</string> - <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Wyświetlanie powiadomień"</string> - <string name="group_system_full_screenshot" msgid="5742204844232667785">"Robienie zrzutu ekranu"</string> - <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Pokazywanie skrótów"</string> - <string name="group_system_go_back" msgid="2730322046244918816">"Przechodzenie wstecz"</string> - <string name="group_system_access_home_screen" msgid="4130366993484706483">"Wyświetlanie ekranu głównego"</string> - <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Wyświetlanie ostatnich aplikacji"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Przełączanie się do przodu między ostatnimi aplikacjami"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Przełączanie się wstecz między ostatnimi aplikacjami"</string> - <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otwieranie listy aplikacji"</string> - <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otwieranie ustawień"</string> - <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otwieranie asystenta"</string> - <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokada ekranu"</string> + <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Wyświetl powiadomienia"</string> + <string name="group_system_full_screenshot" msgid="5742204844232667785">"Zapisz zrzut ekranu"</string> + <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Pokaż skróty"</string> + <string name="group_system_go_back" msgid="2730322046244918816">"Przejdź wstecz"</string> + <string name="group_system_access_home_screen" msgid="4130366993484706483">"Wyświetl ekran główny"</string> + <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Wyświetl ostatnie aplikacje"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Przełącz się do przodu między ostatnimi aplikacjami"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Przełącz się wstecz między ostatnimi aplikacjami"</string> + <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otwórz listę aplikacji"</string> + <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otwórz ustawienia"</string> + <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otwórz asystenta"</string> + <string name="group_system_lock_screen" msgid="7391191300363416543">"Zablokuj ekran"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Zanotuj"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Wielozadaniowość w systemie"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Uruchamianie trybu podzielonego ekranu z bieżącą aplikacją po prawej"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Uruchamianie trybu podzielonego ekranu z bieżącą aplikacją po lewej"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Wielozadaniowość"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Podziel ekran z bieżącą aplikacją widoczną po prawej"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Podziel ekran z bieżącą aplikacją widoczną po lewej"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Przełącz podzielony ekran na pełny ekran"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Przełącz się na aplikację po prawej lub poniżej na podzielonym ekranie"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Przełącz się na aplikację po lewej lub powyżej na podzielonym ekranie"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Podczas podzielonego ekranu: zastępowanie aplikacji"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Wprowadzanie"</string> - <string name="input_switch_input_language_next" msgid="3782155659868227855">"Przełączanie na następny język"</string> - <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Przełączanie na poprzedni język"</string> + <string name="input_switch_input_language_next" msgid="3782155659868227855">"Przełącz na następny język"</string> + <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Przełącz na poprzedni język"</string> <string name="input_access_emoji" msgid="8105642858900406351">"Otwieranie emotikonów"</string> <string name="input_access_voice_typing" msgid="7291201476395326141">"Otwieranie pisania głosowego"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacje"</string> diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml index 5d1c02e1bc5f..5aa719f2ea75 100644 --- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Wyłączono"</item> <item msgid="5137565285664080143">"Włączono"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Niedostępne"</item> + <item msgid="3079622119444911877">"Wyłączono"</item> + <item msgid="3028994095749238254">"Włączone"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 04bdf14eac78..4d8156b6fa37 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problema na gravação"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Que parte da sua experiência no dispositivo foi afetada?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecionar tipo de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravação de tela"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Médio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparelhos auditivos"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parear novo dispositivo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Desbloquear a câmera e o microfone do dispositivo?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar a consulta de pesquisa"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atalhos do teclado"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -769,10 +767,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir configurações"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir o Google Assistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Crie uma nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Usar a tela dividida com o app atual à direita"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Usar a tela dividida com o app atual à esquerda"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Criar nota"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefas"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar a tela dividida com o aplicativo atual à direita"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar a tela dividida com o app atual à esquerda"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Mudar da tela dividida para a tela cheia"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mude para o app à direita ou abaixo ao usar a tela dividida"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para o app à esquerda ou acima ao usar a tela dividida"</string> @@ -830,7 +828,7 @@ <string name="left_icon" msgid="5036278531966897006">"Ícone à esquerda"</string> <string name="right_icon" msgid="1103955040645237425">"Ícone à direita"</string> <string name="drag_to_add_tiles" msgid="8933270127508303672">"Mantenha pressionado e arraste para adicionar blocos"</string> - <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste."</string> + <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arraste aqui para remover"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"É preciso haver pelo menos <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> blocos"</string> <string name="qs_edit" msgid="5583565172803472437">"Editar"</string> @@ -1297,7 +1295,7 @@ <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Em uso pela ligação telefônica"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Usado recentemente em uma ligação telefônica"</string> <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Uso recente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml index 453d8139bd48..3526c77d1e24 100644 --- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desativado"</item> <item msgid="5137565285664080143">"Ativado"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Indisponível"</item> + <item msgid="3079622119444911877">"Desativar"</item> + <item msgid="3028994095749238254">"Ativar"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index b6270906eb7f..3c7578f5e756 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Registar problema"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Relatório de erro"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Que parte da experiência do disposit. foi afetada?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecione o tipo de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravação de ecrã"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Médio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sincronizar novo dispositivo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para sincronizar um novo dispositivo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmara do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Quer desbloquear a câmara e o microfone?"</string> @@ -667,7 +665,7 @@ <string name="notification_alert_title" msgid="3656229781017543655">"Predefinição"</string> <string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string> <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sem som ou vibração"</string> - <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sem som ou vibração e aparece na parte inferior na secção de conversas."</string> + <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sem som ou vibração e aparece na parte inferior na secção de conversas"</string> <string name="notification_channel_summary_default" msgid="777294388712200605">"Pode tocar ou vibrar com base nas definições do dispositivo"</string> <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Pode tocar ou vibrar com base nas definições do dispositivo. As conversas da app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem como um balão por predefinição."</string> <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se esta notificação deve emitir um som ou uma vibração"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar esquema de teclado"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar consulta de pesquisa"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atalhos de teclado"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pesquise atalhos"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -768,12 +766,12 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir definições"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Assistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecrã de bloqueio"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Tire uma nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Execução de várias tarefas em simultâneo no sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Aceder ao ecrã dividido com a app atual para RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Aceder ao ecrã dividido com a app atual para LHS"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Tire notas"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Execução de várias tarefas em simultâneo"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use o ecrã dividido com a app atual à direita"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use o ecrã dividido com a app atual à esquerda"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Mudar de ecrã dividido para ecrã inteiro"</string> - <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mude para a app à direita ou abaixo enquanto usa o ecrã dividido"</string> + <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mudar para a app à direita ou abaixo enquanto usa o ecrã dividido"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para a app à esquerda ou acima enquanto usa o ecrã dividido"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Durante o ecrã dividido: substituir uma app por outra"</string> <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string> @@ -798,7 +796,7 @@ <string name="accessibility_long_click_tile" msgid="210472753156768705">"Abrir as definições"</string> <string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Auscultadores ligados"</string> <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Auscultadores com microfone integrado ligados"</string> - <string name="data_saver" msgid="3484013368530820763">"Poup. dados"</string> + <string name="data_saver" msgid="3484013368530820763">"Poupança de dados"</string> <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Poupança de dados ativada"</string> <string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desativado"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 04bdf14eac78..4d8156b6fa37 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problema na gravação"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Que parte da sua experiência no dispositivo foi afetada?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecionar tipo de problema"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravação de tela"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Médio"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparelhos auditivos"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parear novo dispositivo"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Desbloquear a câmera e o microfone do dispositivo?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar a consulta de pesquisa"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atalhos do teclado"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string> @@ -769,10 +767,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir configurações"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir o Google Assistente"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Crie uma nota"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Usar a tela dividida com o app atual à direita"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Usar a tela dividida com o app atual à esquerda"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Criar nota"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefas"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar a tela dividida com o aplicativo atual à direita"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar a tela dividida com o app atual à esquerda"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Mudar da tela dividida para a tela cheia"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mude para o app à direita ou abaixo ao usar a tela dividida"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para o app à esquerda ou acima ao usar a tela dividida"</string> @@ -830,7 +828,7 @@ <string name="left_icon" msgid="5036278531966897006">"Ícone à esquerda"</string> <string name="right_icon" msgid="1103955040645237425">"Ícone à direita"</string> <string name="drag_to_add_tiles" msgid="8933270127508303672">"Mantenha pressionado e arraste para adicionar blocos"</string> - <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste."</string> + <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arraste aqui para remover"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"É preciso haver pelo menos <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> blocos"</string> <string name="qs_edit" msgid="5583565172803472437">"Editar"</string> @@ -1297,7 +1295,7 @@ <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Em uso pela ligação telefônica"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Usado recentemente em uma ligação telefônica"</string> <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Uso recente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml index 453d8139bd48..3526c77d1e24 100644 --- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Desativado"</item> <item msgid="5137565285664080143">"Ativado"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Indisponível"</item> + <item msgid="3079622119444911877">"Desativar"</item> + <item msgid="3028994095749238254">"Ativar"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 7d65f96a493a..172ee12ad9c9 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problemă legată de înregistrare"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Începe"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Oprește"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ce parte a experienței pe dispozitiv a fost afectată?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selectează tipul problemei"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Înregistrarea ecranului"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mediu"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Ridicat"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparate auditive"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparate auditive"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Asociază un nou dispozitiv"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Dă clic pentru a asocia un nou dispozitiv"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblochezi microfonul dispozitivului?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblochezi camera dispozitivului?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblochezi camera și microfonul dispozitivului?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Schimbă aspectul tastaturii"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"sau"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Șterge termenul de căutare"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Comenzi rapide"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Comenzi rapide de la tastatură"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Caută comenzi rapide"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nu există comenzi rapide"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Deschide Asistentul"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecranul de blocare"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Creează o notă"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking pe sistem"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Accesează ecranul împărțit cu aplicația actuală în dreapta"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Accesează ecranul împărțit cu aplicația actuală în stânga"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Folosește ecranul împărțit cu aplicația curentă în dreapta"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Folosește ecranul împărțit cu aplicația curentă în stânga"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Comută de la ecranul împărțit la ecranul complet"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Treci la aplicația din dreapta sau de mai jos cu ecranul împărțit"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Treci la aplicația din stânga sau de mai sus cu ecranul împărțit"</string> diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml index 5b9661884709..a68f1408dd83 100644 --- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Dezactivat"</item> <item msgid="5137565285664080143">"Activat"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Indisponibil"</item> + <item msgid="3079622119444911877">"Dezactivat"</item> + <item msgid="3028994095749238254">"Activat"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 5e47464dc924..249be7fec750 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Запись неисправности"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Начать"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Остановить"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Отчет об ошибке"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"С чем связана проблема, с которой вы столкнулись?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Выберите тип проблемы"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запись экрана"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартная"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Средняя"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Высокая"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слуховые аппараты"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слуховые аппараты"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Подключить новое устройство"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Нажмите, чтобы подключить новое устройство"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблокировать микрофон устройства?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблокировать камеру устройства?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Разблокировать камеру и микрофон устройства?"</string> @@ -678,7 +675,7 @@ <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Статус:</b> уровень важности понижен"</string> <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Появляется в верхней части уведомлений о сообщениях, а также в качестве фото профиля на заблокированном экране"</string> <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране."</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Появляется в верхней части уведомлений о сообщениях, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Появляется в верхней части уведомлений о сообщениях, а также в виде фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string> <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string> <string name="no_shortcut" msgid="8257177117568230126">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает функции разговоров."</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Переключение раскладки"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Удалить поисковый запрос"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Сочетания клавиш"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Быстрые клавиши"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Поиск сочетаний клавиш"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нет сочетаний клавиш."</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Открыть Ассистента"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокировать экран"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Создать заметку"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Режим многозадачности"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Включить разделение экрана с текущим приложением справа"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Включить разделение экрана с текущим приложением слева"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Многозадачность"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Разделить экран и поместить это приложение справа"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Разделить экран и поместить это приложение слева"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Изменить режим разделения экрана на полноэкранный режим"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Перейти к приложению справа или внизу на разделенном экране"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Перейти к приложению слева или вверху на разделенном экране"</string> @@ -783,7 +780,7 @@ <string name="input_access_emoji" msgid="8105642858900406351">"Открыть список эмодзи"</string> <string name="input_access_voice_typing" msgid="7291201476395326141">"Активировать голосовой ввод"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Приложения"</string> - <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Открыть Ассистента"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Ассистент"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Браузер"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакты"</string> <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Эл. почта"</string> @@ -1123,8 +1120,8 @@ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string> <string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string> <string name="basic_status" msgid="2315371112182658176">"Открытый чат"</string> - <string name="select_conversation_title" msgid="6716364118095089519">"Виджеты чатов"</string> - <string name="select_conversation_text" msgid="3376048251434956013">"Нажмите на чат, чтобы добавить его на главный экран"</string> + <string name="select_conversation_title" msgid="6716364118095089519">"Виджеты разговоров"</string> + <string name="select_conversation_text" msgid="3376048251434956013">"Нажмите на разговор, чтобы добавить его на главный экран"</string> <string name="no_conversations_text" msgid="5354115541282395015">"Здесь появятся ваши недавние разговоры."</string> <string name="priority_conversations" msgid="3967482288896653039">"Важные разговоры"</string> <string name="recent_conversations" msgid="8531874684782574622">"Недавние разговоры"</string> @@ -1291,7 +1288,7 @@ <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Развернуть и показать параметры"</string> <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"Свернуть"</string> <string name="privacy_dialog_close_app_button" msgid="8006250171305878606">"Закрыть это приложение"</string> - <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" закрыто."</string> + <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" закрыто"</string> <string name="privacy_dialog_manage_service" msgid="8320590856621823604">"Настроить сервис"</string> <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Настроить доступ"</string> <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Сейчас используется для телефонного звонка"</string> diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml index cdc4a982dff4..592937c7b9f6 100644 --- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Выключено"</item> <item msgid="5137565285664080143">"Включено"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Недоступны"</item> + <item msgid="3079622119444911877">"Отключены"</item> + <item msgid="3028994095749238254">"Включены"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 5eea02c2e702..90c87f06be68 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"පටිගත කිරීමේ ගැටලුව"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"අරඹන්න"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"නවත්වන්න"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ඔබේ උපාංග අත්දැකීමේ කුමන කොටසට බලපෑවේ ද?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ගැටලු වර්ගය තෝරන්න"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"තිර පටිගත කිරීම"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"සම්මත"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"මධ්යම"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"ඉහළ"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ශ්රවණ උපාංග"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ශ්රවණ උපාංග"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"නව උපාංගය යුගල කරන්න"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"නව උපාංගය යුගල කිරීමට ක්ලික් කරන්න"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"උපාංග මයික්රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"උපාංග කැමරාව අවහිර කිරීම ඉවත් කරන්නද?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"උපාංග කැමරාව සහ මයික්රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"යතුරුපුවරු පිරිසැලසුම මාරු කරන්න"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"හෝ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"සෙවීම් විමසුම හිස් කරන්න"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"කෙටිමං"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"යතුරු පුවරු කෙටිමං"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"කෙටිමං සොයන්න"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"කෙටිමං හමු නොවුණි"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"පද්ධතිය"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"සහායක විවෘත කරන්න"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"තිරය අගුළු දමන්න"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"සටහනක් ගන්න"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"පද්ධති බහු කාර්ය"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHS වෙත වත්මන් යෙදුම සමග බෙදුම් තිරයට ඇතුළු වන්න"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHS වෙත වත්මන් යෙදුම සමග බෙදුම් තිරයට ඇතුළු වන්න"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"බහුකාර්ය"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"දකුණේ වත්මන් යෙදුම සමග බෙදීම් තිරය භාවිතා කරන්න"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"වම් පැත්තේ වත්මන් යෙදුම සමග බෙදීම් තිරය භාවිතා කරන්න"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"බෙදුම් තිරයේ සිට පූර්ණ තිරයට මාරු වන්න"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"බෙදුම් තිරය භාවිත කරන අතරතුර දකුණේ හෝ පහළින් ඇති යෙදුමට මාරු වන්න"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"බෙදුම් තිරය භාවිත කරන අතරතුර වමේ හෝ ඉහළ ඇති යෙදුමට මාරු වන්න"</string> diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml index e7e90341ecb9..681f3d52bc09 100644 --- a/packages/SystemUI/res/values-si/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"ක්රියාවිරහිතයි"</item> <item msgid="5137565285664080143">"ක්රියාත්මකයි"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"නොමැත"</item> + <item msgid="3079622119444911877">"ක්රියාවිරහිතයි"</item> + <item msgid="3028994095749238254">"ක්රියාත්මකයි"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index ea1a8f860a1e..7751c6d09d34 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Problém s nahrávaním"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Začnite"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zastavte"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Hlásenie chyby"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Čo v zariadení bolo ovplyvnené?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Vyberte typ problému"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rekordér obrazovky"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Stredný"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Vysoký"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Načúvacie zariadenia"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Načúvacie zariadenia"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Párovanie nového zariadenia"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zariadenie"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Chcete odblokovať mikrofón zariadenia?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Chcete odblokovať kameru zariadenia?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Chcete odblokovať fotoaparát a mikrofón zariadenia?"</string> @@ -679,7 +677,7 @@ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Zobrazuje sa ako bublina v hornej časti upozornení konverzácie a profilová fotka na uzamknutej obrazovke"</string> <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Zobrazuje sa v hornej časti upozornení konverzácie a ako profilová fotka na uzamknutej obrazovke, preruší režim bez vyrušení"</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje sa ako bublina v hornej časti upozornení konverzácie a profilová fotka na uzamknutej obrazovke, preruší režim bez vyrušení"</string> - <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string> + <string name="notification_priority_title" msgid="2079708866333537093">"Prioritné"</string> <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje funkcie konverzácie"</string> <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tieto upozornenia sa nedajú upraviť."</string> <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornenia na hovory sa nedajú upraviť."</string> @@ -744,12 +742,12 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Prepnúť rozloženie klávesnice"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"alebo"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Vymazať vyhľadávací dopyt"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skratky"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klávesové skratky"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hľadajte skratky"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenašli sa žiadne skratky"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systém"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vstup"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorenie apl."</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorené aplikácie"</string> <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuálna aplik."</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Zobrazujú sa výsledky vyhľadávania"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Zobrazujú sa skratky systému"</string> @@ -767,11 +765,11 @@ <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvorenie zoznamu aplikácií"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvorenie nastavení"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvorenie Asistenta"</string> - <string name="group_system_lock_screen" msgid="7391191300363416543">"Zamknúť obrazovku"</string> + <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknutie obrazovky"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Napísanie poznámky"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking systému"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Rozdelenie obrazovky s aktuálnou aplikáciou vpravo"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Rozdelenie obrazovky s aktuálnou aplikáciou vľavo"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Použite rozdelenú obrazovku s aktuálnou aplikáciou vpravo"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Použite rozdelenú obrazovku s aktuálnou aplikáciou vľavo"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prepnutie rozdelenej obrazovky na celú"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prechod na aplikáciu vpravo alebo dole pri rozdelenej obrazovke"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prechod na aplikáciu vľavo alebo hore pri rozdelenej obrazovke"</string> @@ -1268,7 +1266,7 @@ <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Inštalovať pracovnú telefónnu aplikáciu"</string> <string name="call_from_work_profile_close" msgid="5830072964434474143">"Zrušiť"</string> <string name="lock_screen_settings" msgid="6152703934761402399">"Prispôsobiť uzamknutú obrazovku"</string> - <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ak chcete prispôsobiť uzamknutú obrazovku, odomknite ju"</string> + <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Uzamknutú obrazovku môžete prispôsobiť po odomknutí"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi‑Fi nie je k dispozícii"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokovaná"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofón sú blokované"</string> @@ -1284,7 +1282,7 @@ <string name="dismiss_dialog" msgid="2195508495854675882">"Zavrieť"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"Obrazovka je pripojená"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofón a fotoaparát"</string> - <string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedávne využitie aplikácie"</string> + <string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedávne použitie aplikáciami"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Zobraziť nedávny prístup"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Hotovo"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Rozbaliť a zobraziť možnosti"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 514d2f9d42d1..53be1bde3369 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Snemanje težave"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Začetek"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ustavitev"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Poročilo o napakah"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Na kateri del izkušnje z napravo je to vplivalo?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Izberite vrsto težave"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snemanje zaslona"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardni"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednji"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visok"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni pripomočki"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni pripomočki"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Seznanitev nove naprave"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite za seznanitev nove naprave"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite odblokirati mikrofon v napravi?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite odblokirati fotoaparat v napravi?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite odblokirati fotoaparat in mikrofon v napravi?"</string> @@ -745,12 +742,12 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Preklop postavitve tipkovnice"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ali"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Čiščenje iskalne poizvedbe"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Bližnjice"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Bližnjične tipke"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Iskanje bližnjic"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ni najdenih bližnjic."</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vnos"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Odprte aplikacije"</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Odpiranje aplikacij"</string> <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutna aplikacija"</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Prikaz rezultatov iskanja"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Prikaz sistemskih bližnjic"</string> @@ -770,14 +767,14 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Odpiranje Pomočnika"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaklepanje zaslona"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Ustvarjanje zapiska"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistemska večopravilnost"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Vklop razdeljenega zaslona s trenutno aplikacijo na desni"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Vklop razdeljenega zaslona s trenutno aplikacijo na levi"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Večopravilnost"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Uporaba razdeljenega zaslona s trenutno aplikacijo na desni"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Uporaba razdeljenega zaslona s trenutno aplikacijo na levi"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Preklop iz razdeljenega zaslona v celozaslonski način"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Preklop na aplikacijo desno ali spodaj med uporabo razdeljenega zaslona"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Preklop na aplikacijo levo ali zgoraj med uporabo razdeljenega zaslona"</string> <string name="system_multitasking_replace" msgid="7410071959803642125">"Pri razdeljenem zaslonu: medsebojna zamenjava aplikacij"</string> - <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vnosna naprava"</string> + <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vnos"</string> <string name="input_switch_input_language_next" msgid="3782155659868227855">"Preklop na naslednji jezik"</string> <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Preklop na prejšnji jezik"</string> <string name="input_access_emoji" msgid="8105642858900406351">"Dostop do emodžijev"</string> diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml index 9f9175e7bd0e..5f60ffdaebf7 100644 --- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Izklopljeno"</item> <item msgid="5137565285664080143">"Vklopljeno"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Ni na voljo"</item> + <item msgid="3079622119444911877">"Izklopljeno"</item> + <item msgid="3028994095749238254">"Vklopljeno"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index c13d76b974b7..7e75984a4c35 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Regjistro problemin"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Nis"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ndalo"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cila pjesë e përvojës me pajisjen është prekur?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Zgjidh llojin e problemit"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Regjistrim i ekranit"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mesatar"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"I lartë"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Pajisje ndihmëse për dëgjimin"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Pajisjet e dëgjimit"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Çifto pajisje të re"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliko për të çiftuar një pajisje të re"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Të zhbllokohet mikrofoni i pajisjes?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Të zhbllokohet kamera e pajisjes?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Të zhbllokohen kamera dhe mikrofoni i pajisjes?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ndërro strukturën e tastierës"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ose"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Pastro pyetjen e kërkimit"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shkurtoret"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Shkurtoret e tastierës"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kërko shkurtoret"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nuk u gjet shkurtore"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistemi"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Hap \"Asistentin\""</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekrani i kyçjes"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Mbaj një shënim"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Kryerja e shumë detyrave nga sistemi"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Hyr në ekranin e ndarë me aplikacionin aktual në anën e djathtë"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Hyr në ekranin e ndarë me aplikacionin aktual në anën e majtë"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Kryerja e shumë detyrave"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Përdor ekranin e ndarë me aplikacionin aktual në të djathtë"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Përdor ekranin e ndarë me aplikacionin aktual në të majtë"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Kalo nga ekrani i ndarë në ekranin e plotë"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Kalo tek aplikacioni djathtas ose poshtë kur përdor ekranin e ndarë"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Kalo tek aplikacioni në të majtë ose sipër kur përdor ekranin e ndarë"</string> diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml index aa4832d62b43..9b5032eecbd8 100644 --- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Joaktive"</item> <item msgid="5137565285664080143">"Aktive"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Nuk ofrohen"</item> + <item msgid="3079622119444911877">"Joaktive"</item> + <item msgid="3028994095749238254">"Aktive"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index bc6642af913a..2b1882dbcf64 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Евидентирајте проблем"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Покрени"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Заустави"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Извештај о грешци"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"На који део доживљаја на уређају је ово утицало?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Изаберите тип проблема"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Снимање екрана"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Средње"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Високо"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Упари нови уређај"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликните да бисте упарили нов уређај"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Желите да одблокирате микрофон уређаја?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Желите да одблокирате камеру уређаја?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Желите да одблокирате камеру и микрофон уређаја?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени распоред тастатуре"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Обриши упит за претрагу"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Пречице"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Тастерске пречице"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Претражите пречице"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нису пронађене пречице"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Систем"</string> @@ -768,10 +766,10 @@ <string name="group_system_access_system_settings" msgid="8731721963449070017">"Отвори подешавања"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отвори помоћника"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Закључавање екрана"</string> - <string name="group_system_quick_memo" msgid="3764560265935722903">"Направите белешку"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Обављање више задатака система истовремено"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Покрени подељени екран за актуелну апликацију на десној страни"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Покрени подељени екран за актуелну апликацију на левој страни"</string> + <string name="group_system_quick_memo" msgid="3764560265935722903">"Направи белешку"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Обављање више задатака истовремено"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Користите подељени екран са актуелном апликацијом с десне стране"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Користите подељени екран са актуелном апликацијом с леве стране"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Пређи са подељеног екрана на цео екран"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Пређите у апликацију здесна или испод док користите подељени екран"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Пређите у апликацију слева или изнад док користите подељени екран"</string> @@ -1295,9 +1293,9 @@ <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Управљај приступом"</string> <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Користи телефонски позив"</string> <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Недавно коришћено у телефонском позиву"</string> - <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> + <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string> <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 15c370c6b73e..f075c8c94cb7 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Registrera problem"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Starta"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stoppa"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Vilken enhetsupplevelse påverkades?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Välj problemtyp"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skärminspelning"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medelhög"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hög"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörhjälpmedel"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hörhjälpmedel"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parkoppla en ny enhet"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicka för att parkoppla en ny enhet"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vill du återaktivera enhetens mikrofon?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vill du återaktivera enhetens kamera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vill du återaktivera enhetens kamera och mikrofon?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Byt tangentbordslayout"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Rensa sökfråga"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortkommandon"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Kortkommandon"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sök efter kortkommando"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Inga resultat"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Öppna assistenten"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skärmen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Anteckna"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systemets multikörning"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Öppna delad skärm med aktuell app till höger"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Öppna delad skärm med aktuell app till vänster"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multikörning"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Anänd delad skärm med den aktuella appen till höger"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Använd delad skärm med den aktuella appen till vänster"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Byt mellan delad skärm och helskärm"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Byt till appen till vänster eller nedanför när du använder delad skärm"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Byt till appen till vänster eller ovanför när du använder delad skärm"</string> diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml index 522538a79c07..cf49f8db2606 100644 --- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Av"</item> <item msgid="5137565285664080143">"På"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Inte tillgänglig"</item> + <item msgid="3079622119444911877">"Av"</item> + <item msgid="3028994095749238254">"På"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 41bac7b4fbb7..102926b0246c 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Hitilafu ya Kurekodi"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Anza"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Simamisha"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Ripoti ya Hitilafu"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ni sehemu gani ya matumizi ya kifaa iliathiriwa?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Chagua aina ya tatizo"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rekodi ya skrini"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Wastani"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Juu"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Vifaa vya kusikilizia"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Vifaa vya kusikilizia"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Unganisha kifaa kipya"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Bofya ili uunganishe kifaa kipya"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Ungependa kuwacha kuzuia maikrofoni ya kifaa?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Ungependa kuacha kuzuia kamera ya kifaa?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Ungependa kuwacha kuzuia kamera na maikrofoni ya kifaa?"</string> @@ -636,7 +634,7 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string> - <string name="qr_code_scanner_title" msgid="1938155688725760702">"Kichanganuzi cha msimbo wa QR"</string> + <string name="qr_code_scanner_title" msgid="1938155688725760702">"Kichanganuzi cha QR"</string> <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Inasasisha"</string> <string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string> @@ -719,7 +717,7 @@ <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string> - <string name="keyboard_key_backspace" msgid="4095278312039628074">"Nafasinyuma"</string> + <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string> <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Cheza/Sitisha"</string> <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Simamisha"</string> <string name="keyboard_key_media_next" msgid="8502476691227914952">"Inayofuata"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Badili mkao wa kibodi"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"au"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Futa hoja ya utafutaji"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Njia za mkato"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Mikato ya Kibodi"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tafuta njia za mkato"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Hakuna njia za mkato zilizopatikana"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Mfumo"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Fungua programu ya Mratibu wa Google"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Funga skrini"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Andika dokezo"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Majukumu mengi ya mfumo"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Tumia programu kwenye skrini iliyogawanywa upande wa kulia"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Tumia programu kwenye skrini iliyogawanywa upande wa kushoto"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Majukumu mengi"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Tumia hali ya kugawa skrini na programu ya sasa iwe upande wa kulia"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Tumia hali ya kugawa skrini na programu ya sasa iwe upande wa kushoto"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Badilisha kutoka skrini iliyogawanywa utumie skrini nzima"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Badilisha ili uende kwenye programu iliyo kulia au chini unapotumia hali ya kugawa skrini"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Badilisha uende kwenye programu iliyo kushoto au juu unapotumia hali ya kugawa skrini"</string> @@ -1261,7 +1259,7 @@ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Chaji ya betri imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Unganisha stylus yako kwenye chaja"</string> <string name="stylus_battery_low" msgid="7134370101603167096">"Chaji ya betri ya Stylus imepungua"</string> - <string name="video_camera" msgid="7654002575156149298">"Kamera ya kuchukulia video"</string> + <string name="video_camera" msgid="7654002575156149298">"Kamera ya video"</string> <string name="call_from_work_profile_title" msgid="5418253516453177114">"Huwezi kupiga simu kwa kutumia programu ya binafsi"</string> <string name="call_from_work_profile_text" msgid="2856337395968118274">"Shirika lako linakuruhusu upige simu ukitumia programu za kazini pekee"</string> <string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 019dddcda6e4..9afa0d1db9eb 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"சிக்கலை ரெக்கார்டு செய்தல்"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"தொடங்குங்கள்"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"நிறுத்துங்கள்"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"சாதன அனுபவத்தின் எந்தப் பகுதி பாதிக்கப்பட்டது?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"சிக்கல் வகையைத் தேர்வுசெய்க"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ஸ்கிரீன் ரெக்கார்டு"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"இயல்புநிலை"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"நடுத்தரம்"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"அதிகம்"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"செவித்துணைக் கருவிகள்"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"செவித்துணைக் கருவிகள்"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"புதிய சாதனத்தை இணை"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"புதிய சாதனத்தை இணைக்க கிளிக் செய்யலாம்"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"சாதனத்தின் மைக்ரோஃபோனுக்கான தடுப்பை நீக்கவா?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"சாதனத்தின் கேமராவுக்கான தடுப்பை நீக்கவா?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"சாதனத்தின் கேமராவுக்கும் மைக்ரோஃபோனுக்குமான தடுப்பை நீக்கவா?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"கீபோர்டு லே அவுட்டை மாற்று"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"அல்லது"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"தேடல் வினவலை அழிக்கும்"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ஷார்ட்கட்கள்"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"கீபோர்டு ஷார்ட்கட்கள்"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ஷார்ட்கட்களைத் தேடுக"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ஷார்ட்கட்கள் எதுவுமில்லை"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"சிஸ்டம்"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistantடைத் திறத்தல்"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"பூட்டுத் திரை"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"குறிப்பெடுத்தல்"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"சிஸ்டம் பல வேலைகளைச் செய்தல்"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"வலதுபுறத்தில் தற்போதைய ஆப்ஸ் தோன்றுமாறு திரைப் பிரிப்பை அமைத்தல்"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"இடதுபுறத்தில் தற்போதைய ஆப்ஸ் தோன்றுமாறு திரைப் பிரிப்பை அமைத்தல்"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"பல வேலைகளைச் செய்தல்"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"தற்போது உள்ள ஆப்ஸுடன் வலதுபுறத்தில் திரைப் பிரிப்பைப் பயன்படுத்துதல்"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"தற்போது உள்ள ஆப்ஸுடன் இடதுபுறத்தில் திரைப் பிரிப்பைப் பயன்படுத்துதல்"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"திரைப் பிரிப்பு பயன்முறையிலிருந்து முழுத்திரைக்கு மாற்றுதல்"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது வலது/கீழ் உள்ள ஆப்ஸுக்கு மாறுங்கள்"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது இடது/மேலே உள்ள ஆப்ஸுக்கு மாறுங்கள்"</string> diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml index cacde5ebe57b..a3b9538f891c 100644 --- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"முடக்கப்பட்டுள்ளது"</item> <item msgid="5137565285664080143">"இயக்கப்பட்டுள்ளது"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"கிடைக்கவில்லை"</item> + <item msgid="3079622119444911877">"முடக்கப்பட்டுள்ளது"</item> + <item msgid="3028994095749238254">"இயக்கப்பட்டுள்ளது"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 1b3c5e2e339c..7f82ebf46a71 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -118,7 +118,7 @@ <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"స్క్రీన్, ఆడియో రికార్డింగ్ చేయబడుతున్నాయి"</string> <string name="screenrecord_taps_label" msgid="1595690528298857649">"స్క్రీన్పై తాకే స్థానాలను చూపండి"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయి"</string> - <string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయి"</string> + <string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయండి"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"స్క్రీన్ రికార్డింగ్ సేవ్ చేయబడింది"</string> <string name="screenrecord_save_text" msgid="3008973099800840163">"చూడటానికి ట్యాప్ చేయండి"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"స్క్రీన్ రికార్డింగ్ను సేవ్ చేయడంలో ఎర్రర్ ఏర్పడింది"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"సమస్యను రికార్డ్ చేయడం"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"ప్రారంభించండి"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"ఆపివేయండి"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"బగ్ రిపోర్ట్"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"మీ పరికర అనుభవంలో ఏ భాగం ప్రభావితమైంది?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"సమస్య రకాన్ని ఎంచుకోండి"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"స్క్రీన్ రికార్డ్"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"స్టాండర్డ్"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"మధ్యస్థం"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"అధికం"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"వినికిడి పరికరాలు"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"వినికిడి పరికరం"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"కొత్త పరికరాన్ని పెయిర్ చేయడానికి క్లిక్ చేయండి"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయమంటారా?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"పరికరంలోని కెమెరాను అన్బ్లాక్ చేయమంటారా?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"పరికరంలోని కెమెరా, మైక్రోఫోన్లను అన్బ్లాక్ చేయమంటారా?"</string> @@ -678,7 +675,7 @@ <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>స్టేటస్:</b> తక్కువ ర్యాంక్కు సర్దుబాటు చేయబడింది"</string> <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"సంభాషణ నోటిఫికేషన్ల ఎగువున, లాక్ స్క్రీన్లో ప్రొఫైల్ ఫోటోగా చూపిస్తుంది"</string> <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"సంభాషణ నోటిఫికేషన్ల ఎగువున, లాక్ స్క్రీన్లో ప్రొఫైల్ ఫోటోగా చూపిస్తుంది, బబుల్గా కనిపిస్తుంది"</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"సంభాషణ నోటిఫికేషన్ల ఎగువున, లాక్ స్క్రీన్లో ప్రొఫైల్ ఫోటోగా చూపిస్తుంది, \'అంతరాయం కలిగించవద్దు\'ను అంతరాయం కలిగిస్తుంది"</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"సంభాషణ నోటిఫికేషన్ల ఎగువున, అలాగే లాక్ స్క్రీన్లో ప్రొఫైల్ ఫోటో రూపంలో కనబడుతుంది. \'అంతరాయం కలిగించవద్దు\' మోడ్లో ఉన్నా దాన్ని అధిగమిస్తుంది"</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"సంభాషణ నోటిఫికేషన్ల ఎగువున, లాక్ స్క్రీన్లో ప్రొఫైల్ ఫోటోగా చూపిస్తుంది, బబుల్గా కనిపిస్తుంది, \'అంతరాయం కలిగించవద్దు\'ను అంతరాయం కలిగిస్తుంది"</string> <string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string> <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> సంభాషణ ఫీచర్లను సపోర్ట్ చేయదు"</string> @@ -718,7 +715,7 @@ <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"కుడి వైపు బాణం"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"మధ్య"</string> <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> - <string name="keyboard_key_space" msgid="6980847564173394012">"అంతరం"</string> + <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string> <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"ప్లే చేయి/పాజ్ చేయి"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"కీబోర్డ్ లేఅవుట్ను మార్చండి"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"లేదా"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"సెర్చ్ క్వెరీని క్లియర్ చేయండి"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"షార్ట్కట్లు"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"కీబోర్డ్ షార్ట్కట్లు"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"షార్ట్కట్స్ సెర్చ్ చేయండి"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"షార్ట్కట్లు ఏవీ లేవు"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"సిస్టమ్"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"అసిస్టెంట్ను తెరవండి"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"లాక్ స్క్రీన్"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"గమనికను రాయండి"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"సిస్టమ్ మల్టీ-టాస్కింగ్"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHSకు ప్రస్తుత యాప్తో స్ప్లిట్ స్క్రీన్ను ఎంటర్ చేయండి"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHSకు ప్రస్తుత యాప్తో స్ప్లిట్ స్క్రీన్ను ఎంటర్ చేయండి"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"మల్టీ-టాస్కింగ్"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"కుడివైపు ప్రస్తుత యాప్తో స్ప్లిట్ స్క్రీన్ను ఉపయోగించండి"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ఎడమవైపు ప్రస్తుత యాప్తో స్ప్లిట్ స్క్రీన్ను ఉపయోగించండి"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"స్ప్లిట్ స్క్రీన్ను ఫుల్ స్క్రీన్కు మార్చండి"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"స్ప్లిట్ స్క్రీన్ ఉపయోగిస్తున్నప్పుడు కుడి లేదా పైన యాప్నకు మారండి"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"స్ప్లిట్ స్క్రీన్ ఉపయోగిస్తున్నప్పుడు ఎడమ లేదా పైన యాప్నకు మారండి"</string> @@ -802,7 +799,7 @@ <string name="data_saver" msgid="3484013368530820763">"డేటా సేవర్"</string> <string name="accessibility_data_saver_on" msgid="5394743820189757731">"డేటా సేవర్ ఆన్లో ఉంది"</string> <string name="switch_bar_on" msgid="1770868129120096114">"ఆన్"</string> - <string name="switch_bar_off" msgid="5669805115416379556">"ఆఫ్ చేయి"</string> + <string name="switch_bar_off" msgid="5669805115416379556">"ఆఫ్"</string> <string name="tile_unavailable" msgid="3095879009136616920">"అందుబాటులో లేదు"</string> <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"మరింత తెలుసుకోండి"</string> <string name="nav_bar" msgid="4642708685386136807">"నావిగేషన్ బార్"</string> @@ -1066,7 +1063,7 @@ <string name="controls_media_button_next" msgid="6662636627525947610">"తర్వాతి ట్రాక్"</string> <string name="controls_media_button_connecting" msgid="3138354625847598095">"కనెక్ట్ అవుతోంది"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ప్లే చేయండి"</string> - <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>ను తెరవండి"</string> + <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"\'<xliff:g id="APP_LABEL">%1$s</xliff:g>\'ను తెరవండి"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి <xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g>ను ప్లే చేయండి"</string> <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> నుండి <xliff:g id="SONG_NAME">%1$s</xliff:g>ను ప్లే చేయండి"</string> <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"మీ కోసం"</string> @@ -1194,7 +1191,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# యాప్ యాక్టివ్గా ఉంది}other{# యాప్లు యాక్టివ్గా ఉన్నాయి}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"కొత్త సమాచారం"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"యాక్టివ్గా ఉన్న యాప్లు"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"మీరు ఈ యాప్లను ఉపయోగించపోయినా కూడా అవి యాక్టివ్గా ఉండి, రన్ అవుతూ ఉంటాయి. దీని వల్ల వాటి ఫంక్షనాలిటీ మెరుగవుతుంది. అయితే ఇది బ్యాటరీ లైఫ్ను కూడా ప్రభావితం చేయవచ్చు."</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"మీరు ఈ యాప్లను ఉపయోగించపోయినా కూడా అవి యాక్టివ్గా ఉండి, రన్ అవుతూ ఉంటాయి. తద్వారా వాటి ఫంక్షనాలిటీ మెరుగవుతుంది. అయితే దీనివల్ల బ్యాటరీ లైఫ్ ప్రభావితం అయ్యే అవకాశం ఉంది."</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"ఆపివేయండి"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"ఆపివేయబడింది"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"పూర్తయింది"</string> @@ -1240,7 +1237,7 @@ <string name="log_access_confirmation_body" msgid="6883031912003112634">"మీ పరికరంలో జరిగే దాన్ని పరికర లాగ్లు రికార్డ్ చేస్తాయి. సమస్యలను కనుగొని, పరిష్కరించడానికి యాప్లు ఈ లాగ్లను ఉపయోగిస్తాయి.\n\nకొన్ని లాగ్లలో గోప్యమైన సమాచారం ఉండవచ్చు, కాబట్టి మీరు విశ్వసించే యాప్లను మాత్రమే అన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి అనుమతించండి. \n\nఅన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి మీరు ఈ యాప్ను అనుమతించకపోతే, అది తన స్వంత లాగ్లను ఇప్పటికి యాక్సెస్ చేయగలదు. మీ పరికర తయారీదారు ఇప్పటికీ మీ పరికరంలో కొన్ని లాగ్లు లేదా సమాచారాన్ని యాక్సెస్ చేయగలరు."</string> <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"మరింత తెలుసుకోండి"</string> <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>లో మరింత తెలుసుకోండి"</string> - <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>ను తెరవండి"</string> + <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"\'<xliff:g id="APPNAME">%1$s</xliff:g>\'ను తెరవండి"</string> <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet యాప్ను షార్ట్కట్గా జోడించడానికి, యాప్ ఇన్స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string> <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet యాప్ను షార్ట్కట్గా జోడించడానికి, కనీసం ఒక కార్డ్ జోడించబడిందని నిర్ధారించుకోండి"</string> <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home యాప్ను షార్ట్కట్గా జోడించడానికి, యాప్ ఇన్స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string> diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml index a1ee29f5f724..6584cdd59282 100644 --- a/packages/SystemUI/res/values-te/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"ఆఫ్లో ఉంది"</item> <item msgid="5137565285664080143">"ఆన్లో ఉంది"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"అందుబాటులో లేదు"</item> + <item msgid="3079622119444911877">"ఆఫ్లో ఉంది"</item> + <item msgid="3028994095749238254">"ఆన్లో ఉంది"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index e8d376dba34c..dece9c1ffeb5 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -119,7 +119,7 @@ <string name="screenrecord_taps_label" msgid="1595690528298857649">"แสดงการแตะบนหน้าจอ"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"หยุด"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"แชร์"</string> - <string name="screenrecord_save_title" msgid="1886652605520893850">"บันทึกการบันทึกหน้าจอแล้ว"</string> + <string name="screenrecord_save_title" msgid="1886652605520893850">"จัดเก็บการบันทึกหน้าจอไว้แล้ว"</string> <string name="screenrecord_save_text" msgid="3008973099800840163">"แตะเพื่อดู"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"เกิดข้อผิดพลาดในการบันทึกหน้าจอ"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"เกิดข้อผิดพลาดขณะเริ่มบันทึกหน้าจอ"</string> @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"ปัญหาการบันทึก"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"เริ่ม"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"หยุด"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"รายงานข้อบกพร่อง"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ประสบการณ์การใช้งานอุปกรณ์ส่วนใดที่ได้รับผลกระทบ"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"เลือกประเภทปัญหา"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"บันทึกหน้าจอ"</string> @@ -363,14 +364,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"มาตรฐาน"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ปานกลาง"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"สูง"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"เครื่องช่วยฟัง"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"เครื่องช่วยฟัง"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"จับคู่อุปกรณ์ใหม่"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"คลิกเพื่อจับคู่อุปกรณ์ใหม่"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"เลิกบล็อกไมโครโฟนของอุปกรณ์ใช่ไหม"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"เลิกบล็อกกล้องของอุปกรณ์ใช่ไหม"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"เลิกบล็อกกล้องและไมโครโฟนของอุปกรณ์ใช่ไหม"</string> @@ -745,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"สลับรูปแบบแป้นพิมพ์"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"หรือ"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ล้างคำค้นหา"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"แป้นพิมพ์ลัด"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"แป้นพิมพ์ลัด"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ค้นหาแป้นพิมพ์ลัด"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ไม่พบแป้นพิมพ์ลัด"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ระบบ"</string> @@ -770,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"เปิด Assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"ล็อกหน้าจอ"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"จดโน้ต"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"การทํางานหลายอย่างพร้อมกันของระบบ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"เข้าสู่โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านขวา"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"เข้าสู่โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านซ้าย"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"การทํางานหลายอย่างพร้อมกัน"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"ใช้โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านขวา"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"ใช้โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านซ้าย"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"เปลี่ยนจากโหมดแยกหน้าจอเป็นเต็มหน้าจอ"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"เปลี่ยนไปใช้แอปทางด้านขวาหรือด้านล่างขณะใช้โหมดแยกหน้าจอ"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"เปลี่ยนไปใช้แอปทางด้านซ้ายหรือด้านบนขณะใช้โหมดแยกหน้าจอ"</string> @@ -1194,7 +1191,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{ทำงานอยู่ # แอป}other{ทำงานอยู่ # แอป}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"ข้อมูลใหม่"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"แอปที่ทำงานอยู่"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"แอปเหล่านี้กำลังทำงานแม้ว่าคุณจะไม่ได้ใช้งานอยู่ก็ตาม วิธีนี้ช่วยให้ฟังก์ชันการทำงานของแอปมีประสิทธิภาพมากขึ้น แต่ก็อาจส่งผลต่ออายุการใช้งานแบตเตอรี่ด้วย"</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"แอปเหล่านี้กำลังทำงานแม้ว่าคุณจะไม่ได้ใช้งานอยู่ก็ตาม วิธีนี้ช่วยให้ฟังก์ชันการทำงานของแอปมีประสิทธิภาพมากขึ้น แต่ก็อาจส่งผลต่อระยะเวลาการใช้งานแบตเตอรี่ด้วย"</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"หยุด"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"หยุดแล้ว"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"เสร็จ"</string> diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml index d6351ce7df4d..8b7187b66baa 100644 --- a/packages/SystemUI/res/values-th/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"ปิด"</item> <item msgid="5137565285664080143">"เปิด"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"ไม่พร้อมใช้งาน"</item> + <item msgid="3079622119444911877">"ปิด"</item> + <item msgid="3028994095749238254">"เปิด"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 54bb74b85cba..9f408f4168e8 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Mag-record ng Isyu"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Magsimula"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ihinto"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Ulat ng Bug"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ano\'ng naapektuhang parte ng experience sa device?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Piliin ang uri ng isyu"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Pag-record ng screen"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Katamtaman"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Mataas"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Mga hearing device"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Mga hearing device"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Magpares ng bagong device"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"I-click para magpares ng bagong device"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"I-unblock ang mikropono ng device?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"I-unblock ang camera ng device?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"I-unblock ang camera at mikropono ng device?"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Magpalit ng layout ng keyboard"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"I-clear ang query sa paghahanap"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Mga Shortcut"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Mga Keyboard Shortcut"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Maghanap ng mga shortcut"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Walang nakitang shortcut"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Buksan ang assistant"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"I-lock ang screen"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Magtala"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking ng system"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Lumipat sa split screen nang nasa RHS ang kasalukuyang app"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Lumipat sa split screen nang nasa LHS ang kasalukuyang app"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Pag-multitask"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gumamit ng split screen nang nasa kanan ang kasalukuyang app"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gumamit ng split screen nang nasa kaliwa ang kasalukuyang app"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Lumipat sa full screen mula sa split screen"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Lumipat sa app sa kanan o ibaba habang ginagamit ang split screen"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Lumipat sa app sa kaliwa o itaas habang ginagamit ang split screen"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 5364c83d0694..c07c35037642 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Sorunu Kaydedin"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Başlayın"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Durdurun"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cihaz deneyiminiz ne şekilde etkilendi?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Sorun türünü seçin"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekran kaydedicisi"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Orta"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Yüksek"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"İşitme cihazları"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"İşitme cihazları"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yeni cihaz eşle"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz eşlemek için tıklayın"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonunun engellemesi kaldırılsın mı?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerasının engellemesi kaldırılsın mı?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası ile mikrofonunun engellemesi kaldırılsın mı?"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klavye düzenini değiştir"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"veya"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Arama sorgusunu temizle"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kısayollar"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klavye Kısayolları"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kısayol araması yapın"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Kısayol bulunamadı"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Asistan\'ı aç"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilit ekranı"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Not al"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistem çoklu görevi"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Mevcut uygulamayı sağ tarafa alarak bölünmüş ekrana geç"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Mevcut uygulamayı sol tarafa alarak bölünmüş ekrana geç"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Çoklu görev"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Sağdaki mevcut uygulamayla birlikte bölünmüş ekranı kullanın"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Soldaki mevcut uygulamayla birlikte bölünmüş ekranı kullanın"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Bölünmüş ekrandan tam ekrana geç"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bölünmüş ekran kullanırken sağdaki veya alttaki uygulamaya geçiş yapın"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bölünmüş ekran kullanırken soldaki veya üstteki uygulamaya geçiş yapın"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index da1dfa4af50d..65630348c22c 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Запис помилки"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Почати"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Зупинити"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"На який аспект роботи пристрою вплинула проблема?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Виберіть тип проблеми"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запис відео з екрана"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартний"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Середній"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Високий"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухові апарати"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слухові апарати"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Підключити новий пристрій"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Натисніть, щоб підключити новий пристрій"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Надати доступ до мікрофона?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Надати доступ до камери пристрою?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Надати доступ до камери й мікрофона?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Змінити розкладку клавіатури"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"або"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Очистити пошуковий запит"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Швидкі команди"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Комбінації клавіш"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пошук швидких команд"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Швидк. команд не знайдено"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Відкрити додаток Асистент"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокувати екран"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Створити нотатку"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Багатозадачність системи"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Розділити екран із поточним додатком праворуч"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Розділити екран із поточним додатком ліворуч"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Багатозадачність"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Розділити екран і показувати поточний додаток праворуч"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Розділити екран і показувати поточний додаток ліворуч"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Перейти з розділення екрана на весь екран"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Під час розділення екрана перемикатися на додаток праворуч або внизу"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Під час розділення екрана перемикатися на додаток ліворуч або вгорі"</string> @@ -784,7 +782,7 @@ <string name="input_access_voice_typing" msgid="7291201476395326141">"Відкрити голосовий ввід"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Додатки"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Асистент"</string> - <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Веб-переглядач"</string> + <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Вебпереглядач"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакти"</string> <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Електронна пошта"</string> <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string> @@ -903,7 +901,7 @@ <string name="instant_apps_message" msgid="6112428971833011754">"Додаток відкрито без встановлення."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Додаток відкрито без встановлення. Торкніться, щоб дізнатися більше."</string> <string name="app_info" msgid="5153758994129963243">"Про додаток"</string> - <string name="go_to_web" msgid="636673528981366511">"Веб-переглядач"</string> + <string name="go_to_web" msgid="636673528981366511">"Вебпереглядач"</string> <string name="mobile_data" msgid="4564407557775397216">"Мобільний трафік"</string> <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml index be779eb51330..61e62e4395ce 100644 --- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"Вимкнено"</item> <item msgid="5137565285664080143">"Увімкнено"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"Недоступно"</item> + <item msgid="3079622119444911877">"Вимкнено"</item> + <item msgid="3028994095749238254">"Увімкнено"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index fa4bd02124e5..452beaf4b07b 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -350,6 +350,7 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"مسئلہ ریکارڈ کریں"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"شروع کریں"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"روکیں"</string> + <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"بگ رپورٹ"</string> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"آپ کے آلے کے تجربے کا کون سا حصہ متاثر ہوا؟"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"مسئلہ کی قسم منتخب کریں"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"اسکرین ریکارڈ"</string> @@ -364,12 +365,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"متوسط"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"زیادہ"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعت کے آلات"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سماعت کے آلات"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"نئے آلے کا جوڑا بنائیں"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"نئے آلے کا جوڑا بنانے کے لیے کلک کریں"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"آلے کا مائیکروفون غیر مسدود کریں؟"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"آلے کا کیمرا غیر مسدود کریں؟"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"آلے کا کیمرا اور مائیکروفون غیر مسدود کریں؟"</string> @@ -744,7 +742,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"کی بورڈ لے آؤٹ سوئچ کریں"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"یا"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"تلاش کا استفسار صاف کریں"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"شارٹ کٹس"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"کی بورڈ شارٹ کٹس"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"شارٹ کٹس تلاش کریں"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"کوئی شارٹ کٹ نہیں ملا"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"سسٹم"</string> @@ -769,9 +767,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"اسسٹنٹ کھولیں"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"مقفل اسکرین"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"نوٹ لیں"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"سسٹم ملٹی ٹاسکنگ"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"موجودہ ایپ کے ساتھ دائیں جانب اسپلٹ اسکرین انٹر کریں"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"موجودہ ایپ کے ساتھ بائیں جانب اسپلٹ اسکرین انٹر کریں"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ملٹی ٹاسکنگ"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"دائیں جانب موجودہ ایپ کے ساتھ اسپلٹ اسکرین کا استعمال کریں"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"بائیں جانب موجودہ ایپ کے ساتھ اسپلٹ اسکرین کا استعمال کریں"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"اسپلٹ اسکرین سے پوری سکرین پر سوئچ کریں"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"اسپلٹ اسکرین کا استعمال کرتے ہوئے دائیں یا نیچے ایپ پر سوئچ کریں"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"اسپلٹ اسکرین کا استعمال کرتے ہوئے بائیں یا اوپر ایپ پر سوئچ کریں"</string> @@ -1123,7 +1121,7 @@ <string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string> <string name="basic_status" msgid="2315371112182658176">"گفتگو کھولیں"</string> <string name="select_conversation_title" msgid="6716364118095089519">"گفتگو ویجیٹس"</string> - <string name="select_conversation_text" msgid="3376048251434956013">"اسے اپنے ہوم اسکرین پر شامل کرنے کے لیے گفتگو پر تھپتھپائیں"</string> + <string name="select_conversation_text" msgid="3376048251434956013">"اسے اپنی ہوم اسکرین پر شامل کرنے کے لیے گفتگو پر تھپتھپائیں"</string> <string name="no_conversations_text" msgid="5354115541282395015">"آپ کی حالیہ گفتگوئیں یہاں دکھائی دیں گی"</string> <string name="priority_conversations" msgid="3967482288896653039">"ترجیحی گفتگوئیں"</string> <string name="recent_conversations" msgid="8531874684782574622">"حالیہ گفتگوئیں"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 195b044a0f6f..7a5cbad4aae1 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Yozib olishda xato"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Boshlash"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Toʻxtatish"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Qurilma ishlashining qaysi qismiga taʼsir qildi?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Muammo turini tanlang"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekran yozuvi"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Oʻrtacha"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Yuqori"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eshitish qurilmalari"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eshitish qurilmalari"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yangi qurilmani ulash"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yangi qurilmani ulash uchun bosing"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Qurilma mikrofoni blokdan chiqarilsinmi?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Qurilma kamerasi blokdan chiqarilsinmi?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Qurilma kamerasi va mikrofoni blokdan chiqarilsinmi?"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura terilmasini almashtirish"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"yoki"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Qidiruv soʻrovini tozalash"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tezkor tugmalar"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tezkor tugmalar"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tezkor tugmalar qidiruvi"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tezkor tugmalar topilmadi"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Tizim"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistentni ochish"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekran qulfi"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Qayd yaratish"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Tizimdagi multi-vazifalik"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Oʻng tomondagi ajratilgan ekran rejimiga kirish"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Chap tomondagi ajratilgan ekran rejimiga kirish"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-vazifalilik"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Ekranni ajratib, joriy ilovani oʻngga joylash"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Ekranni ajratib, joriy ilovani chapga joylash"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Ajratilgan ekran rejimidan butun ekranga almashtirish"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ajratilgan ekranda oʻngdagi yoki pastdagi ilovaga almashish"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ajratilgan ekranda chapdagi yoki yuqoridagi ilovaga almashish"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 469430b5dcf6..85421eef947f 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Ghi lại vấn đề"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Bắt đầu"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Dừng"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Bạn gặp loại vấn đề gì khi dùng thiết bị?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Chọn loại vấn đề"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ghi màn hình"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Vừa"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Cao"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Thiết bị trợ thính"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Thiết bị trợ thính"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Ghép nối thiết bị mới"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Nhấp để ghép nối thiết bị mới"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Bỏ chặn micrô của thiết bị?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Bỏ chặn camera của thiết bị?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Bỏ chặn máy ảnh và micrô của thiết bị?"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Chuyển đổi bố cục bàn phím"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"hoặc"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Xoá cụm từ tìm kiếm"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lối tắt"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Phím tắt"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Lối tắt tìm kiếm"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Không tìm thấy lối tắt"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Hệ thống"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Mở Trợ lý"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Màn hình khoá"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Tạo ghi chú"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Xử lý đa nhiệm trong hệ thống"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Vào chế độ chia đôi màn hình, ứng dụng hiện tại ở màn hình bên phải"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Vào chế độ chia đôi màn hình, ứng dụng hiện tại ở màn hình bên trái"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Đa nhiệm"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Dùng tính năng chia đôi màn hình, trong đó ứng dụng hiện tại ở bên phải"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Dùng tính năng chia đôi màn hình, trong đó ứng dụng hiện tại ở bên trái"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Chuyển từ chế độ chia đôi màn hình sang chế độ toàn màn hình"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Chuyển sang ứng dụng bên phải hoặc ở dưới khi đang chia đôi màn hình"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Chuyển sang ứng dụng bên trái hoặc ở trên khi đang chia đôi màn hình"</string> @@ -994,7 +993,7 @@ <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Huỷ"</string> <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Đã ẩn nút hỗ trợ tiếp cận"</string> <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Nhấn để hiện nút hỗ trợ tiếp cận"</string> - <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Đã xoá phím tắt dành cho <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> + <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Đã xoá lối tắt cho <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Đã xoá # lối tắt}other{Đã xoá # lối tắt}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Chuyển lên trên cùng bên trái"</string> <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Chuyển lên trên cùng bên phải"</string> @@ -1283,7 +1282,7 @@ <string name="mirror_display" msgid="2515262008898122928">"Phản chiếu màn hình"</string> <string name="dismiss_dialog" msgid="2195508495854675882">"Đóng"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"Đã kết nối màn hình"</string> - <string name="privacy_dialog_title" msgid="7839968133469098311">"Micrô và máy ảnh"</string> + <string name="privacy_dialog_title" msgid="7839968133469098311">"Micrô và camera"</string> <string name="privacy_dialog_summary" msgid="2458769652125995409">"Hoạt động sử dụng gần đây của ứng dụng"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Xem hoạt động truy cập gần đây"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Xong"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 6765d1e4f175..d23a0fd97bc4 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"录制问题"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"开始"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"设备体验的哪个方面受到影响?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"选择问题类型"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"屏幕录制"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"标准"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助听装置"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助听装置"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"与新设备配对"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"点击即可与新设备配对"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解锁设备麦克风吗?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解锁设备摄像头吗?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解锁设备摄像头和麦克风吗?"</string> @@ -686,7 +684,7 @@ <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"无法修改来电通知。"</string> <string name="notification_multichannel_desc" msgid="7414593090056236179">"您无法在此处配置这组通知"</string> <string name="notification_delegate_header" msgid="1264510071031479920">"代理通知"</string> - <string name="notification_channel_dialog_title" msgid="6856514143093200019">"所有的<xliff:g id="APP_NAME">%1$s</xliff:g>通知"</string> + <string name="notification_channel_dialog_title" msgid="6856514143093200019">"所有“<xliff:g id="APP_NAME">%1$s</xliff:g>”通知"</string> <string name="see_more_title" msgid="7409317011708185729">"查看更多"</string> <string name="feedback_alerted" msgid="5192459808484271208">"系统已自动将此通知的重要性<b>提升为“默认”</b>。"</string> <string name="feedback_silenced" msgid="9116540317466126457">"系统已自动将此通知的重要性<b>降低为“静音”</b>。"</string> @@ -745,12 +743,12 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切换键盘布局"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜索查询"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快捷键"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"键盘快捷键"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜索快捷键"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"未找到任何快捷键"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"系统"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"输入"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已开应用"</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已打开的应用"</string> <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"当前应用"</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"目前显示的是搜索结果"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"目前显示的是系统快捷键"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"打开 Google 助理"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"锁定屏幕"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"添加记事"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系统多任务处理"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"进入分屏模式,当前应用显示于右侧"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"进入分屏模式,当前应用显示于左侧"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多任务处理"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"使用分屏模式,并且当前应用位于右侧"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"使用分屏模式,并且当前应用位于左侧"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"从分屏模式切换为全屏"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分屏模式时,切换到右侧或下方的应用"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分屏模式时,切换到左侧或上方的应用"</string> @@ -830,7 +828,7 @@ <string name="left_icon" msgid="5036278531966897006">"向左图标"</string> <string name="right_icon" msgid="1103955040645237425">"向右图标"</string> <string name="drag_to_add_tiles" msgid="8933270127508303672">"按住并拖动即可添加功能块"</string> - <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"按住并拖动即可重新排列图块"</string> + <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"按住并拖动即可重新排列功能块"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"拖动到此处即可移除"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"您至少需要 <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> 个卡片"</string> <string name="qs_edit" msgid="5583565172803472437">"编辑"</string> @@ -1194,7 +1192,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 个应用处于活动状态}other{# 个应用处于活动状态}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"新信息"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"已开启的应用"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"这些应用正在保持活跃运行状态,即使您没有在使用它们。这可以改进它们的功能,但可能会影响到电池续航时间。"</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"这些应用即使在闲置时仍处于活跃运行状态。应用的功能会因此提升,但可能会影响电池续航时间。"</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"已停止"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"完成"</string> @@ -1285,7 +1283,7 @@ <string name="dismiss_dialog" msgid="2195508495854675882">"关闭"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"显示屏已连接"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"麦克风和摄像头"</string> - <string name="privacy_dialog_summary" msgid="2458769652125995409">"近期应用对手机传感器的使用情况"</string> + <string name="privacy_dialog_summary" msgid="2458769652125995409">"近期被应用使用的情况"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期使用情况"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"完成"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"展开并显示选项"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml index a9a377a0fbff..9467b9b27f26 100644 --- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"已关闭"</item> <item msgid="5137565285664080143">"已开启"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"不可用"</item> + <item msgid="3079622119444911877">"关闭"</item> + <item msgid="3028994095749238254">"开启"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index d4891d533276..04565e53be1c 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"錄製問題"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"開始"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"哪些裝置使用體驗受影響?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"選取問題類型"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"螢幕錄影"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助聽器"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"配對新裝置"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"㩒一下就可以配對新裝置"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解除封鎖裝置相機和麥克風嗎?"</string> @@ -745,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜尋查詢"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"鍵盤快速鍵"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜尋快速鍵"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"找不到快速鍵"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"系統"</string> @@ -770,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"開啟「Google 助理」"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"上鎖畫面"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"寫筆記"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系統多工處理"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"進入分割螢幕模式,並將目前的應用程式顯示在右側"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"進入分割螢幕模式,並將目前的應用程式顯示在左側"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多工處理"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"使用分割螢幕,並在右側顯示目前使用的應用程式"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"使用分割螢幕,並在左側顯示目前使用的應用程式"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"將分割螢幕切換為全螢幕"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分割螢幕時,切換至右邊或下方的應用程式"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分割螢幕時,切換至左邊或上方的應用程式"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml index f0ccd9e3d864..cca7ac42906a 100644 --- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"關閉"</item> <item msgid="5137565285664080143">"開啟"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"無法使用"</item> + <item msgid="3079622119444911877">"關閉"</item> + <item msgid="3028994095749238254">"開啟"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index bc59988f681d..11d2c3ed0b0f 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"記錄問題"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"開始"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"哪些裝置使用體驗受到影響?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"選取問題類型"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"螢幕錄影"</string> @@ -363,14 +365,10 @@ <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string> <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string> - <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) --> - <skip /> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助聽器"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"配對新裝置"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"按一下即可配對新裝置"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要將裝置的相機和麥克風解除封鎖嗎?"</string> @@ -678,7 +676,7 @@ <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>狀態:</b>已調降順序"</string> <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片)"</string> <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"以對話框的形式顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片)"</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片),並會中斷「零打擾」模式"</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"顯示在對話通知頂端 (螢幕鎖定時會顯示個人資料相片),並會中斷「零打擾」模式"</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以對話框的形式顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片),並會中斷「零打擾」模式"</string> <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string> <string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string> @@ -745,12 +743,12 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜尋查詢"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"鍵盤快速鍵"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜尋快速鍵"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"找不到快速鍵"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"系統"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"輸入"</string> - <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已開啟的應用程式"</string> + <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"開啟應用程式"</string> <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"目前的應用程式"</string> <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"顯示搜尋結果"</string> <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"顯示系統快速鍵"</string> @@ -763,16 +761,16 @@ <string name="group_system_go_back" msgid="2730322046244918816">"返回"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"前往主畫面"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"查看最近開啟的應用程式"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"前往最近開啟的應用程式"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"返回最近開啟的應用程式"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"向前循環切換最近開啟的應用程式"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"向後循環切換最近開啟的應用程式"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"開啟應用程式清單"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"開啟設定"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"開啟 Google 助理"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"螢幕鎖定"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"新增記事"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系統多工處理"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"進入分割畫面模式,並將目前的應用程式顯示於右側"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"進入分割畫面模式,並將目前的應用程式顯示於左側"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多工處理"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"使用分割畫面,並在右側顯示目前使用的應用程式"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"使用分割畫面,並在左側顯示目前使用的應用程式"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"從分割畫面切換到完整畫面"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分割畫面時,切換到右邊或上方的應用程式"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分割畫面時,切換到左邊或上方的應用程式"</string> @@ -868,7 +866,7 @@ <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"編輯設定順序。"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源鍵選單"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string> - <string name="tuner_lock_screen" msgid="2267383813241144544">"鎖定畫面"</string> + <string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string> <string name="finder_active" msgid="7907846989716941952">"即使這支手機關機,仍可透過「尋找我的裝置」找出手機位置"</string> <string name="shutdown_progress" msgid="5464239146561542178">"關機中…"</string> <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看處理步驟"</string> @@ -1194,7 +1192,7 @@ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 個應用程式正在運作}other{# 個應用程式正在運作}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"新資訊"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"運作中的應用程式"</string> - <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"即使你並未使用,這些應用程式仍會持續運作。這可提升應用程式效能,但也可能影響電池續航力。"</string> + <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"這些應用程式會在沒有使用的情況下持續運作。應用程式的實用度會因此提升,但也可能影響電池續航力。"</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"已停止"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"完成"</string> @@ -1285,7 +1283,7 @@ <string name="dismiss_dialog" msgid="2195508495854675882">"關閉"</string> <string name="connected_display_icon_desc" msgid="6373560639989971997">"螢幕已連結"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"麥克風和相機"</string> - <string name="privacy_dialog_summary" msgid="2458769652125995409">"最近曾使用感應器的應用程式"</string> + <string name="privacy_dialog_summary" msgid="2458769652125995409">"最近使用的應用程式"</string> <string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期存取記錄"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"完成"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"展開並顯示選項"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml index 2c474f624ca7..4cc580434a36 100644 --- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml @@ -186,7 +186,9 @@ <item msgid="2478289035899842865">"關閉"</item> <item msgid="5137565285664080143">"開啟"</item> </string-array> - <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) --> - <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) --> - <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) --> + <string-array name="tile_states_hearing_devices"> + <item msgid="1235334096484287173">"無法使用"</item> + <item msgid="3079622119444911877">"已關閉"</item> + <item msgid="3028994095749238254">"已開啟"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 780fe948d531..6f87762c1b41 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -260,7 +260,7 @@ <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Isikrini sikhiyelwe ngomumo we-landscape."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Isikrini sikhiyelwe ngomumo we-portrait."</string> <string name="dessert_case" msgid="9104973640704357717">"Isikhwama soswidi"</string> - <string name="start_dreams" msgid="9131802557946276718">"Isigcini sihenqo"</string> + <string name="start_dreams" msgid="9131802557946276718">"Isigciniskrini"</string> <string name="ethernet_label" msgid="2203544727007463351">"I-Ethernet"</string> <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ungaphazamisi"</string> <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"I-Bluetooth"</string> @@ -350,6 +350,8 @@ <string name="qs_record_issue_label" msgid="8166290137285529059">"Rekhoda Inkinga"</string> <string name="qs_record_issue_start" msgid="2979831312582567056">"Qala"</string> <string name="qs_record_issue_stop" msgid="3531747965741982657">"Misa"</string> + <!-- no translation found for qs_record_issue_bug_report (8229031766918650079) --> + <skip /> <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Kuthinteke yiphi ingxenye yokusebenzisa idivayisi?"</string> <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Khetha uhlobo lwenkinga"</string> <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Irekhodi lesikrini"</string> @@ -364,12 +366,9 @@ <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Okuphakathi"</string> <string name="quick_settings_contrast_high" msgid="656049259587494499">"Phezulu"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Izinsizakuzwa"</string> - <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) --> - <skip /> - <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) --> - <skip /> - <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) --> - <skip /> + <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Izinsizakuzwa"</string> + <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Bhangqa idivayisi entsha"</string> + <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Chofoza ukuze ubhangqe idivayisi entsha"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vulela imakrofoni yedivayisi?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vulela ikhamera yedivayisi?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vulela ikhamera yedivayisi nemakrofoni?"</string> @@ -744,7 +743,7 @@ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Shintsha isakhiwo sekhibhodi"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"noma"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Sula umbuzo wosesho"</string> - <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Izinqamuleli"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Izinqamuleli Zekhibhodi"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sesha izinqamuleli"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Azikho izinqamuleli ezitholakele"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Isistimu"</string> @@ -769,9 +768,9 @@ <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Vula umsizi"</string> <string name="group_system_lock_screen" msgid="7391191300363416543">"Khiya isikrini"</string> <string name="group_system_quick_memo" msgid="3764560265935722903">"Thatha inothi"</string> - <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Ukwenza imisebenzi eminingi yesistimu"</string> - <string name="system_multitasking_rhs" msgid="2454557648974553729">"Faka ukuhlukanisa isikrini nge-app yamanje kuya ku-RHS"</string> - <string name="system_multitasking_lhs" msgid="3516599774920979402">"Faka ukuhlukanisa isikrini nge-app yamanje kuya ku-LHS"</string> + <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Ukwenza imisebenzi eminingi"</string> + <string name="system_multitasking_rhs" msgid="8714224917276297810">"Sebenzisa isikrini esihlukanisayo nge-app yamanje kwesokudla"</string> + <string name="system_multitasking_lhs" msgid="8402954791206308783">"Sebenzisa isikrini sokuhlukanisa nge-app yamanje kwesokunxele"</string> <string name="system_multitasking_full_screen" msgid="336048080383640562">"Shintsha usuka ekuhlukaniseni isikrini uye kusikrini esigcwele"</string> <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Shintshela ku-app ngakwesokudla noma ngezansi ngenkathi usebenzisa uhlukanisa isikrini"</string> <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Shintshela ku-app ngakwesokunxele noma ngaphezulu ngenkathi usebenzisa ukuhlukanisa isikrini"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index a6f6d4dcf2f9..fa9d507dbff5 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -116,9 +116,6 @@ The syntax is setting-name:spec. If the tile is a TileService, the spec should be specified as custom(package/class). Relative class name is supported. --> <string-array name="config_quickSettingsAutoAdd" translatable="false"> - <item>accessibility_display_daltonizer_enabled:color_correction</item> - <item>accessibility_display_inversion_enabled:inversion</item> - <item>one_handed_mode_enabled:onehanded</item> <item>accessibility_font_scaling_has_been_changed:font_scaling</item> </string-array> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index b0b548295b71..26fa2b136ed4 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -613,7 +613,7 @@ <dimen name="volume_panel_slice_vertical_padding">8dp</dimen> <dimen name="volume_panel_slice_horizontal_padding">24dp</dimen> - <dimen name="volume_panel_corner_radius">52dp</dimen> + <dimen name="volume_panel_corner_radius">28dp</dimen> <!-- Size of each item in the ringer selector drawer. --> <dimen name="volume_ringer_drawer_item_size">42dp</dimen> @@ -2001,4 +2001,7 @@ <!-- SliceView grid gutter for ANC Slice --> <dimen name="abc_slice_grid_gutter">0dp</dimen> + <!-- SliceView icon size --> + <dimen name="abc_slice_big_pic_min_height">64dp</dimen> + <dimen name="abc_slice_big_pic_max_height">64dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index af661aa172c7..f60f6c7af289 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -678,6 +678,8 @@ <string name="turn_on_bluetooth">Use Bluetooth</string> <!-- QuickSettings: Bluetooth dialog device connected default summary [CHAR LIMIT=NONE]--> <string name="quick_settings_bluetooth_device_connected">Connected</string> + <!-- QuickSettings: Bluetooth dialog device in audio sharing default summary [CHAR LIMIT=50]--> + <string name="quick_settings_bluetooth_device_audio_sharing">Audio Sharing</string> <!-- QuickSettings: Bluetooth dialog device saved default summary [CHAR LIMIT=NONE]--> <string name="quick_settings_bluetooth_device_saved">Saved</string> <!-- QuickSettings: Accessibility label to disconnect a device [CHAR LIMIT=NONE]--> @@ -687,9 +689,13 @@ <!-- QuickSettings: Bluetooth auto on tomorrow [CHAR LIMIT=NONE]--> <string name="turn_on_bluetooth_auto_tomorrow">Automatically turn on again tomorrow</string> <!-- QuickSettings: Bluetooth auto on info text when disabled [CHAR LIMIT=NONE]--> - <string name="turn_on_bluetooth_auto_info_disabled">Features like Quick Share, Find My Device, and device location use Bluetooth</string> + <string name="turn_on_bluetooth_auto_info_disabled">Features like Quick Share and Find My Device use Bluetooth</string> <!-- QuickSettings: Bluetooth auto on info text when enabled [CHAR LIMIT=NONE]--> - <string name="turn_on_bluetooth_auto_info_enabled">Bluetooth will turn on tomorrow at 5 AM</string> + <string name="turn_on_bluetooth_auto_info_enabled">Bluetooth will turn on tomorrow morning</string> + <!-- QuickSettings: Bluetooth dialog audio sharing button text [CHAR LIMIT=50]--> + <string name="quick_settings_bluetooth_audio_sharing_button">Audio Sharing</string> + <!-- QuickSettings: Bluetooth dialog audio sharing button text when sharing audio [CHAR LIMIT=50]--> + <string name="quick_settings_bluetooth_audio_sharing_button_sharing">Sharing Audio</string> <!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]--> <string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string> diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt index a2b119833474..f07dce5e3482 100644 --- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt +++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt @@ -16,6 +16,7 @@ package com.android.systemui.biometrics.shared.model +import android.graphics.Rect import android.hardware.fingerprint.FingerprintSensorPropertiesInternal /** Fingerprint sensor property. Represents [FingerprintSensorPropertiesInternal]. */ @@ -23,12 +24,23 @@ data class FingerprintSensor( val sensorId: Int, val sensorStrength: SensorStrength, val maxEnrollmentsPerUser: Int, - val sensorType: FingerprintSensorType + val sensorType: FingerprintSensorType, + val sensorBounds: Rect, + val sensorRadius: Int, ) /** Convert [FingerprintSensorPropertiesInternal] to corresponding [FingerprintSensor] */ fun FingerprintSensorPropertiesInternal.toFingerprintSensor(): FingerprintSensor { val sensorStrength: SensorStrength = this.sensorStrength.toSensorStrength() val sensorType: FingerprintSensorType = this.sensorType.toSensorType() - return FingerprintSensor(this.sensorId, sensorStrength, this.maxEnrollmentsPerUser, sensorType) + val sensorBounds: Rect = this.location.rect + val sensorRadius = this.location.sensorRadius + return FingerprintSensor( + this.sensorId, + sensorStrength, + this.maxEnrollmentsPerUser, + sensorType, + sensorBounds, + sensorRadius, + ) } diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt index 476daac5ff00..0f3d28586588 100644 --- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt +++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt @@ -33,3 +33,10 @@ fun Int.toSensorStrength(): SensorStrength = SensorProperties.STRENGTH_STRONG -> SensorStrength.STRONG else -> throw IllegalArgumentException("Invalid SensorStrength value: $this") } +/** Convert [SensorStrength] to corresponding [Int] */ +fun SensorStrength.toInt(): Int = + when (this) { + SensorStrength.CONVENIENCE -> SensorProperties.STRENGTH_CONVENIENCE + SensorStrength.WEAK -> SensorProperties.STRENGTH_WEAK + SensorStrength.STRONG -> SensorProperties.STRENGTH_STRONG + } diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 70182c16a093..460779c73cda 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -15,6 +15,7 @@ */ package com.android.keyguard +import android.os.Trace import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -31,7 +32,6 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener import androidx.annotation.VisibleForTesting import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle -import com.android.app.tracing.coroutines.launch import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.customization.R import com.android.systemui.dagger.qualifiers.Background @@ -66,7 +66,6 @@ import java.util.Locale import java.util.TimeZone import java.util.concurrent.Executor import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job @@ -74,6 +73,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.launch /** * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by @@ -91,7 +91,6 @@ constructor( @DisplaySpecific private val resources: Resources, private val context: Context, @Main private val mainExecutor: DelayableExecutor, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, @Background private val bgExecutor: Executor, private val clockBuffers: ClockMessageBuffers, private val featureFlags: FeatureFlagsClassic, @@ -426,12 +425,13 @@ constructor( keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) zenModeController.addCallback(zenModeCallback) disposableHandle = - parent.repeatWhenAttached(mainImmediateDispatcher) { + parent.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { listenForDozing(this) if (MigrateClocksToBlueprint.isEnabled) { listenForDozeAmountTransition(this) listenForAnyStateToAodTransition(this) + listenForAnyStateToLockscreenTransition(this) } else { listenForDozeAmount(this) } @@ -522,8 +522,12 @@ constructor( private fun handleDoze(doze: Float) { dozeAmount = doze clock?.run { + Trace.beginSection("$TAG#smallClock.animations.doze") smallClock.animations.doze(dozeAmount) + Trace.endSection() + Trace.beginSection("$TAG#largeClock.animations.doze") largeClock.animations.doze(dozeAmount) + Trace.endSection() } smallTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD) largeTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD) @@ -531,19 +535,17 @@ constructor( @VisibleForTesting internal fun listenForDozeAmount(scope: CoroutineScope): Job { - return scope.launch("$TAG#listenForDozeAmount") { - keyguardInteractor.dozeAmount.collect { handleDoze(it) } - } + return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } } } @VisibleForTesting internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job { - return scope.launch("$TAG#listenForDozeAmountTransition") { + return scope.launch { merge( - keyguardTransitionInteractor.aodToLockscreenTransition.map { step -> + keyguardTransitionInteractor.transition(AOD, LOCKSCREEN).map { step -> step.copy(value = 1f - step.value) }, - keyguardTransitionInteractor.lockscreenToAodTransition, + keyguardTransitionInteractor.transition(LOCKSCREEN, AOD), ).filter { it.transitionState != TransitionState.FINISHED } @@ -556,7 +558,7 @@ constructor( */ @VisibleForTesting internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job { - return scope.launch("$TAG#listenForAnyStateToAodTransition") { + return scope.launch { keyguardTransitionInteractor .transitionStepsToState(AOD) .filter { it.transitionState == TransitionState.STARTED } @@ -566,8 +568,19 @@ constructor( } @VisibleForTesting + internal fun listenForAnyStateToLockscreenTransition(scope: CoroutineScope): Job { + return scope.launch { + keyguardTransitionInteractor + .transitionStepsToState(LOCKSCREEN) + .filter { it.transitionState == TransitionState.STARTED } + .filter { it.from != AOD } + .collect { handleDoze(0f) } + } + } + + @VisibleForTesting internal fun listenForDozing(scope: CoroutineScope): Job { - return scope.launch("$TAG#listenForDozing") { + return scope.launch { combine( keyguardInteractor.dozeAmount, keyguardInteractor.isDozing, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 25d771308aea..e8e1cab4b932 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -83,14 +83,14 @@ import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardWmStateRefactor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent; import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -101,6 +101,8 @@ import com.android.systemui.util.ViewController; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.settings.GlobalSettings; +import dagger.Lazy; + import java.io.File; import java.util.Arrays; import java.util.Optional; @@ -108,7 +110,6 @@ import java.util.Optional; import javax.inject.Inject; import javax.inject.Provider; -import dagger.Lazy; import kotlinx.coroutines.Job; /** Controller for {@link KeyguardSecurityContainer} */ @@ -133,7 +134,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard private final UserSwitcherController mUserSwitcherController; private final GlobalSettings mGlobalSettings; private final FeatureFlags mFeatureFlags; - private final SceneContainerFlags mSceneContainerFlags; private final SessionTracker mSessionTracker; private final Optional<SideFpsController> mSideFpsController; private final FalsingA11yDelegate mFalsingA11yDelegate; @@ -310,7 +310,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard */ @Override public void finish(int targetUserId) { - if (!mFeatureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (!RefactorKeyguardDismissIntent.isEnabled()) { // If there's a pending runnable because the user interacted with a widget // and we're leaving keyguard, then run it. boolean deferKeyguardDone = false; @@ -455,7 +455,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard FalsingManager falsingManager, UserSwitcherController userSwitcherController, FeatureFlags featureFlags, - SceneContainerFlags sceneContainerFlags, GlobalSettings globalSettings, SessionTracker sessionTracker, Optional<SideFpsController> sideFpsController, @@ -490,7 +489,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mFalsingManager = falsingManager; mUserSwitcherController = userSwitcherController; mFeatureFlags = featureFlags; - mSceneContainerFlags = sceneContainerFlags; mGlobalSettings = globalSettings; mSessionTracker = sessionTracker; if (SideFpsControllerRefactor.isEnabled()) { @@ -533,7 +531,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard showPrimarySecurityScreen(false); - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { // When the scene framework says that the lockscreen has been dismissed, dismiss the // keyguard here, revealing the underlying app or launcher: mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow( @@ -649,7 +647,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard * @param action callback to be invoked when keyguard disappear animation completes. */ public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) { - if (mFeatureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled()) { return; } if (mCancelAction != null) { @@ -943,7 +941,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mUiEventLogger.log(uiEvent, getSessionId()); } - if (mFeatureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled()) { if (authenticatedWithPrimaryAuth) { mPrimaryBouncerInteractor.get() .notifyKeyguardAuthenticatedPrimaryAuth(targetUserId); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java index 9b09265763a2..afeb0f8cdb0d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java @@ -189,6 +189,5 @@ public interface KeyguardViewController { ShadeLockscreenInteractor shadeLockscreenInteractor, @Nullable ShadeExpansionStateManager shadeExpansionStateManager, BiometricUnlockController biometricUnlockController, - View notificationContainer, - KeyguardBypassController bypassController); + View notificationContainer); } diff --git a/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java index 4e5df3543451..cf2675b46418 100644 --- a/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java @@ -74,7 +74,7 @@ import com.android.systemui.keyguard.shared.model.TransitionStep; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -131,7 +131,6 @@ public class LegacyLockIconViewController implements Dumpable, LockIconViewContr @NonNull private final KeyguardInteractor mKeyguardInteractor; @NonNull private final View.AccessibilityDelegate mAccessibilityDelegate; @NonNull private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractor; - @NonNull private final SceneContainerFlags mSceneContainerFlags; // Tracks the velocity of a touch to help filter out the touches that move too fast. private VelocityTracker mVelocityTracker; @@ -208,8 +207,7 @@ public class LegacyLockIconViewController implements Dumpable, LockIconViewContr @NonNull FeatureFlags featureFlags, PrimaryBouncerInteractor primaryBouncerInteractor, Context context, - Lazy<DeviceEntryInteractor> deviceEntryInteractor, - SceneContainerFlags sceneContainerFlags + Lazy<DeviceEntryInteractor> deviceEntryInteractor ) { mStatusBarStateController = statusBarStateController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; @@ -236,7 +234,6 @@ public class LegacyLockIconViewController implements Dumpable, LockIconViewContr mResources = resources; mContext = context; mDeviceEntryInteractor = deviceEntryInteractor; - mSceneContainerFlags = sceneContainerFlags; mAccessibilityDelegate = new View.AccessibilityDelegate() { private final AccessibilityNodeInfo.AccessibilityAction mAccessibilityAuthenticateHint = @@ -746,7 +743,7 @@ public class LegacyLockIconViewController implements Dumpable, LockIconViewContr // play device entry haptic (consistent with UDFPS controller longpress) vibrateOnLongPress(); - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { mDeviceEntryInteractor.get().attemptDeviceEntry(); } else { mKeyguardViewController.showPrimaryBouncer(/* scrim */ true); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 3e03fb8dfaff..b8af59d78942 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -401,8 +401,6 @@ public class ScreenDecorations implements mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler); mExecutor.execute(this::startOnScreenDecorationsThread); mDotViewController.setUiExecutor(mExecutor); - mJavaAdapter.alwaysCollectFlow(mFacePropertyRepository.getSensorLocation(), - this::onFaceSensorLocationChanged); mCommandRegistry.registerCommand(ScreenDecorCommand.SCREEN_DECOR_CMD_NAME, () -> new ScreenDecorCommand(mScreenDecorCommandCallback)); } @@ -579,6 +577,8 @@ public class ScreenDecorations implements }; mDisplayTracker.addDisplayChangeCallback(mDisplayListener, new HandlerExecutor(mHandler)); updateConfiguration(); + mJavaAdapter.alwaysCollectFlow(mFacePropertyRepository.getSensorLocation(), + this::onFaceSensorLocationChanged); Trace.endSection(); } @@ -1320,10 +1320,18 @@ public class ScreenDecorations implements @VisibleForTesting void onFaceSensorLocationChanged(Point location) { mLogger.onSensorLocationChanged(); + if (mExecutor != null) { mExecutor.execute( - () -> updateOverlayProviderViews( - new Integer[]{mFaceScanningViewId})); + () -> { + if (getOverlayView(mFaceScanningViewId) == null) { + // face sensor location was just initialized + setupDecorations(); + } else { + updateOverlayProviderViews(new Integer[]{mFaceScanningViewId}); + } + } + ); } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java index 0f4d63c7ebcc..615363da073a 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java @@ -72,6 +72,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp private boolean mEndAnimationCanceled = false; @MagnificationState private int mState = STATE_DISABLED; + private Runnable mOnAnimationEndRunnable; WindowMagnificationAnimationController(@UiContext Context context) { this(context, newValueAnimator(context.getResources())); @@ -149,7 +150,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp if (mState == STATE_ENABLING || mState == STATE_DISABLING) { mValueAnimator.cancel(); } - mController.enableWindowMagnificationInternal(scale, centerX, centerY, + mController.updateWindowMagnificationInternal(scale, centerX, centerY, mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY); updateState(); return; @@ -159,7 +160,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp if (mEndSpec.equals(mStartSpec)) { if (mState == STATE_DISABLED) { - mController.enableWindowMagnificationInternal(scale, centerX, centerY, + mController.updateWindowMagnificationInternal(scale, centerX, centerY, mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY); } else if (mState == STATE_ENABLING || mState == STATE_DISABLING) { mValueAnimator.cancel(); @@ -303,12 +304,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp return; } - // If the animation is playing backwards, mStartSpec will be the final spec we would - // like to reach. - AnimationSpec spec = isReverse ? mStartSpec : mEndSpec; - mController.enableWindowMagnificationInternal( - spec.mScale, spec.mCenterX, spec.mCenterY, - mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY); + mOnAnimationEndRunnable.run(); if (mState == STATE_DISABLING) { mController.deleteWindowMagnification(); @@ -333,6 +329,10 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp public void onAnimationRepeat(Animator animation) { } + void setOnAnimationEndRunnable(Runnable runnable) { + mOnAnimationEndRunnable = runnable; + } + private void sendAnimationCallback(boolean success) { if (mAnimationCallback != null) { try { @@ -358,7 +358,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp mStartSpec.mCenterX + (mEndSpec.mCenterX - mStartSpec.mCenterX) * fract; final float centerY = mStartSpec.mCenterY + (mEndSpec.mCenterY - mStartSpec.mCenterY) * fract; - mController.enableWindowMagnificationInternal(sentScale, centerX, centerY, + mController.updateWindowMagnificationInternal(sentScale, centerX, centerY, mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index d65cd5c09dcf..9837e369bc91 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -148,7 +148,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold /** * SourceBound is the bound of the magnified region which projects the magnified content. * SourceBound's center is equal to the parameters centerX and centerY in - * {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float, float)}} + * {@link WindowMagnificationController#updateWindowMagnificationInternal(float, float, float)}} * but it is calculated from {@link #mMagnificationFrame}'s center in the runtime. */ private final Rect mSourceBounds = new Rect(); @@ -260,6 +260,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mContext = context; mHandler = handler; mAnimationController = animationController; + mAnimationController.setOnAnimationEndRunnable(() -> { + if (Flags.createWindowlessWindowMagnifier()) { + notifySourceBoundsChanged(); + } + }); mAnimationController.setWindowMagnificationController(this); mWindowMagnifierCallback = callback; mSysUiState = sysUiState; @@ -566,7 +571,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // window size changed not caused by rotation. if (isActivated() && reCreateWindow) { deleteWindowMagnification(); - enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); + updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); } } @@ -1051,11 +1056,15 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // Notify source bounds change when the magnifier is not animating. if (!mAnimationController.isAnimating()) { - mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds); + notifySourceBoundsChanged(); } } } + private void notifySourceBoundsChanged() { + mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds); + } + /** * Updates the position of {@link mSurfaceControlViewHost} and layout params of MirrorView based * on the position and size of {@link #mMagnificationFrame}. @@ -1317,7 +1326,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } /** - * Wraps {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float, + * Wraps {@link WindowMagnificationController#updateWindowMagnificationInternal(float, float, * float, float, float)} * with transition animation. If the window magnification is not enabled, the scale will start * from 1.0 and the center won't be changed during the animation. If animator is @@ -1344,10 +1353,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } /** - * Enables window magnification with specified parameters. If the given scale is <strong>less - * than or equal to 1.0f</strong>, then + * Updates window magnification status with specified parameters. If the given scale is + * <strong>less than 1.0f</strong>, then * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to - * be consistent with the behavior of display magnification. + * be consistent with the behavior of display magnification. If the given scale is + * <strong>larger than or equal to 1.0f</strong>, and the window magnification is not activated + * yet, window magnification will be enabled. * * @param scale the target scale, or {@link Float#NaN} to leave unchanged * @param centerX the screen-relative X coordinate around which to center for magnification, @@ -1355,16 +1366,17 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * @param centerY the screen-relative Y coordinate around which to center for magnification, * or {@link Float#NaN} to leave unchanged. */ - void enableWindowMagnificationInternal(float scale, float centerX, float centerY) { - enableWindowMagnificationInternal(scale, centerX, centerY, Float.NaN, Float.NaN); + void updateWindowMagnificationInternal(float scale, float centerX, float centerY) { + updateWindowMagnificationInternal(scale, centerX, centerY, Float.NaN, Float.NaN); } /** - * Enables window magnification with specified parameters. If the given scale is <strong>less - * than 1.0f</strong>, then + * Updates window magnification status with specified parameters. If the given scale is + * <strong>less than 1.0f</strong>, then * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to - * be consistent with the behavior of display magnification. - * + * be consistent with the behavior of display magnification. If the given scale is + * <strong>larger than or equal to 1.0f</strong>, and the window magnification is not activated + * yet, window magnification will be enabled. * @param scale the target scale, or {@link Float#NaN} to leave unchanged * @param centerX the screen-relative X coordinate around which to center for magnification, * or {@link Float#NaN} to leave unchanged. @@ -1377,7 +1389,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * between frame position Y and centerY, * or {@link Float#NaN} to leave unchanged. */ - void enableWindowMagnificationInternal(float scale, float centerX, float centerY, + void updateWindowMagnificationInternal(float scale, float centerX, float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) { if (Float.compare(scale, 1.0f) < 0) { deleteWindowMagnification(); @@ -1433,7 +1445,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return; } - enableWindowMagnificationInternal(scale, Float.NaN, Float.NaN); + updateWindowMagnificationInternal(scale, Float.NaN, Float.NaN); mHandler.removeCallbacks(mUpdateStateDescriptionRunnable); mHandler.postDelayed(mUpdateStateDescriptionRunnable, UPDATE_STATE_DESCRIPTION_DELAY_MS); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java index 1018f70c7f60..eb840f1f4c90 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java @@ -244,11 +244,13 @@ class MenuInfoRepository { mSecureSettings.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS), /* notifyForDescendants */ false, mMenuTargetFeaturesContentObserver, UserHandle.USER_CURRENT); - mSecureSettings.registerContentObserverForUser( - mSecureSettings.getUriFor(ENABLED_ACCESSIBILITY_SERVICES), - /* notifyForDescendants */ false, - mMenuTargetFeaturesContentObserver, - UserHandle.USER_CURRENT); + if (!com.android.systemui.Flags.floatingMenuNarrowTargetContentObserver()) { + mSecureSettings.registerContentObserverForUser( + mSecureSettings.getUriFor(ENABLED_ACCESSIBILITY_SERVICES), + /* notifyForDescendants */ false, + mMenuTargetFeaturesContentObserver, + UserHandle.USER_CURRENT); + } mSecureSettings.registerContentObserverForUser( mSecureSettings.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE), /* notifyForDescendants */ false, mMenuSizeContentObserver, @@ -263,8 +265,10 @@ class MenuInfoRepository { UserHandle.USER_CURRENT); mContext.registerComponentCallbacks(mComponentCallbacks); - mAccessibilityManager.addAccessibilityServicesStateChangeListener( - mA11yServicesStateChangeListener); + if (!com.android.systemui.Flags.floatingMenuNarrowTargetContentObserver()) { + mAccessibilityManager.addAccessibilityServicesStateChangeListener( + mA11yServicesStateChangeListener); + } } void unregisterObserversAndCallbacks() { @@ -273,8 +277,10 @@ class MenuInfoRepository { mContext.getContentResolver().unregisterContentObserver(mMenuFadeOutContentObserver); mContext.unregisterComponentCallbacks(mComponentCallbacks); - mAccessibilityManager.removeAccessibilityServicesStateChangeListener( - mA11yServicesStateChangeListener); + if (!com.android.systemui.Flags.floatingMenuNarrowTargetContentObserver()) { + mAccessibilityManager.removeAccessibilityServicesStateChangeListener( + mA11yServicesStateChangeListener); + } } interface OnSettingsContentsChanged { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt index 7cb028abba60..b8ff0c030f01 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt +++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt @@ -16,6 +16,7 @@ package com.android.systemui.accessibility.qs +import com.android.systemui.Flags import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.tileimpl.QSTileImpl @@ -40,9 +41,14 @@ import com.android.systemui.qs.tiles.impl.inversion.domain.ColorInversionTileMap import com.android.systemui.qs.tiles.impl.inversion.domain.interactor.ColorInversionTileDataInteractor import com.android.systemui.qs.tiles.impl.inversion.domain.interactor.ColorInversionUserActionInteractor import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor.ReduceBrightColorsTileDataInteractor +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor.ReduceBrightColorsTileUserActionInteractor +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.android.systemui.qs.tiles.impl.reducebrightness.ui.ReduceBrightColorsTileMapper import com.android.systemui.qs.tiles.viewmodel.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel +import com.android.systemui.qs.tiles.viewmodel.StubQSTileViewModel import com.android.systemui.res.R import dagger.Binds import dagger.Module @@ -105,6 +111,7 @@ interface QSAccessibilityModule { const val COLOR_CORRECTION_TILE_SPEC = "color_correction" const val COLOR_INVERSION_TILE_SPEC = "inversion" const val FONT_SCALING_TILE_SPEC = "font_scaling" + const val REDUCE_BRIGHTNESS_TILE_SPEC = "reduce_brightness" @Provides @IntoMap @@ -198,5 +205,41 @@ interface QSAccessibilityModule { stateInteractor, mapper, ) + + @Provides + @IntoMap + @StringKey(REDUCE_BRIGHTNESS_TILE_SPEC) + fun provideReduceBrightColorsTileConfig(uiEventLogger: QsEventLogger): QSTileConfig = + QSTileConfig( + tileSpec = TileSpec.create(REDUCE_BRIGHTNESS_TILE_SPEC), + uiConfig = + QSTileUIConfig.Resource( + iconRes = R.drawable.qs_extra_dim_icon_on, + labelRes = com.android.internal.R.string.reduce_bright_colors_feature_name, + ), + instanceId = uiEventLogger.getNewInstanceId(), + ) + + /** + * Inject Reduce Bright Colors Tile into tileViewModelMap in QSModule. The tile is hidden + * behind a flag. + */ + @Provides + @IntoMap + @StringKey(REDUCE_BRIGHTNESS_TILE_SPEC) + fun provideReduceBrightColorsTileViewModel( + factory: QSTileViewModelFactory.Static<ReduceBrightColorsTileModel>, + mapper: ReduceBrightColorsTileMapper, + stateInteractor: ReduceBrightColorsTileDataInteractor, + userActionInteractor: ReduceBrightColorsTileUserActionInteractor + ): QSTileViewModel = + if (Flags.qsNewTilesFuture()) + factory.create( + TileSpec.create(REDUCE_BRIGHTNESS_TILE_SPEC), + userActionInteractor, + stateInteractor, + mapper, + ) + else StubQSTileViewModel } } diff --git a/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS b/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS new file mode 100644 index 000000000000..b65d29c6a0bb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 1495344 + +dupin@google.com +linyuh@google.com +pauldpong@google.com +praveenj@google.com +vicliang@google.com +mfolkerts@google.com +yuklimko@google.com diff --git a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt new file mode 100644 index 000000000000..ea0039858551 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.ambient.dagger + +import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent +import com.android.systemui.ambient.touch.dagger.InputSessionComponent +import dagger.Module + +@Module(subcomponents = [AmbientTouchComponent::class, InputSessionComponent::class]) +interface AmbientModule { + companion object { + const val TOUCH_HANDLERS = "touch_handlers" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java index 75c50fd5f586..d0f08f53fb32 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; - -import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING; -import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING; -import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION; -import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE; +package com.android.systemui.ambient.touch; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -37,9 +32,11 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.internal.widget.LockPatternUtils; +import com.android.systemui.Flags; +import com.android.systemui.ambient.touch.dagger.BouncerSwipeModule; +import com.android.systemui.ambient.touch.scrim.ScrimController; +import com.android.systemui.ambient.touch.scrim.ScrimManager; import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants; -import com.android.systemui.dreams.touch.scrim.ScrimController; -import com.android.systemui.dreams.touch.scrim.ScrimManager; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.statusbar.NotificationShadeWindowController; @@ -54,7 +51,7 @@ import javax.inject.Named; /** * Monitor for tracking touches on the DreamOverlay to bring up the bouncer. */ -public class BouncerSwipeTouchHandler implements DreamTouchHandler { +public class BouncerSwipeTouchHandler implements TouchHandler { /** * An interface for creating ValueAnimators. */ @@ -124,13 +121,19 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (mCapture == null) { - // If the user scrolling favors a vertical direction, begin capturing - // scrolls. - mCapture = Math.abs(distanceY) > Math.abs(distanceX); mBouncerInitiallyShowing = mCentralSurfaces .map(CentralSurfaces::isBouncerShowing) .orElse(false); + if (Flags.dreamOverlayBouncerSwipeDirectionFiltering()) { + mCapture = Math.abs(distanceY) > Math.abs(distanceX) + && ((distanceY < 0 && mBouncerInitiallyShowing) + || (distanceY > 0 && !mBouncerInitiallyShowing)); + } else { + // If the user scrolling favors a vertical direction, begin capturing + // scrolls. + mCapture = Math.abs(distanceY) > Math.abs(distanceX); + } if (mCapture) { // reset expanding mExpanded = false; @@ -219,12 +222,12 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { VelocityTrackerFactory velocityTrackerFactory, LockPatternUtils lockPatternUtils, UserTracker userTracker, - @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING) + @Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING) FlingAnimationUtils flingAnimationUtils, - @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING) + @Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING) FlingAnimationUtils flingAnimationUtilsClosing, - @Named(SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage, - @Named(MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage, + @Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage, + @Named(BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage, UiEventLogger uiEventLogger) { mCentralSurfaces = centralSurfaces; mScrimManager = scrimManager; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/InputSession.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/InputSession.java index e1d03392044a..6a76c87fd190 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/InputSession.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/InputSession.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; -import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.INPUT_SESSION_NAME; -import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.PILFER_ON_GESTURE_CONSUME; +import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.PILFER_ON_GESTURE_CONSUME; import android.os.Looper; import android.view.Choreographer; import android.view.GestureDetector; import android.view.MotionEvent; -import com.android.systemui.settings.DisplayTracker; +import com.android.systemui.Flags; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputMonitorCompat; @@ -42,26 +42,34 @@ public class InputSession { private final InputChannelCompat.InputEventReceiver mInputEventReceiver; private final GestureDetector mGestureDetector; + // Pilfering is a destructive operation. Once pilfering starts, the all events will be captured + // by the associated monitor. We track whether we're pilfering since initiating pilfering + // requires reaching out to the InputManagerService, which can be a heavy operation. This is + // especially costly if this is happening on a continuous stream of motion events. + private boolean mPilfering; + /** * Default session constructor. - * @param sessionName The session name that will be applied to the underlying - * {@link InputMonitorCompat}. + * @param inputMonitor Input monitor to track input events. + * @param gestureDetector Gesture detector for detecting gestures. * @param inputEventListener A listener to receive input events. - * @param gestureListener A listener to receive gesture events. + * @param choreographer Choreographer to use with the input receiver. + * @param looper Looper to use with the input receiver * @param pilferOnGestureConsume Whether touch events should be pilfered after a gesture has * been consumed. */ @Inject - public InputSession(@Named(INPUT_SESSION_NAME) String sessionName, + public InputSession( + InputMonitorCompat inputMonitor, + GestureDetector gestureDetector, InputChannelCompat.InputEventListener inputEventListener, - GestureDetector.OnGestureListener gestureListener, - DisplayTracker displayTracker, + Choreographer choreographer, + @Main Looper looper, @Named(PILFER_ON_GESTURE_CONSUME) boolean pilferOnGestureConsume) { - mInputMonitor = new InputMonitorCompat(sessionName, displayTracker.getDefaultDisplayId()); - mGestureDetector = new GestureDetector(gestureListener); + mInputMonitor = inputMonitor; + mGestureDetector = gestureDetector; - mInputEventReceiver = mInputMonitor.getInputReceiver(Looper.getMainLooper(), - Choreographer.getInstance(), + mInputEventReceiver = mInputMonitor.getInputReceiver(looper, choreographer, ev -> { // Process event. Since sometimes input may be a prerequisite for some // gesture logic, process input first. @@ -69,7 +77,9 @@ public class InputSession { if (ev instanceof MotionEvent && mGestureDetector.onTouchEvent((MotionEvent) ev) - && pilferOnGestureConsume) { + && pilferOnGestureConsume + && !(mPilfering && Flags.dreamInputSessionPilferOnce())) { + mPilfering = true; mInputMonitor.pilferPointers(); } }); diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/ShadeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java index e0bf52e81875..9ef9938ab8ad 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/ShadeTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; -import static com.android.systemui.dreams.touch.dagger.ShadeModule.NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT; +import static com.android.systemui.ambient.touch.dagger.ShadeModule.NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT; import android.graphics.Rect; import android.graphics.Region; @@ -35,7 +35,7 @@ import javax.inject.Named; * {@link ShadeTouchHandler} is responsible for handling swipe down gestures over dream * to bring down the shade. */ -public class ShadeTouchHandler implements DreamTouchHandler { +public class ShadeTouchHandler implements TouchHandler { private final Optional<CentralSurfaces> mSurfaces; private final ShadeViewController mShadeViewController; private final int mInitiationHeight; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchHandler.java index 1ec000835ad2..190bc1587525 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; import android.graphics.Rect; import android.graphics.Region; @@ -25,24 +25,30 @@ import com.android.systemui.shared.system.InputChannelCompat; import com.google.common.util.concurrent.ListenableFuture; /** - * The {@link DreamTouchHandler} interface provides a way for dream overlay components to observe + * The {@link TouchHandler} interface provides a way for dream overlay components to observe * touch events and gestures with the ability to intercept the latter. Touch interaction sequences * are abstracted as sessions. A session represents the time of first - * {@code android.view.MotionEvent.ACTION_DOWN} event to the last {@link DreamTouchHandler} + * {@code android.view.MotionEvent.ACTION_DOWN} event to the last {@link TouchHandler} * stopping interception of gestures. If no gesture is intercepted, the session continues - * indefinitely. {@link DreamTouchHandler} have the ability to create a stack of sessions, which + * indefinitely. {@link TouchHandler} have the ability to create a stack of sessions, which * allows for motion logic to be captured in modal states. */ -public interface DreamTouchHandler { +public interface TouchHandler { /** - * A touch session captures the interaction surface of a {@link DreamTouchHandler}. Clients + * A touch session captures the interaction surface of a {@link TouchHandler}. Clients * register listeners as desired to participate in motion/gesture callbacks. */ interface TouchSession { interface Callback { + /** + * Invoked when the session has been removed. + */ void onRemoved(); } + /** + * Registers a callback to be notified when there are updates to the {@link TouchSession}. + */ void registerCallback(Callback callback); /** diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java index 3b22b31de121..e7e12bab745b 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; @@ -37,10 +37,10 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleOwner; +import com.android.systemui.ambient.touch.dagger.InputSessionComponent; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dreams.touch.dagger.InputSessionComponent; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.util.display.DisplayHelper; @@ -58,12 +58,12 @@ import java.util.stream.Collectors; import javax.inject.Inject; /** - * {@link DreamOverlayTouchMonitor} is responsible for monitoring touches and gestures over the + * {@link TouchMonitor} is responsible for monitoring touches and gestures over the * dream overlay and redirecting them to a set of listeners. This monitor is in charge of figuring * out when listeners are eligible for receiving touches and filtering the listener pool if * touches are consumed. */ -public class DreamOverlayTouchMonitor { +public class TouchMonitor { // This executor is used to protect {@code mActiveTouchSessions} from being modified // concurrently. Any operation that adds or removes values should use this executor. public String TAG = "DreamOverlayTouchMonitor"; @@ -83,11 +83,10 @@ public class DreamOverlayTouchMonitor { }; - /** * Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures. */ - private ListenableFuture<DreamTouchHandler.TouchSession> push( + private ListenableFuture<TouchHandler.TouchSession> push( TouchSessionImpl touchSessionImpl) { return CallbackToFutureAdapter.getFuture(completer -> { mMainExecutor.execute(() -> { @@ -110,7 +109,7 @@ public class DreamOverlayTouchMonitor { /** * Removes a {@link TouchSessionImpl} from receiving further updates. */ - private ListenableFuture<DreamTouchHandler.TouchSession> pop( + private ListenableFuture<TouchHandler.TouchSession> pop( TouchSessionImpl touchSessionImpl) { return CallbackToFutureAdapter.getFuture(completer -> { mMainExecutor.execute(() -> { @@ -140,11 +139,11 @@ public class DreamOverlayTouchMonitor { } /** - * {@link TouchSessionImpl} implements {@link DreamTouchHandler.TouchSession} for - * {@link DreamOverlayTouchMonitor}. It enables the monitor to access the associated listeners + * {@link TouchSessionImpl} implements {@link TouchHandler.TouchSession} for + * {@link TouchMonitor}. It enables the monitor to access the associated listeners * and provides the associated client with access to the monitor. */ - private static class TouchSessionImpl implements DreamTouchHandler.TouchSession { + private static class TouchSessionImpl implements TouchHandler.TouchSession { private final HashSet<InputChannelCompat.InputEventListener> mEventListeners = new HashSet<>(); private final HashSet<GestureDetector.OnGestureListener> mGestureListeners = @@ -152,10 +151,10 @@ public class DreamOverlayTouchMonitor { private final HashSet<Callback> mCallbacks = new HashSet<>(); private final TouchSessionImpl mPredecessor; - private final DreamOverlayTouchMonitor mTouchMonitor; + private final TouchMonitor mTouchMonitor; private final Rect mBounds; - TouchSessionImpl(DreamOverlayTouchMonitor touchMonitor, Rect bounds, + TouchSessionImpl(TouchMonitor touchMonitor, Rect bounds, TouchSessionImpl predecessor) { mPredecessor = predecessor; mTouchMonitor = touchMonitor; @@ -179,12 +178,12 @@ public class DreamOverlayTouchMonitor { } @Override - public ListenableFuture<DreamTouchHandler.TouchSession> push() { + public ListenableFuture<TouchHandler.TouchSession> push() { return mTouchMonitor.push(this); } @Override - public ListenableFuture<DreamTouchHandler.TouchSession> pop() { + public ListenableFuture<TouchHandler.TouchSession> pop() { return mTouchMonitor.pop(this); } @@ -275,10 +274,10 @@ public class DreamOverlayTouchMonitor { }); } mCurrentInputSession = mInputSessionFactory.create( - "dreamOverlay", - mInputEventListener, - mOnGestureListener, - true) + "dreamOverlay", + mInputEventListener, + mOnGestureListener, + true) .getInputSession(); } @@ -323,21 +322,21 @@ public class DreamOverlayTouchMonitor { private final HashSet<TouchSessionImpl> mActiveTouchSessions = new HashSet<>(); - private final Collection<DreamTouchHandler> mHandlers; + private final Collection<TouchHandler> mHandlers; private final DisplayHelper mDisplayHelper; private boolean mStopMonitoringPending; private InputChannelCompat.InputEventListener mInputEventListener = new InputChannelCompat.InputEventListener() { - @Override - public void onInputEvent(InputEvent ev) { - // No Active sessions are receiving touches. Create sessions for each listener - if (mActiveTouchSessions.isEmpty()) { - final HashMap<DreamTouchHandler, DreamTouchHandler.TouchSession> sessionMap = - new HashMap<>(); + @Override + public void onInputEvent(InputEvent ev) { + // No Active sessions are receiving touches. Create sessions for each listener + if (mActiveTouchSessions.isEmpty()) { + final HashMap<TouchHandler, TouchHandler.TouchSession> sessionMap = + new HashMap<>(); - for (DreamTouchHandler handler : mHandlers) { + for (TouchHandler handler : mHandlers) { if (!handler.isEnabled()) { continue; } @@ -349,46 +348,49 @@ public class DreamOverlayTouchMonitor { exclusionRect = getCurrentExclusionRect(); } handler.getTouchInitiationRegion( - maxBounds, initiationRegion, exclusionRect); + maxBounds, initiationRegion, exclusionRect); + + if (!initiationRegion.isEmpty()) { + // Initiation regions require a motion event to determine pointer + // location + // within the region. + if (!(ev instanceof MotionEvent)) { + continue; + } + + final MotionEvent motionEvent = (MotionEvent) ev; + + // If the touch event is outside the region, then ignore. + if (!initiationRegion.contains(Math.round(motionEvent.getX()), + Math.round(motionEvent.getY()))) { + continue; + } + } - if (!initiationRegion.isEmpty()) { - // Initiation regions require a motion event to determine pointer location - // within the region. - if (!(ev instanceof MotionEvent)) { - continue; + final TouchSessionImpl sessionStack = new TouchSessionImpl( + TouchMonitor.this, maxBounds, null); + mActiveTouchSessions.add(sessionStack); + sessionMap.put(handler, sessionStack); } - final MotionEvent motionEvent = (MotionEvent) ev; - - // If the touch event is outside the region, then ignore. - if (!initiationRegion.contains(Math.round(motionEvent.getX()), - Math.round(motionEvent.getY()))) { - continue; - } + // Informing handlers of new sessions is delayed until we have all + // created so the + // final session is correct. + sessionMap.forEach((dreamTouchHandler, touchSession) + -> dreamTouchHandler.onSessionStart(touchSession)); } - final TouchSessionImpl sessionStack = new TouchSessionImpl( - DreamOverlayTouchMonitor.this, maxBounds, null); - mActiveTouchSessions.add(sessionStack); - sessionMap.put(handler, sessionStack); + // Find active sessions and invoke on InputEvent. + mActiveTouchSessions.stream() + .map(touchSessionStack -> touchSessionStack.getEventListeners()) + .flatMap(Collection::stream) + .forEach(inputEventListener -> inputEventListener.onInputEvent(ev)); } - // Informing handlers of new sessions is delayed until we have all created so the - // final session is correct. - sessionMap.forEach((dreamTouchHandler, touchSession) - -> dreamTouchHandler.onSessionStart(touchSession)); - } - - // Find active sessions and invoke on InputEvent. - mActiveTouchSessions.stream() - .map(touchSessionStack -> touchSessionStack.getEventListeners()) - .flatMap(Collection::stream) - .forEach(inputEventListener -> inputEventListener.onInputEvent(ev)); - } - private Rect getCurrentExclusionRect() { - return mExclusionRect; - } - }; + private Rect getCurrentExclusionRect() { + return mExclusionRect; + } + }; /** * The {@link Evaluator} interface allows for callers to inspect a listener from the @@ -401,71 +403,75 @@ public class DreamOverlayTouchMonitor { private GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.OnGestureListener() { - private boolean evaluate(Evaluator evaluator) { - final Set<TouchSessionImpl> consumingSessions = new HashSet<>(); - - // When a gesture is consumed, it is assumed that all touches for the current session - // should be directed only to those TouchSessions until those sessions are popped. All - // non-participating sessions are removed from receiving further updates with - // {@link DreamOverlayTouchMonitor#isolate}. - final boolean eventConsumed = mActiveTouchSessions.stream() - .map(touchSession -> { - boolean consume = touchSession.getGestureListeners() - .stream() - .map(listener -> evaluator.evaluate(listener)) - .anyMatch(consumed -> consumed); - - if (consume) { - consumingSessions.add(touchSession); - } - return consume; - }).anyMatch(consumed -> consumed); - - if (eventConsumed) { - DreamOverlayTouchMonitor.this.isolate(consumingSessions); - } + private boolean evaluate(Evaluator evaluator) { + final Set<TouchSessionImpl> consumingSessions = new HashSet<>(); + + // When a gesture is consumed, it is assumed that all touches for the current + // session + // should be directed only to those TouchSessions until those sessions are + // popped. All + // non-participating sessions are removed from receiving further updates with + // {@link DreamOverlayTouchMonitor#isolate}. + final boolean eventConsumed = mActiveTouchSessions.stream() + .map(touchSession -> { + boolean consume = touchSession.getGestureListeners() + .stream() + .map(listener -> evaluator.evaluate(listener)) + .anyMatch(consumed -> consumed); + + if (consume) { + consumingSessions.add(touchSession); + } + return consume; + }).anyMatch(consumed -> consumed); + + if (eventConsumed) { + TouchMonitor.this.isolate(consumingSessions); + } - return eventConsumed; - } + return eventConsumed; + } - // This method is called for gesture events that cannot be consumed. - private void observe(Consumer<GestureDetector.OnGestureListener> consumer) { - mActiveTouchSessions.stream() - .map(touchSession -> touchSession.getGestureListeners()) - .flatMap(Collection::stream) - .forEach(listener -> consumer.accept(listener)); - } + // This method is called for gesture events that cannot be consumed. + private void observe(Consumer<GestureDetector.OnGestureListener> consumer) { + mActiveTouchSessions.stream() + .map(touchSession -> touchSession.getGestureListeners()) + .flatMap(Collection::stream) + .forEach(listener -> consumer.accept(listener)); + } - @Override - public boolean onDown(MotionEvent e) { - return evaluate(listener -> listener.onDown(e)); - } + @Override + public boolean onDown(MotionEvent e) { + return evaluate(listener -> listener.onDown(e)); + } - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - return evaluate(listener -> listener.onFling(e1, e2, velocityX, velocityY)); - } + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, + float velocityY) { + return evaluate(listener -> listener.onFling(e1, e2, velocityX, velocityY)); + } - @Override - public void onLongPress(MotionEvent e) { - observe(listener -> listener.onLongPress(e)); - } + @Override + public void onLongPress(MotionEvent e) { + observe(listener -> listener.onLongPress(e)); + } - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - return evaluate(listener -> listener.onScroll(e1, e2, distanceX, distanceY)); - } + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, + float distanceY) { + return evaluate(listener -> listener.onScroll(e1, e2, distanceX, distanceY)); + } - @Override - public void onShowPress(MotionEvent e) { - observe(listener -> listener.onShowPress(e)); - } + @Override + public void onShowPress(MotionEvent e) { + observe(listener -> listener.onShowPress(e)); + } - @Override - public boolean onSingleTapUp(MotionEvent e) { - return evaluate(listener -> listener.onSingleTapUp(e)); - } - }; + @Override + public boolean onSingleTapUp(MotionEvent e) { + return evaluate(listener -> listener.onSingleTapUp(e)); + } + }; private InputSessionComponent.Factory mInputSessionFactory; private InputSession mCurrentInputSession; @@ -474,25 +480,27 @@ public class DreamOverlayTouchMonitor { /** - * Designated constructor for {@link DreamOverlayTouchMonitor} - * @param executor This executor will be used for maintaining the active listener list to avoid - * concurrent modification. - * @param lifecycle {@link DreamOverlayTouchMonitor} will listen to this lifecycle to determine - * whether touch monitoring should be active. + * Designated constructor for {@link TouchMonitor} + * + * @param executor This executor will be used for maintaining the active listener + * list to avoid + * concurrent modification. + * @param lifecycle {@link TouchMonitor} will listen to this lifecycle to determine + * whether touch monitoring should be active. * @param inputSessionFactory This factory will generate the {@link InputSession} requested by * the monitor. Each session should be unique and valid when * returned. - * @param handlers This set represents the {@link DreamTouchHandler} instances that will - * participate in touch handling. + * @param handlers This set represents the {@link TouchHandler} instances that will + * participate in touch handling. */ @Inject - public DreamOverlayTouchMonitor( + public TouchMonitor( @Main Executor executor, @Background Executor backgroundExecutor, Lifecycle lifecycle, InputSessionComponent.Factory inputSessionFactory, DisplayHelper displayHelper, - Set<DreamTouchHandler> handlers, + Set<TouchHandler> handlers, IWindowManager windowManagerService, @DisplayId int displayId) { mDisplayId = displayId; diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt new file mode 100644 index 000000000000..390e53bb5782 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.ambient.touch.dagger + +import androidx.lifecycle.LifecycleOwner +import com.android.systemui.ambient.dagger.AmbientModule.Companion.TOUCH_HANDLERS +import com.android.systemui.ambient.touch.TouchHandler +import com.android.systemui.ambient.touch.TouchMonitor +import dagger.BindsInstance +import dagger.Subcomponent +import javax.inject.Named + +/** + * {@link AmbientTouchComponent} can be used for setting up a touch environment over the entire + * display surface. This allows for implementing behaviors such as swiping up to bring up the + * bouncer. + */ +@Subcomponent(modules = [AmbientTouchModule::class, ShadeModule::class, BouncerSwipeModule::class]) +interface AmbientTouchComponent { + @Subcomponent.Factory + interface Factory { + fun create( + @BindsInstance lifecycleOwner: LifecycleOwner, + @BindsInstance + @Named(TOUCH_HANDLERS) + touchHandlers: Set<@JvmSuppressWildcards TouchHandler> + ): AmbientTouchComponent + } + + /** Builds a [TouchMonitor] */ + fun getTouchMonitor(): TouchMonitor +} diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchModule.kt new file mode 100644 index 000000000000..a4924d18e0c6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchModule.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.ambient.touch.dagger + +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import com.android.systemui.ambient.dagger.AmbientModule +import com.android.systemui.ambient.touch.TouchHandler +import dagger.Module +import dagger.Provides +import dagger.multibindings.ElementsIntoSet +import javax.inject.Named + +@Module +interface AmbientTouchModule { + companion object { + @JvmStatic + @Provides + fun providesLifecycle(lifecycleOwner: LifecycleOwner): Lifecycle { + return lifecycleOwner.lifecycle + } + + @Provides + @ElementsIntoSet + fun providesDreamTouchHandlers( + @Named(AmbientModule.TOUCH_HANDLERS) + touchHandlers: Set<@JvmSuppressWildcards TouchHandler> + ): Set<@JvmSuppressWildcards TouchHandler> { + return touchHandlers + } + + const val INPUT_SESSION_NAME = "INPUT_SESSION_NAME" + const val PILFER_ON_GESTURE_CONSUME = "PILFER_ON_GESTURE_CONSUME" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/BouncerSwipeModule.java index a5db2ff81f99..dac2d8eaa3d0 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/BouncerSwipeModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,16 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.dagger; +package com.android.systemui.ambient.touch.dagger; import android.animation.ValueAnimator; import android.content.res.Resources; import android.util.TypedValue; import android.view.VelocityTracker; +import com.android.systemui.ambient.touch.BouncerSwipeTouchHandler; +import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dreams.touch.BouncerSwipeTouchHandler; -import com.android.systemui.dreams.touch.DreamTouchHandler; import com.android.systemui.res.R; import com.android.systemui.shade.ShadeViewController; import com.android.wm.shell.animation.FlingAnimationUtils; @@ -66,7 +66,7 @@ public class BouncerSwipeModule { */ @Provides @IntoSet - public static DreamTouchHandler providesBouncerSwipeTouchHandler( + public static TouchHandler providesBouncerSwipeTouchHandler( BouncerSwipeTouchHandler touchHandler) { return touchHandler; } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/InputSessionComponent.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionComponent.java index ad59a2e2b5c3..203fb6430455 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/InputSessionComponent.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionComponent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,32 +14,35 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.dagger; +package com.android.systemui.ambient.touch.dagger; -import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.INPUT_SESSION_NAME; -import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.PILFER_ON_GESTURE_CONSUME; +import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.INPUT_SESSION_NAME; +import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.PILFER_ON_GESTURE_CONSUME; import android.view.GestureDetector; -import com.android.systemui.dreams.touch.InputSession; +import com.android.systemui.ambient.touch.InputSession; import com.android.systemui.shared.system.InputChannelCompat; -import javax.inject.Named; - import dagger.BindsInstance; import dagger.Subcomponent; +import javax.inject.Named; + /** * {@link InputSessionComponent} generates {@link InputSession} with specific instances bound for * the session name and whether touches should be pilfered when consumed. */ -@Subcomponent +@Subcomponent( + modules = { InputSessionModule.class } +) public interface InputSessionComponent { /** * Generates {@link InputSessionComponent}. */ @Subcomponent.Factory interface Factory { + /** */ InputSessionComponent create(@Named(INPUT_SESSION_NAME) @BindsInstance String name, @BindsInstance InputChannelCompat.InputEventListener inputEventListener, @BindsInstance GestureDetector.OnGestureListener gestureListener, diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java new file mode 100644 index 000000000000..99dbdee659ed --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.ambient.touch.dagger; + +import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.INPUT_SESSION_NAME; + +import android.view.GestureDetector; + +import com.android.systemui.settings.DisplayTracker; +import com.android.systemui.shared.system.InputMonitorCompat; + +import dagger.Module; +import dagger.Provides; + +import javax.inject.Named; + + +/** + * Module for providing dependencies to {@link com.android.systemui.dreams.touch.InputSession}. + */ +@Module +public interface InputSessionModule { + /** */ + @Provides + static InputMonitorCompat providesInputMonitorCompat(@Named(INPUT_SESSION_NAME) String name, + DisplayTracker displayTracker) { + return new InputMonitorCompat(name, displayTracker.getDefaultDisplayId()); + } + + /** */ + @Provides + static GestureDetector providesGestureDetector( + android.view.GestureDetector.OnGestureListener gestureListener) { + return new GestureDetector(gestureListener); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/ShadeModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java index 0f08d376f37c..bc2f35467312 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/ShadeModule.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,13 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.dagger; +package com.android.systemui.ambient.touch.dagger; import android.content.res.Resources; +import com.android.systemui.ambient.touch.ShadeTouchHandler; +import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dreams.touch.CommunalTouchHandler; -import com.android.systemui.dreams.touch.DreamTouchHandler; -import com.android.systemui.dreams.touch.ShadeTouchHandler; import com.android.systemui.res.R; import dagger.Binds; @@ -43,23 +42,14 @@ public abstract class ShadeModule { public static final String NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT = "notification_shade_gesture_initiation_height"; - /** Width of swipe gesture edge to show communal hub. */ - public static final String COMMUNAL_GESTURE_INITIATION_WIDTH = - "communal_gesture_initiation_width"; - /** * Provides {@link ShadeTouchHandler} to handle notification swipe down over dream. */ @Binds @IntoSet - public abstract DreamTouchHandler providesNotificationShadeTouchHandler( + public abstract TouchHandler providesNotificationShadeTouchHandler( ShadeTouchHandler touchHandler); - /** Provides {@link CommunalTouchHandler}. */ - @Binds - @IntoSet - public abstract DreamTouchHandler bindCommunalTouchHandler(CommunalTouchHandler touchHandler); - /** * Provides the height of the gesture area for notification swipe down. */ @@ -69,12 +59,4 @@ public abstract class ShadeModule { return resources.getDimensionPixelSize(R.dimen.dream_overlay_status_bar_height); } - /** - * Provides the width of the gesture area for swiping open communal hub. - */ - @Provides - @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) - public static int providesCommunalGestureInitiationWidth(@Main Resources resources) { - return resources.getDimensionPixelSize(R.dimen.communal_gesture_initiation_width); - } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java index 776b7bd080d0..94c998267598 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim; +package com.android.systemui.ambient.touch.scrim; import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimController.java index 01e4d04dcc2c..c453ddb4c5cb 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimController.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim; +package com.android.systemui.ambient.touch.scrim; import android.os.PowerManager; import android.os.SystemClock; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java index 61629ef79637..00543523ec2e 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim; +package com.android.systemui.ambient.touch.scrim; import com.android.systemui.shade.ShadeExpansionChangeEvent; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimManager.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimManager.java index 0d0dff6c8fb0..676221d8b11e 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimManager.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim; +package com.android.systemui.ambient.touch.scrim; -import static com.android.systemui.dreams.touch.scrim.dagger.ScrimModule.BOUNCERLESS_SCRIM_CONTROLLER; -import static com.android.systemui.dreams.touch.scrim.dagger.ScrimModule.BOUNCER_SCRIM_CONTROLLER; +import static com.android.systemui.ambient.touch.scrim.dagger.ScrimModule.BOUNCERLESS_SCRIM_CONTROLLER; +import static com.android.systemui.ambient.touch.scrim.dagger.ScrimModule.BOUNCER_SCRIM_CONTROLLER; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.policy.KeyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/dagger/ScrimModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/dagger/ScrimModule.java index 4ad5161c08aa..b07029bf8ac6 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/dagger/ScrimModule.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/dagger/ScrimModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.scrim.dagger; +package com.android.systemui.ambient.touch.scrim.dagger; -import com.android.systemui.dreams.touch.scrim.BouncerScrimController; -import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController; -import com.android.systemui.dreams.touch.scrim.ScrimController; +import com.android.systemui.ambient.touch.scrim.BouncerScrimController; +import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController; +import com.android.systemui.ambient.touch.scrim.ScrimController; import dagger.Module; import dagger.Provides; diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt index 454ed27161a2..a9f985f0955b 100644 --- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt @@ -36,7 +36,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository import com.android.systemui.user.data.repository.UserRepository import com.android.systemui.util.kotlin.onSubscriberAdded @@ -186,7 +186,6 @@ class AuthenticationRepositoryImpl constructor( @Application private val applicationScope: CoroutineScope, @Background private val backgroundDispatcher: CoroutineDispatcher, - flags: SceneContainerFlags, private val clock: SystemClock, private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>, private val userRepository: UserRepository, @@ -255,7 +254,7 @@ constructor( override val hasLockoutOccurred: StateFlow<Boolean> = _hasLockoutOccurred.asStateFlow() init { - if (flags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { // Hydrate failedAuthenticationAttempts initially and whenever the selected user // changes. applicationScope.launch { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt index 3a45db17b64c..4a60d195ea36 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt @@ -323,7 +323,13 @@ class UdfpsControllerOverlay @JvmOverloads constructor( overlayParams = updatedOverlayParams sensorBounds = updatedOverlayParams.sensorBounds getTouchOverlay()?.let { - windowManager.updateViewLayout(it, coreLayoutParams.updateDimensions(null)) + if (addViewRunnable == null) { + // Only updateViewLayout if there's no pending view to add to WM. + // If there is a pending view, that means the view hasn't been added yet so there's + // no need to update any layouts. Instead the correct params will be used when the + // view is eventually added. + windowManager.updateViewLayout(it, coreLayoutParams.updateDimensions(null)) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt index ec54e4ce5e86..9816896e3ea8 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt @@ -282,7 +282,8 @@ open class UdfpsKeyguardViewControllerLegacy( @VisibleForTesting suspend fun listenForGoneToAodTransition(scope: CoroutineScope): Job { return scope.launch { - transitionInteractor.goneToAodTransition.collect { transitionStep -> + transitionInteractor.transition(KeyguardState.GONE, KeyguardState.AOD).collect { + transitionStep -> view.onDozeAmountChanged( transitionStep.value, transitionStep.value, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt index 7d6721903c37..591da4096956 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt @@ -18,7 +18,6 @@ package com.android.systemui.biometrics.domain.interactor import android.content.Context import android.content.res.Configuration -import android.view.Display import com.android.systemui.biometrics.data.repository.DisplayStateRepository import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging @@ -28,7 +27,6 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.unfold.compat.ScreenSizeFoldProvider import com.android.systemui.unfold.updates.FoldProvider -import com.android.systemui.util.kotlin.sample import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -36,8 +34,6 @@ import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** Aggregates display state information. */ @@ -129,16 +125,7 @@ constructor( screenSizeFoldProvider.onConfigurationChange(newConfig) } - private val defaultDisplay = - displayRepository.displays.map { displays -> - displays.firstOrNull { it.displayId == Display.DEFAULT_DISPLAY } - } - - override val isDefaultDisplayOff = - displayRepository.displayChangeEvent - .filter { it == Display.DEFAULT_DISPLAY } - .sample(defaultDisplay) - .map { it?.state == Display.STATE_OFF } + override val isDefaultDisplayOff = displayRepository.defaultDisplayOff override val isLargeScreen: Flow<Boolean> = displayStateRepository.isLargeScreen diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt index 83b3380ae6be..1eef91debab3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt @@ -27,7 +27,8 @@ import com.android.systemui.biometrics.udfps.TouchProcessorResult.ProcessedTouch import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject -private val SUPPORTED_ROTATIONS = setOf(Surface.ROTATION_90, Surface.ROTATION_270) +private val SUPPORTED_ROTATIONS = + setOf(Surface.ROTATION_90, Surface.ROTATION_270, Surface.ROTATION_180) /** * TODO(b/259140693): Consider using an object pool of TouchProcessorResult to avoid allocations. diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt index 76d46ed9889f..072fe47df42b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt @@ -463,6 +463,23 @@ object BiometricViewBinder { } } } + + // Retry and confirmation when finger on sensor + launch { + combine( + viewModel.canTryAgainNow, + viewModel.hasFingerOnSensor, + viewModel.isPendingConfirmation, + ::Triple + ) + .collect { (canRetry, fingerAcquired, pendingConfirmation) -> + if (canRetry && fingerAcquired) { + legacyCallback.onButtonTryAgain() + } else if (pendingConfirmation && fingerAcquired) { + viewModel.confirmAuthenticated() + } + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt index 66b7d7afb8c4..d9d3715f0a30 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt @@ -26,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.airbnb.lottie.LottieAnimationView +import com.airbnb.lottie.LottieOnCompositionLoadedListener import com.android.settingslib.widget.LottieColorUtils import com.android.systemui.Flags.constraintBp import com.android.systemui.biometrics.ui.viewmodel.PromptIconViewModel @@ -77,6 +78,8 @@ object PromptIconViewBinder { } launch { + var lottieOnCompositionLoadedListener: LottieOnCompositionLoadedListener? = null + combine(viewModel.activeAuthType, viewModel.iconSize, ::Pair).collect { (activeAuthType, iconSize) -> // Every time after bp shows, [isIconViewLoaded] is set to false in @@ -94,10 +97,18 @@ object PromptIconViewBinder { * TODO(b/288175072): May be able to remove this once constraint * layout is implemented */ - iconView.removeAllLottieOnCompositionLoadedListener() - iconView.addLottieOnCompositionLoadedListener { - promptViewModel.setIsIconViewLoaded(true) + if (lottieOnCompositionLoadedListener != null) { + iconView.removeLottieOnCompositionLoadedListener( + lottieOnCompositionLoadedListener!! + ) } + lottieOnCompositionLoadedListener = + LottieOnCompositionLoadedListener { + promptViewModel.setIsIconViewLoaded(true) + } + iconView.addLottieOnCompositionLoadedListener( + lottieOnCompositionLoadedListener!! + ) } AuthType.Face -> { /** diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt index 21ebff4d0b71..4e9acbd25b62 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt @@ -22,6 +22,7 @@ import android.content.pm.PackageManager import android.graphics.Rect import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.hardware.biometrics.BiometricFingerprintConstants import android.hardware.biometrics.BiometricPrompt import android.hardware.biometrics.Flags.customBiometricPrompt import android.hardware.biometrics.PromptContentView @@ -32,6 +33,7 @@ import com.android.systemui.Flags.bpTalkback import com.android.systemui.Flags.constraintBp import com.android.systemui.biometrics.UdfpsUtils import com.android.systemui.biometrics.Utils +import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor @@ -40,6 +42,7 @@ import com.android.systemui.biometrics.shared.model.BiometricModality import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.biometrics.shared.model.PromptKind import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus import com.android.systemui.res.R import javax.inject.Inject import kotlinx.coroutines.Job @@ -66,6 +69,7 @@ constructor( promptSelectorInteractor: PromptSelectorInteractor, @Application private val context: Context, private val udfpsOverlayInteractor: UdfpsOverlayInteractor, + private val biometricStatusInteractor: BiometricStatusInteractor, private val udfpsUtils: UdfpsUtils ) { /** The set of modalities available for this prompt */ @@ -185,6 +189,24 @@ constructor( /** Fingerprint sensor state. */ val fingerprintStartMode: Flow<FingerprintStartMode> = _fingerprintStartMode.asStateFlow() + /** Whether a finger has been acquired by the sensor */ + // TODO(b/331948073): Add support for detecting SFPS finger without authentication running + val hasFingerBeenAcquired: Flow<Boolean> = + combine(biometricStatusInteractor.fingerprintAcquiredStatus, modalities) { + status, + modalities -> + modalities.hasSfps && + status is AcquiredFingerprintAuthenticationStatus && + status.acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START + } + .distinctUntilChanged() + + /** Whether there is currently a finger on the sensor */ + val hasFingerOnSensor: Flow<Boolean> = + combine(hasFingerBeenAcquired, _isOverlayTouched) { hasFingerBeenAcquired, overlayTouched -> + hasFingerBeenAcquired || overlayTouched + } + private val _forceLargeSize = MutableStateFlow(false) private val _forceMediumSize = MutableStateFlow(false) diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java index 161458fdb33e..a90e60d2a8a3 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java @@ -56,4 +56,22 @@ public class BroadcastDialogController { broadcastDialog.show(); } } + + /** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device + * + * @param currentBroadcastAppName Indicates the APP name currently broadcasting + * @param outputPkgName Indicates the output media package name to be switched + * @param controller Indicates the dialog controller of the source view. + */ + public void createBroadcastDialogWithController( + String currentBroadcastAppName, String outputPkgName, + DialogTransitionAnimator.Controller controller) { + SystemUIDialog broadcastDialog = mBroadcastDialogFactory.create( + currentBroadcastAppName, outputPkgName).createDialog(); + if (controller != null) { + mDialogTransitionAnimator.show(broadcastDialog, controller); + } else { + broadcastDialog.show(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java index 66aeda63e222..207f7dbb5816 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java @@ -217,10 +217,13 @@ public class BroadcastDialogDelegate implements SystemUIDialog.Delegate { mSwitchBroadcast.setText(mContext.getString( R.string.bt_le_audio_broadcast_dialog_switch_app, switchBroadcastApp), null); mSwitchBroadcast.setOnClickListener((view) -> startSwitchBroadcast()); - changeOutput.setOnClickListener((view) -> { - mMediaOutputDialogManager.createAndShow(mOutputPackageName, true, null); - dialog.dismiss(); - }); + changeOutput.setOnClickListener( + (view) -> { + // TODO: b/321969740 - Take the userHandle as a parameter and pass it through. + // The package name is not sufficient to unambiguously identify an app. + mMediaOutputDialogManager.createAndShow(mOutputPackageName, true, null, null); + dialog.dismiss(); + }); cancelBtn.setOnClickListener((view) -> { if (DEBUG) { Log.d(TAG, "BroadcastDialog dismiss."); diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt new file mode 100644 index 000000000000..e44f0543fc87 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2023 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.systemui.bluetooth.qsdialog + +import androidx.annotation.StringRes +import com.android.settingslib.bluetooth.BluetoothUtils +import com.android.settingslib.bluetooth.LocalBluetoothManager +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.res.R +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.stateIn + +internal sealed class AudioSharingButtonState { + object Gone : AudioSharingButtonState() + data class Visible(@StringRes val resId: Int) : AudioSharingButtonState() +} + +/** Holds business logic for the audio sharing state. */ +@SysUISingleton +internal class AudioSharingInteractor +@Inject +constructor( + private val localBluetoothManager: LocalBluetoothManager?, + bluetoothStateInteractor: BluetoothStateInteractor, + deviceItemInteractor: DeviceItemInteractor, + @Application private val coroutineScope: CoroutineScope, + @Background private val backgroundDispatcher: CoroutineDispatcher, +) { + /** Flow representing the update of AudioSharingButtonState. */ + internal val audioSharingButtonStateUpdate: Flow<AudioSharingButtonState> = + combine( + bluetoothStateInteractor.bluetoothStateUpdate, + deviceItemInteractor.deviceItemUpdate + ) { bluetoothState, deviceItem -> + getButtonState(bluetoothState, deviceItem) + } + .flowOn(backgroundDispatcher) + .stateIn( + coroutineScope, + SharingStarted.WhileSubscribed(replayExpirationMillis = 0), + initialValue = AudioSharingButtonState.Gone + ) + + private fun getButtonState( + bluetoothState: Boolean, + deviceItem: List<DeviceItem> + ): AudioSharingButtonState { + return when { + // Don't show button when bluetooth is off + !bluetoothState -> AudioSharingButtonState.Gone + // Show sharing audio when broadcasting + BluetoothUtils.isBroadcasting(localBluetoothManager) -> + AudioSharingButtonState.Visible( + R.string.quick_settings_bluetooth_audio_sharing_button_sharing + ) + // When not broadcasting, don't show button if there's connected source in any device + deviceItem.any { + BluetoothUtils.hasConnectedBroadcastSource( + it.cachedBluetoothDevice, + localBluetoothManager + ) + } -> AudioSharingButtonState.Gone + // Show audio sharing when there's a connected LE audio device + deviceItem.any { BluetoothUtils.isActiveLeAudioDevice(it.cachedBluetoothDevice) } -> + AudioSharingButtonState.Visible( + R.string.quick_settings_bluetooth_audio_sharing_button + ) + else -> AudioSharingButtonState.Gone + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt index 94d7af74f1dd..17f9e634ec62 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt @@ -25,12 +25,17 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.withContext /** Holds business logic for the Bluetooth Dialog's bluetooth and device connection state */ @SysUISingleton @@ -40,9 +45,10 @@ constructor( private val localBluetoothManager: LocalBluetoothManager?, private val logger: BluetoothTileDialogLogger, @Application private val coroutineScope: CoroutineScope, + @Background private val backgroundDispatcher: CoroutineDispatcher, ) { - internal val bluetoothStateUpdate: StateFlow<Boolean?> = + internal val bluetoothStateUpdate: StateFlow<Boolean> = conflatedCallbackFlow { val listener = object : BluetoothCallback { @@ -64,16 +70,22 @@ constructor( localBluetoothManager?.eventManager?.registerCallback(listener) awaitClose { localBluetoothManager?.eventManager?.unregisterCallback(listener) } } + .onStart { emit(isBluetoothEnabled()) } + .flowOn(backgroundDispatcher) .stateIn( coroutineScope, SharingStarted.WhileSubscribed(replayExpirationMillis = 0), - initialValue = null + initialValue = false ) - internal var isBluetoothEnabled: Boolean - get() = localBluetoothManager?.bluetoothAdapter?.isEnabled == true - set(value) { - if (isBluetoothEnabled != value) { + suspend fun isBluetoothEnabled(): Boolean = + withContext(backgroundDispatcher) { + localBluetoothManager?.bluetoothAdapter?.isEnabled == true + } + + suspend fun setBluetoothEnabled(value: Boolean) { + withContext(backgroundDispatcher) { + if (isBluetoothEnabled() != value) { localBluetoothManager?.bluetoothAdapter?.apply { if (value) enable() else disable() logger.logBluetoothState( @@ -83,6 +95,7 @@ constructor( } } } + } companion object { private const val TAG = "BtStateInteractor" diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt index c7d171d5b804..dd8c0df387dc 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt @@ -27,6 +27,7 @@ import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.accessibility.AccessibilityNodeInfo import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction +import android.widget.Button import android.widget.ImageView import android.widget.ProgressBar import android.widget.Switch @@ -59,7 +60,6 @@ class BluetoothTileDialogDelegate internal constructor( @Assisted private val initialUiProperties: BluetoothTileDialogViewModel.UiProperties, @Assisted private val cachedContentHeight: Int, - @Assisted private val bluetoothToggleInitialValue: Boolean, @Assisted private val bluetoothTileDialogCallback: BluetoothTileDialogCallback, @Assisted private val dismissListener: Runnable, @Main private val mainDispatcher: CoroutineDispatcher, @@ -69,8 +69,7 @@ internal constructor( private val systemuiDialogFactory: SystemUIDialog.Factory, ) : SystemUIDialog.Delegate { - private val mutableBluetoothStateToggle: MutableStateFlow<Boolean> = - MutableStateFlow(bluetoothToggleInitialValue) + private val mutableBluetoothStateToggle: MutableStateFlow<Boolean?> = MutableStateFlow(null) internal val bluetoothStateToggle get() = mutableBluetoothStateToggle.asStateFlow() @@ -99,7 +98,6 @@ internal constructor( fun create( initialUiProperties: BluetoothTileDialogViewModel.UiProperties, cachedContentHeight: Int, - bluetoothEnabled: Boolean, dialogCallback: BluetoothTileDialogCallback, dimissListener: Runnable ): BluetoothTileDialogDelegate @@ -130,6 +128,9 @@ internal constructor( getPairNewDeviceButton(dialog).setOnClickListener { bluetoothTileDialogCallback.onPairNewDeviceClicked(it) } + getAudioSharingButtonView(dialog).setOnClickListener { + bluetoothTileDialogCallback.onAudioSharingButtonClicked(it) + } getScrollViewContent(dialog).apply { minimumHeight = resources.getDimensionPixelSize(initialUiProperties.scrollViewMinHeightResId) @@ -211,9 +212,19 @@ internal constructor( getAutoOnToggleInfoTextView(dialog).text = dialog.context.getString(infoResId) } + internal fun onAudioSharingButtonUpdated( + dialog: SystemUIDialog, + visibility: Int, + label: String? + ) { + getAudioSharingButtonView(dialog).apply { + this.visibility = visibility + label?.let { text = it } + } + } + private fun setupToggle(dialog: SystemUIDialog) { val toggleView = getToggleView(dialog) - toggleView.isChecked = bluetoothToggleInitialValue toggleView.setOnCheckedChangeListener { view, isChecked -> mutableBluetoothStateToggle.value = isChecked view.apply { @@ -259,6 +270,10 @@ internal constructor( return dialog.requireViewById(R.id.bluetooth_auto_on_toggle) } + private fun getAudioSharingButtonView(dialog: SystemUIDialog): Button { + return dialog.requireViewById(R.id.audio_sharing_button) + } + private fun getAutoOnToggleView(dialog: SystemUIDialog): View { return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_layout) } @@ -412,6 +427,8 @@ internal constructor( const val ACTION_PREVIOUSLY_CONNECTED_DEVICE = "com.android.settings.PREVIOUSLY_CONNECTED_DEVICE" const val ACTION_PAIR_NEW_DEVICE = "android.settings.BLUETOOTH_PAIRING_SETTINGS" + const val ACTION_AUDIO_SHARING = + "com.google.android.settings.BLUETOOTH_AUDIO_SHARING_SETTINGS" const val DISABLED_ALPHA = 0.3f const val ENABLED_ALPHA = 1f const val PROGRESS_BAR_ANIMATION_DURATION_MS = 1500L diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.kt index add1647143d8..b592b8ed4332 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.kt @@ -30,9 +30,12 @@ enum class BluetoothTileDialogUiEvent(val metricId: Int) : UiEventLogger.UiEvent @UiEvent(doc = "Connected device clicked to active") CONNECTED_DEVICE_SET_ACTIVE(1499), @UiEvent(doc = "Saved clicked to connect") SAVED_DEVICE_CONNECT(1500), @UiEvent(doc = "Active device clicked to disconnect") ACTIVE_DEVICE_DISCONNECT(1507), + @UiEvent(doc = "Audio sharing device clicked, do nothing") AUDIO_SHARING_DEVICE_CLICKED(1699), @UiEvent(doc = "Connected other device clicked to disconnect") CONNECTED_OTHER_DEVICE_DISCONNECT(1508), - @UiEvent(doc = "The auto on toggle is clicked") BLUETOOTH_AUTO_ON_TOGGLE_CLICKED(1617); + @UiEvent(doc = "The auto on toggle is clicked") BLUETOOTH_AUTO_ON_TOGGLE_CLICKED(1617), + @UiEvent(doc = "The audio sharing button is clicked") + BLUETOOTH_AUDIO_SHARING_BUTTON_CLICKED(1700); override fun getId() = metricId } diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt index e65b65710f94..eb919e3ca36b 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt @@ -28,9 +28,11 @@ import androidx.annotation.StringRes import androidx.annotation.VisibleForTesting import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.UiEventLogger +import com.android.settingslib.bluetooth.BluetoothUtils import com.android.systemui.Prefs import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogTransitionAnimator +import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_AUDIO_SHARING import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE @@ -61,6 +63,7 @@ constructor( private val deviceItemInteractor: DeviceItemInteractor, private val bluetoothStateInteractor: BluetoothStateInteractor, private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor, + private val audioSharingInteractor: AudioSharingInteractor, private val dialogTransitionAnimator: DialogTransitionAnimator, private val activityStarter: ActivityStarter, private val uiEventLogger: UiEventLogger, @@ -119,7 +122,8 @@ constructor( dialog, it.take(MAX_DEVICE_ITEM_ENTRY), showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY, - showPairNewDevice = bluetoothStateInteractor.isBluetoothEnabled + showPairNewDevice = + bluetoothStateInteractor.isBluetoothEnabled() ) animateProgressBar(dialog, false) } @@ -142,10 +146,25 @@ constructor( } .launchIn(this) + if (BluetoothUtils.isAudioSharingEnabled()) { + audioSharingInteractor.audioSharingButtonStateUpdate + .onEach { + if (it is AudioSharingButtonState.Visible) { + dialogDelegate.onAudioSharingButtonUpdated( + dialog, + VISIBLE, + context.getString(it.resId) + ) + } else { + dialogDelegate.onAudioSharingButtonUpdated(dialog, GONE, null) + } + } + .launchIn(this) + } + // bluetoothStateUpdate is emitted when bluetooth on/off state is changed, re-fetch // the device item list. bluetoothStateInteractor.bluetoothStateUpdate - .filterNotNull() .onEach { dialogDelegate.onBluetoothStateUpdated( dialog, @@ -165,9 +184,10 @@ constructor( // bluetoothStateToggle is emitted when user toggles the bluetooth state switch, // send the new value to the bluetoothStateInteractor and animate the progress bar. dialogDelegate.bluetoothStateToggle + .filterNotNull() .onEach { dialogDelegate.animateProgressBar(dialog, true) - bluetoothStateInteractor.isBluetoothEnabled = it + bluetoothStateInteractor.setBluetoothEnabled(it) } .launchIn(this) @@ -222,11 +242,10 @@ constructor( return bluetoothDialogDelegateFactory.create( UiProperties.build( - bluetoothStateInteractor.isBluetoothEnabled, + bluetoothStateInteractor.isBluetoothEnabled(), isAutoOnToggleFeatureAvailable() ), cachedContentHeight, - bluetoothStateInteractor.isBluetoothEnabled, this@BluetoothTileDialogViewModel, { cancelJob() } ) @@ -256,6 +275,11 @@ constructor( startSettingsActivity(Intent(ACTION_PAIR_NEW_DEVICE), view) } + override fun onAudioSharingButtonClicked(view: View) { + uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_AUDIO_SHARING_BUTTON_CLICKED) + startSettingsActivity(Intent(ACTION_AUDIO_SHARING), view) + } + private fun cancelJob() { job?.cancel() job = null @@ -312,4 +336,5 @@ interface BluetoothTileDialogCallback { fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View) fun onSeeAllClicked(view: View) fun onPairNewDeviceClicked(view: View) + fun onAudioSharingButtonClicked(view: View) } diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt index dc5efefdfb16..0ea98d14bca3 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt @@ -37,6 +37,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice enum class DeviceItemType { ACTIVE_MEDIA_BLUETOOTH_DEVICE, + AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE, AVAILABLE_MEDIA_BLUETOOTH_DEVICE, CONNECTED_BLUETOOTH_DEVICE, SAVED_BLUETOOTH_DEVICE, diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt index f04ba75ca3ef..49d0847ab0c7 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt @@ -21,13 +21,16 @@ import android.content.Context import android.media.AudioManager import com.android.settingslib.bluetooth.BluetoothUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice +import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.settingslib.flags.Flags +import com.android.settingslib.flags.Flags.enableLeAudioSharing import com.android.systemui.res.R private val backgroundOn = R.drawable.settingslib_switch_bar_bg_on private val backgroundOff = R.drawable.bluetooth_tile_dialog_bg_off private val backgroundOffBusy = R.drawable.bluetooth_tile_dialog_bg_off_busy private val connected = R.string.quick_settings_bluetooth_device_connected +private val audioSharing = R.string.quick_settings_bluetooth_device_audio_sharing private val saved = R.string.quick_settings_bluetooth_device_saved private val actionAccessibilityLabelActivate = R.string.accessibility_quick_settings_bluetooth_device_tap_to_activate @@ -39,35 +42,81 @@ internal abstract class DeviceItemFactory { abstract fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager, ): Boolean abstract fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem + + companion object { + @JvmStatic + fun createDeviceItem( + context: Context, + cachedDevice: CachedBluetoothDevice, + type: DeviceItemType, + connectionSummary: String, + background: Int, + actionAccessibilityLabel: String + ): DeviceItem { + return DeviceItem( + type = type, + cachedBluetoothDevice = cachedDevice, + deviceName = cachedDevice.name, + connectionSummary = connectionSummary, + iconWithDescription = + BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { + Pair(it.first, it.second) + }, + background = background, + isEnabled = !cachedDevice.isBusy, + actionAccessibilityLabel = actionAccessibilityLabel + ) + } + } } internal open class ActiveMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return BluetoothUtils.isActiveMediaDevice(cachedDevice) && BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager) } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { - return DeviceItem( - type = DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE, - cachedBluetoothDevice = cachedDevice, - deviceName = cachedDevice.name, - connectionSummary = cachedDevice.connectionSummary ?: "", - iconWithDescription = - BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p -> - Pair(p.first, p.second) - }, - background = backgroundOn, - isEnabled = !cachedDevice.isBusy, - actionAccessibilityLabel = context.getString(actionAccessibilityLabelDisconnect), + return createDeviceItem( + context, + cachedDevice, + DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE, + cachedDevice.connectionSummary ?: "", + backgroundOn, + context.getString(actionAccessibilityLabelDisconnect) + ) + } +} + +internal class AudioSharingMediaDeviceItemFactory( + private val localBluetoothManager: LocalBluetoothManager? +) : DeviceItemFactory() { + override fun isFilterMatched( + context: Context, + cachedDevice: CachedBluetoothDevice, + audioManager: AudioManager + ): Boolean { + return enableLeAudioSharing() && + BluetoothUtils.hasConnectedBroadcastSource(cachedDevice, localBluetoothManager) + } + + override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { + return createDeviceItem( + context, + cachedDevice, + DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE, + cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } + ?: context.getString(audioSharing), + if (cachedDevice.isBusy) backgroundOffBusy else backgroundOn, + "" ) } } @@ -76,7 +125,7 @@ internal class ActiveHearingDeviceItemFactory : ActiveMediaDeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return BluetoothUtils.isActiveMediaDevice(cachedDevice) && BluetoothUtils.isAvailableHearingDevice(cachedDevice) @@ -87,27 +136,21 @@ internal open class AvailableMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return !BluetoothUtils.isActiveMediaDevice(cachedDevice) && BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager) } - // TODO(b/298124674): move create() to the abstract class to reduce duplicate code override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { - return DeviceItem( - type = DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE, - cachedBluetoothDevice = cachedDevice, - deviceName = cachedDevice.name, - connectionSummary = cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } - ?: context.getString(connected), - iconWithDescription = - BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p -> - Pair(p.first, p.second) - }, - background = if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff, - isEnabled = !cachedDevice.isBusy, - actionAccessibilityLabel = context.getString(actionAccessibilityLabelActivate), + return createDeviceItem( + context, + cachedDevice, + DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE, + cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } + ?: context.getString(connected), + if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff, + context.getString(actionAccessibilityLabelActivate) ) } } @@ -116,7 +159,7 @@ internal class AvailableHearingDeviceItemFactory : ActiveMediaDeviceItemFactory( override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return !BluetoothUtils.isActiveMediaDevice(cachedDevice) && BluetoothUtils.isAvailableHearingDevice(cachedDevice) @@ -127,32 +170,25 @@ internal class ConnectedDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { - !BluetoothUtils.isExclusivelyManagedBluetoothDevice( - context, - cachedDevice.getDevice() - ) && BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) + !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) && + BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) } else { BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) } } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { - return DeviceItem( - type = DeviceItemType.CONNECTED_BLUETOOTH_DEVICE, - cachedBluetoothDevice = cachedDevice, - deviceName = cachedDevice.name, - connectionSummary = cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } - ?: context.getString(connected), - iconWithDescription = - BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p -> - Pair(p.first, p.second) - }, - background = if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff, - isEnabled = !cachedDevice.isBusy, - actionAccessibilityLabel = context.getString(actionAccessibilityLabelDisconnect), + return createDeviceItem( + context, + cachedDevice, + DeviceItemType.CONNECTED_BLUETOOTH_DEVICE, + cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } + ?: context.getString(connected), + if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff, + context.getString(actionAccessibilityLabelDisconnect) ) } } @@ -161,32 +197,26 @@ internal open class SavedDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { - !BluetoothUtils.isExclusivelyManagedBluetoothDevice( - context, - cachedDevice.getDevice() - ) && cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected + !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) && + cachedDevice.bondState == BluetoothDevice.BOND_BONDED && + !cachedDevice.isConnected } else { cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected } } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { - return DeviceItem( - type = DeviceItemType.SAVED_BLUETOOTH_DEVICE, - cachedBluetoothDevice = cachedDevice, - deviceName = cachedDevice.name, - connectionSummary = cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } - ?: context.getString(saved), - iconWithDescription = - BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p -> - Pair(p.first, p.second) - }, - background = if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff, - isEnabled = !cachedDevice.isBusy, - actionAccessibilityLabel = context.getString(actionAccessibilityLabelActivate), + return createDeviceItem( + context, + cachedDevice, + DeviceItemType.SAVED_BLUETOOTH_DEVICE, + cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() } + ?: context.getString(saved), + if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff, + context.getString(actionAccessibilityLabelActivate) ) } } @@ -195,7 +225,7 @@ internal class SavedHearingDeviceItemFactory : SavedDeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ): Boolean { return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { !BluetoothUtils.isExclusivelyManagedBluetoothDevice( diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt index 4e28cafb5004..66e593b94b21 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt @@ -113,6 +113,7 @@ constructor( private var deviceItemFactoryList: List<DeviceItemFactory> = listOf( ActiveMediaDeviceItemFactory(), + AudioSharingMediaDeviceItemFactory(localBluetoothManager), AvailableMediaDeviceItemFactory(), ConnectedDeviceItemFactory(), SavedDeviceItemFactory() @@ -121,6 +122,7 @@ constructor( private var displayPriority: List<DeviceItemType> = listOf( DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE, + DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE, DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE, DeviceItemType.SAVED_BLUETOOTH_DEVICE, @@ -177,6 +179,9 @@ constructor( disconnect() uiEventLogger.log(BluetoothTileDialogUiEvent.ACTIVE_DEVICE_DISCONNECT) } + DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE -> { + uiEventLogger.log(BluetoothTileDialogUiEvent.AUDIO_SHARING_DEVICE_CLICKED) + } DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> { setActive() uiEventLogger.log(BluetoothTileDialogUiEvent.CONNECTED_DEVICE_SET_ACTIVE) diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt index 7525ce0f98ac..fa19bf478453 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt @@ -27,9 +27,9 @@ import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState -import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.kotlin.BooleanFlowOperators.or import com.android.systemui.util.time.SystemClock import dagger.Lazy import javax.inject.Inject @@ -78,15 +78,14 @@ constructor( bouncerRepository.alternateBouncerUIAvailable } private val isDozingOrAod: Flow<Boolean> = - keyguardTransitionInteractor - .get() - .transitions - .map { - it.to == KeyguardState.DOZING || - it.to == KeyguardState.AOD || - ((it.from == KeyguardState.DOZING || it.from == KeyguardState.AOD) && - it.transitionState != TransitionState.FINISHED) - } + or( + keyguardTransitionInteractor.get().transitionValue(KeyguardState.DOZING).map { + it > 0f + }, + keyguardTransitionInteractor.get().transitionValue(KeyguardState.AOD).map { + it > 0f + }, + ) .distinctUntilChanged() /** diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt index aeb564d53195..dd71bc782c1c 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt @@ -16,16 +16,26 @@ package com.android.systemui.bouncer.domain.interactor +import android.app.StatusBarManager.SESSION_KEYGUARD +import com.android.compose.animation.scene.SceneKey +import com.android.internal.logging.UiEventLogger import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor import com.android.systemui.authentication.domain.interactor.AuthenticationResult +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Password +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Pattern +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Pin import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Sim import com.android.systemui.bouncer.data.repository.BouncerRepository +import com.android.systemui.bouncer.shared.logging.BouncerUiEvent import com.android.systemui.classifier.FalsingClassifier import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor +import com.android.systemui.log.SessionTracker import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.model.Scenes import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async @@ -47,6 +57,9 @@ constructor( private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor, private val falsingInteractor: FalsingInteractor, private val powerInteractor: PowerInteractor, + private val uiEventLogger: UiEventLogger, + private val sessionTracker: SessionTracker, + sceneInteractor: SceneInteractor, ) { private val _onIncorrectBouncerInput = MutableSharedFlow<Unit>() val onIncorrectBouncerInput: SharedFlow<Unit> = _onIncorrectBouncerInput @@ -80,6 +93,10 @@ constructor( } .map {} + /** The scene to show when bouncer is dismissed. */ + val dismissDestination: Flow<SceneKey> = + sceneInteractor.previousScene.map { it ?: Scenes.Lockscreen } + /** Notifies that the user has places down a pointer, not necessarily dragging just yet. */ fun onDown() { falsingInteractor.avoidGesture() @@ -154,6 +171,18 @@ constructor( ) { _onIncorrectBouncerInput.emit(Unit) } + + if (authenticationInteractor.getAuthenticationMethod() in setOf(Pin, Password, Pattern)) { + if (authResult == AuthenticationResult.SUCCEEDED) { + uiEventLogger.log(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS) + } else if (authResult == AuthenticationResult.FAILED) { + uiEventLogger.log( + BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, + sessionTracker.getSessionId(SESSION_KEYGUARD) + ) + } + } + return authResult } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt index e789475b7877..62ef365345b7 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt @@ -18,7 +18,7 @@ package com.android.systemui.bouncer.shared.flag import com.android.systemui.Flags import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import dagger.Module import dagger.Provides @@ -42,11 +42,10 @@ interface ComposeBouncerFlags { fun isOnlyComposeBouncerEnabled(): Boolean } -class ComposeBouncerFlagsImpl(private val sceneContainerFlags: SceneContainerFlags) : - ComposeBouncerFlags { +class ComposeBouncerFlagsImpl() : ComposeBouncerFlags { override fun isComposeBouncerOrSceneContainerEnabled(): Boolean { - return sceneContainerFlags.isEnabled() || Flags.composeBouncer() + return SceneContainerFlag.isEnabled || Flags.composeBouncer() } @Deprecated( @@ -55,7 +54,7 @@ class ComposeBouncerFlagsImpl(private val sceneContainerFlags: SceneContainerFla replaceWith = ReplaceWith("isComposeBouncerOrSceneContainerEnabled()") ) override fun isOnlyComposeBouncerEnabled(): Boolean { - return !sceneContainerFlags.isEnabled() && Flags.composeBouncer() + return !SceneContainerFlag.isEnabled && Flags.composeBouncer() } } @@ -63,7 +62,7 @@ class ComposeBouncerFlagsImpl(private val sceneContainerFlags: SceneContainerFla object ComposeBouncerFlagsModule { @Provides @SysUISingleton - fun impl(sceneContainerFlags: SceneContainerFlags): ComposeBouncerFlags { - return ComposeBouncerFlagsImpl(sceneContainerFlags) + fun impl(): ComposeBouncerFlags { + return ComposeBouncerFlagsImpl() } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/logging/BouncerUiEvent.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/logging/BouncerUiEvent.kt new file mode 100644 index 000000000000..3be54992f918 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/logging/BouncerUiEvent.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bouncer.shared.logging + +import com.android.internal.logging.UiEvent +import com.android.internal.logging.UiEventLogger + +/** + * Legacy bouncer UI events {@link com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent}. + * Only contains that used by metrics. + */ +enum class BouncerUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum { + @UiEvent(doc = "Bouncer is dismissed using extended security access.") + BOUNCER_DISMISS_EXTENDED_ACCESS(413), + + // PASSWORD here includes password, pattern, and pin. + @UiEvent(doc = "Bouncer is successfully unlocked using password.") + BOUNCER_PASSWORD_SUCCESS(418), + @UiEvent(doc = "An attempt to unlock bouncer using password has failed.") + BOUNCER_PASSWORD_FAILURE(419); + + override fun getId() = _id +} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt index 5c07cc57c620..7c41b75d7105 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt @@ -21,6 +21,12 @@ import android.app.admin.DevicePolicyResources import android.content.Context import android.graphics.Bitmap import androidx.core.graphics.drawable.toBitmap +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.SwipeDirection +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationWipeModel @@ -35,6 +41,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.inputmethod.domain.interactor.InputMethodInteractor +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.user.ui.viewmodel.UserActionViewModel import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel @@ -82,6 +89,15 @@ class BouncerViewModel( initialValue = null, ) + val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> = + bouncerInteractor.dismissDestination + .map(::destinationSceneMap) + .stateIn( + applicationScope, + SharingStarted.WhileSubscribed(), + initialValue = destinationSceneMap(Scenes.Lockscreen), + ) + val message: BouncerMessageViewModel = bouncerMessageViewModel val userSwitcherDropdown: StateFlow<List<UserSwitcherDropdownItemViewModel>> = @@ -310,8 +326,7 @@ class BouncerViewModel( { message }, failedAttempts, remainingAttempts, - ) - ?: message + ) ?: message } else { message } @@ -328,8 +343,7 @@ class BouncerViewModel( .KEYGUARD_DIALOG_FAILED_ATTEMPTS_ERASING_PROFILE, { message }, failedAttempts, - ) - ?: message + ) ?: message } else { message } @@ -357,6 +371,12 @@ class BouncerViewModel( } } + private fun destinationSceneMap(prevScene: SceneKey) = + mapOf( + Back to UserActionResult(prevScene), + Swipe(SwipeDirection.Down) to UserActionResult(prevScene), + ) + data class DialogViewModel( val text: String, @@ -400,13 +420,13 @@ object BouncerViewModelModule { simBouncerInteractor = simBouncerInteractor, authenticationInteractor = authenticationInteractor, selectedUserInteractor = selectedUserInteractor, + devicePolicyManager = devicePolicyManager, + bouncerMessageViewModel = bouncerMessageViewModel, flags = flags, selectedUser = userSwitcherViewModel.selectedUser, users = userSwitcherViewModel.users, userSwitcherMenu = userSwitcherViewModel.menu, actionButton = actionButtonInteractor.actionButton, - devicePolicyManager = devicePolicyManager, - bouncerMessageViewModel = bouncerMessageViewModel, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt index 12cac9251b25..4c2380c5e4db 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt @@ -135,8 +135,11 @@ class PinBouncerViewModel( onIntentionalUserInput() - mutablePinInput.value = pinInput.append(input) - tryAuthenticate(useAutoConfirm = true) + val maxInputLength = hintedPinLength.value ?: Int.MAX_VALUE + if (pinInput.getPin().size < maxInputLength) { + mutablePinInput.value = pinInput.append(input) + tryAuthenticate(useAutoConfirm = true) + } } /** Notifies that the user clicked the backspace button. */ diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java index af467ef1319b..613280c3ba5d 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java @@ -22,7 +22,7 @@ import android.view.ViewConfiguration; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.phone.NotificationTapHelper; import dagger.Binds; @@ -51,9 +51,8 @@ public interface FalsingModule { @SysUISingleton static FalsingCollector providesFalsingCollectorLegacy( FalsingCollectorImpl impl, - FalsingCollectorNoOp noOp, - SceneContainerFlags flags) { - return flags.isEnabled() ? noOp : impl; + FalsingCollectorNoOp noOp) { + return SceneContainerFlag.isEnabled() ? noOp : impl; } /** Provides the actual {@link FalsingCollector}. */ diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt index d4a1f74234ef..0c181e99b21c 100644 --- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt +++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt @@ -16,14 +16,14 @@ package com.android.systemui.common.coroutine +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow as wrapped import kotlin.experimental.ExperimentalTypeInference -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.ProducerScope import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.callbackFlow +@Deprecated("Use com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow instead") object ConflatedCallbackFlow { /** @@ -32,9 +32,15 @@ object ConflatedCallbackFlow { * consumer(s) of the values in the flow), the values are buffered and, if the buffer fills up, * we drop the oldest values automatically instead of suspending the producer. */ - @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") - @OptIn(ExperimentalTypeInference::class, ExperimentalCoroutinesApi::class) + @Deprecated( + "Use com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow instead", + ReplaceWith( + "conflatedCallbackFlow", + "com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow" + ) + ) + @OptIn(ExperimentalTypeInference::class) fun <T> conflatedCallbackFlow( @BuilderInference block: suspend ProducerScope<T>.() -> Unit, - ): Flow<T> = callbackFlow(block).buffer(capacity = Channel.CONFLATED) + ): Flow<T> = wrapped(block) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index 4d328d6cb13f..5a174b9d2f80 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -21,6 +21,7 @@ import com.android.compose.animation.scene.SceneKey import com.android.systemui.CoreStartable import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -70,9 +71,9 @@ constructor( keyguardTransitionInteractor.startedKeyguardTransitionStep .mapLatest(::determineSceneAfterTransition) .filterNotNull() - // TODO(b/322787129): Also set a custom transition animation here to avoid the regular - // slide-in animation when setting the scene programmatically - .onEach { nextScene -> communalInteractor.changeScene(nextScene) } + .onEach { nextScene -> + communalInteractor.changeScene(nextScene, CommunalTransitionKeys.SimpleFade) + } .launchIn(applicationScope) // TODO(b/322787129): re-enable once custom animations are in place @@ -143,7 +144,14 @@ constructor( val docked = dockManager.isDocked return when { - docked && to == KeyguardState.LOCKSCREEN && from == KeyguardState.DREAMING -> { + to == KeyguardState.OCCLUDED -> { + // Hide communal when an activity is started on keyguard, to ensure the activity + // underneath the hub is shown. + CommunalScenes.Blank + } + to == KeyguardState.GLANCEABLE_HUB && from == KeyguardState.OCCLUDED -> { + // When transitioning to the hub from an occluded state, fade out the hub without + // doing any translation. CommunalScenes.Communal } to == KeyguardState.GONE -> CommunalScenes.Blank diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt index c724244816ea..9debe0e56083 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt @@ -57,6 +57,9 @@ interface CommunalSettingsRepository { * Settings. */ fun getWidgetCategories(user: UserInfo): Flow<CommunalWidgetCategories> + + /** Keyguard widgets enabled state by Device Policy Manager for the specified user. */ + fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean> } @SysUISingleton @@ -115,6 +118,16 @@ constructor( } .flowOn(bgDispatcher) + override fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean> = + broadcastDispatcher + .broadcastFlow( + filter = + IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), + user = user.userHandle + ) + .emitOnStart() + .map { devicePolicyManager.areKeyguardWidgetsAllowed(user.id) } + private fun getEnabledByUser(user: UserInfo): Flow<Boolean> = secureSettings .observerFlow(userId = user.id, names = arrayOf(Settings.Secure.GLANCEABLE_HUB_ENABLED)) @@ -128,16 +141,6 @@ constructor( ) == 1 } - private fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean> = - broadcastDispatcher - .broadcastFlow( - filter = - IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), - user = user.userHandle - ) - .emitOnStart() - .map { devicePolicyManager.areKeyguardWidgetsAllowed(user.id) } - companion object { const val GLANCEABLE_HUB_CONTENT_SETTING = "glanceable_hub_content_setting" private const val ENABLED_SETTING_DEFAULT = 1 diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index 246d5d92f8b0..619e0525acd8 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -44,6 +44,8 @@ import com.android.systemui.communal.widgets.EditWidgetsActivityStarter import com.android.systemui.communal.widgets.WidgetConfigurator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dock.DockManager +import com.android.systemui.dock.retrieveIsDocked import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger @@ -53,7 +55,7 @@ import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.plugins.ActivityStarter import com.android.systemui.scene.domain.interactor.SceneInteractor -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.UserTracker import com.android.systemui.smartspace.data.repository.SmartspaceRepository @@ -97,14 +99,14 @@ constructor( mediaRepository: CommunalMediaRepository, smartspaceRepository: SmartspaceRepository, keyguardInteractor: KeyguardInteractor, - communalSettingsInteractor: CommunalSettingsInteractor, + private val communalSettingsInteractor: CommunalSettingsInteractor, private val appWidgetHost: CommunalAppWidgetHost, private val editWidgetsActivityStarter: EditWidgetsActivityStarter, private val userTracker: UserTracker, private val activityStarter: ActivityStarter, private val userManager: UserManager, + private val dockManager: DockManager, sceneInteractor: SceneInteractor, - sceneContainerFlags: SceneContainerFlags, @CommunalLog logBuffer: LogBuffer, @CommunalTableLog tableLogBuffer: TableLogBuffer, ) { @@ -123,7 +125,7 @@ constructor( and( communalSettingsInteractor.isCommunalEnabled, not(keyguardInteractor.isEncryptedOrLockdown), - or(keyguardInteractor.isKeyguardVisible, keyguardInteractor.isDreaming) + or(keyguardInteractor.isKeyguardShowing, keyguardInteractor.isDreaming) ) .distinctUntilChanged() .onEach { available -> @@ -143,6 +145,9 @@ constructor( replay = 1, ) + /** Whether to show communal by default */ + val showByDefault: Flow<Boolean> = and(isCommunalAvailable, dockManager.retrieveIsDocked()) + /** * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene]. * @@ -210,7 +215,7 @@ constructor( */ // TODO(b/323215860): rename to something more appropriate after cleaning up usages val isCommunalShowing: Flow<Boolean> = - flow { emit(sceneContainerFlags.isEnabled()) } + flow { emit(SceneContainerFlag.isEnabled) } .flatMapLatest { sceneContainerEnabled -> if (sceneContainerEnabled) { sceneInteractor.currentScene.map { it == Scenes.Communal } @@ -352,7 +357,14 @@ constructor( /** A list of widget content to be displayed in the communal hub. */ val widgetContent: Flow<List<WidgetContent>> = combine( - widgetRepository.communalWidgets.map { filterWidgetsByExistingUsers(it) }, + widgetRepository.communalWidgets + .map { filterWidgetsByExistingUsers(it) } + .combine(communalSettingsInteractor.allowedByDevicePolicyForWorkProfile) { + // exclude widgets under work profile if not allowed by device policy + widgets, + allowedForWorkProfile -> + filterWidgetsAllowedByDevicePolicy(widgets, allowedForWorkProfile) + }, communalSettingsInteractor.communalWidgetCategories, updateOnWorkProfileBroadcastReceived, ) { widgets, allowedCategories, _ -> @@ -374,6 +386,19 @@ constructor( } } + /** Filter widgets based on whether their associated profile is allowed by device policy. */ + private fun filterWidgetsAllowedByDevicePolicy( + list: List<CommunalWidgetContentModel>, + allowedByDevicePolicyForWorkProfile: Boolean + ): List<CommunalWidgetContentModel> = + if (allowedByDevicePolicyForWorkProfile) { + list + } else { + // Get associated work profile for the currently selected user. + val workProfile = userTracker.userProfiles.find { it.isManagedProfile } + list.filter { it.providerInfo.profile.identifier != workProfile?.id } + } + /** A flow of available smartspace targets. Currently only showing timers. */ private val smartspaceTargets: Flow<List<SmartspaceTarget>> = if (!smartspaceRepository.isSmartspaceRemoteViewsEnabled) { diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt index 20f60b79c784..f9de60984e2d 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt @@ -16,6 +16,8 @@ package com.android.systemui.communal.domain.interactor +import android.content.pm.UserInfo +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.communal.data.model.CommunalEnabledState import com.android.systemui.communal.data.model.CommunalWidgetCategories import com.android.systemui.communal.data.repository.CommunalSettingsRepository @@ -24,13 +26,18 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.log.dagger.CommunalTableLog import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable +import com.android.systemui.settings.UserTracker import com.android.systemui.user.domain.interactor.SelectedUserInteractor +import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -40,8 +47,10 @@ class CommunalSettingsInteractor @Inject constructor( @Background private val bgScope: CoroutineScope, + @Background private val bgExecutor: Executor, private val repository: CommunalSettingsRepository, userInteractor: SelectedUserInteractor, + private val userTracker: UserTracker, @CommunalTableLog tableLogBuffer: TableLogBuffer, ) { /** Whether or not communal is enabled for the currently selected user. */ @@ -68,4 +77,33 @@ constructor( started = SharingStarted.Eagerly, initialValue = CommunalWidgetCategories().categories ) + + private val workProfileUserInfoCallbackFlow: Flow<UserInfo?> = conflatedCallbackFlow { + fun send(profiles: List<UserInfo>) { + trySend(profiles.find { it.isManagedProfile }) + } + + val callback = + object : UserTracker.Callback { + override fun onProfilesChanged(profiles: List<UserInfo>) { + send(profiles) + } + } + userTracker.addCallback(callback, bgExecutor) + send(userTracker.userProfiles) + + awaitClose { userTracker.removeCallback(callback) } + } + + /** Whether or not keyguard widgets are allowed for work profile by device policy manager. */ + val allowedByDevicePolicyForWorkProfile: StateFlow<Boolean> = + workProfileUserInfoCallbackFlow + .flatMapLatest { workProfile -> + workProfile?.let { repository.getAllowedByDevicePolicy(it) } ?: flowOf(false) + } + .stateIn( + scope = bgScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false + ) } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt index b719126adcf8..a3c61a413639 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java +++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +14,16 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch.dagger; +package com.android.systemui.communal.shared.model -import dagger.Module; +import com.android.compose.animation.scene.TransitionKey /** - * {@link DreamTouchModule} encapsulates dream touch-related components. + * Defines all known named transitions for [CommunalScenes]. + * + * These transitions can be referenced by key when changing scenes programmatically. */ -@Module(includes = { - BouncerSwipeModule.class, - ShadeModule.class, - }, subcomponents = { - InputSessionComponent.class, -}) -public interface DreamTouchModule { - String INPUT_SESSION_NAME = "INPUT_SESSION_NAME"; - String PILFER_ON_GESTURE_CONSUME = "PILFER_ON_GESTURE_CONSUME"; +object CommunalTransitionKeys { + /** Fades the glanceable hub without any translation */ + val SimpleFade = TransitionKey("SimpleFade") } diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt index 96e4b341cb6d..bdf4e721a551 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt @@ -16,7 +16,11 @@ package com.android.systemui.communal.ui.viewmodel +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel @@ -25,6 +29,7 @@ import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.merge /** View model for transitions related to the communal hub. */ @@ -37,6 +42,8 @@ constructor( lockscreenToGlanceableHubTransitionViewModel: LockscreenToGlanceableHubTransitionViewModel, dreamToGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, glanceableHubToDreamTransitionViewModel: GlanceableHubToDreamingTransitionViewModel, + communalInteractor: CommunalInteractor, + keyguardTransitionInteractor: KeyguardTransitionInteractor, ) { /** * Whether UMO location should be on communal. This flow is responsive to transitions so that a @@ -51,4 +58,14 @@ constructor( glanceableHubToDreamTransitionViewModel.showUmo, ) .distinctUntilChanged() + + /** Whether to show communal by default */ + val showByDefault: Flow<Boolean> = communalInteractor.showByDefault + + val transitionFromOccludedEnded = + keyguardTransitionInteractor.transitionStepsFromState(KeyguardState.OCCLUDED).filter { step + -> + step.transitionState == TransitionState.FINISHED || + step.transitionState == TransitionState.CANCELED + } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 7d86e0639b16..6b85d3039e15 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -32,6 +32,7 @@ import com.android.systemui.CameraProtectionModule; import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.accessibility.AccessibilityModule; import com.android.systemui.accessibility.data.repository.AccessibilityRepositoryModule; +import com.android.systemui.ambient.dagger.AmbientModule; import com.android.systemui.appops.dagger.AppOpsModule; import com.android.systemui.assist.AssistModule; import com.android.systemui.authentication.AuthenticationModule; @@ -162,14 +163,14 @@ import dagger.Provides; import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; +import kotlinx.coroutines.CoroutineScope; + import java.util.Collections; import java.util.Optional; import java.util.concurrent.Executor; import javax.inject.Named; -import kotlinx.coroutines.CoroutineScope; - /** * A dagger module for injecting components of System UI that are required by System UI. * @@ -183,6 +184,7 @@ import kotlinx.coroutines.CoroutineScope; @Module(includes = { AccessibilityModule.class, AccessibilityRepositoryModule.class, + AmbientModule.class, AppOpsModule.class, AssistModule.class, AuthenticationModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt index 0e04d15d8680..e418641231ed 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt @@ -50,6 +50,7 @@ import com.android.systemui.keyguard.data.repository.TrustRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.log.FaceAuthenticationLogger @@ -294,7 +295,8 @@ constructor( } private fun listenForSchedulingWatchdog() { - keyguardTransitionInteractor.anyStateToGoneTransition + keyguardTransitionInteractor + .transition(to = KeyguardState.GONE) .filter { it.transitionState == TransitionState.FINISHED } .onEach { // We deliberately want to run this in background because scheduleWatchdog does @@ -312,7 +314,17 @@ constructor( // or device starts going to sleep. merge( powerInteractor.isAsleep, - keyguardTransitionInteractor.isInTransitionToState(KeyguardState.GONE), + combine( + keyguardTransitionInteractor.isFinishedInState(KeyguardState.GONE), + keyguardInteractor.statusBarState, + ) { isFinishedInGoneState, statusBarState -> + // When the user is dragging the primary bouncer in (up) by manually scrolling + // up on the lockscreen, the device won't be irreversibly transitioned to GONE + // until the statusBarState updates to SHADE, so we check that here. + // Else, we could reset the face auth state too early and end up in a strange + // state. + isFinishedInGoneState && statusBarState == StatusBarState.SHADE + }, userRepository.selectedUser.map { it.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS }, diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt index a7266503b7a1..03819ed9e2fe 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt @@ -37,6 +37,10 @@ import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStat import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.AOD +import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING +import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN +import com.android.systemui.keyguard.shared.model.KeyguardState.OFF import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.log.FaceAuthenticationLogger import com.android.systemui.power.domain.interactor.PowerInteractor @@ -121,9 +125,9 @@ constructor( .launchIn(applicationScope) merge( - keyguardTransitionInteractor.aodToLockscreenTransition, - keyguardTransitionInteractor.offToLockscreenTransition, - keyguardTransitionInteractor.dozingToLockscreenTransition + keyguardTransitionInteractor.transition(AOD, LOCKSCREEN), + keyguardTransitionInteractor.transition(OFF, LOCKSCREEN), + keyguardTransitionInteractor.transition(DOZING, LOCKSCREEN), ) .filter { it.transitionState == TransitionState.STARTED } .sample(powerInteractor.detailedWakefulness) diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt index 1230156953ee..4ac0c5683d06 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map @@ -67,6 +68,9 @@ interface DisplayRepository { */ val pendingDisplay: Flow<PendingDisplay?> + /** Whether the default display is currently off. */ + val defaultDisplayOff: Flow<Boolean> + /** Represents a connected display that has not been enabled yet. */ interface PendingDisplay { /** Id of the pending display. */ @@ -290,6 +294,11 @@ constructor( } .debugLog("pendingDisplay") + override val defaultDisplayOff: Flow<Boolean> = + displays + .map { displays -> displays.firstOrNull { it.displayId == Display.DEFAULT_DISPLAY } } + .map { it?.state == Display.STATE_OFF } + private fun <T> Flow<T>.debugLog(flowName: String): Flow<T> { return if (DEBUG) { traceEach(flowName, logcat = true, traceEmissionCount = true) diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt deleted file mode 100644 index 989b0de85e0c..000000000000 --- a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2023 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.systemui.display.ui.view - -import android.content.Context -import android.os.Bundle -import android.view.View -import android.view.WindowInsets -import android.widget.TextView -import androidx.core.view.updatePadding -import com.android.systemui.res.R -import com.android.systemui.statusbar.phone.SystemUIBottomSheetDialog -import com.android.systemui.statusbar.policy.ConfigurationController -import kotlin.math.max - -/** - * Dialog used to decide what to do with a connected display. - * - * [onCancelMirroring] is called **only** if mirroring didn't start, or when the dismiss button is - * pressed. - */ -class MirroringConfirmationDialog( - context: Context, - private val onStartMirroringClickListener: View.OnClickListener, - private val onCancelMirroring: View.OnClickListener, - private val navbarBottomInsetsProvider: () -> Int, - configurationController: ConfigurationController? = null, - private val showConcurrentDisplayInfo: Boolean = false, - theme: Int = R.style.Theme_SystemUI_Dialog, -) : SystemUIBottomSheetDialog(context, configurationController, theme) { - - private lateinit var mirrorButton: TextView - private lateinit var dismissButton: TextView - private lateinit var dualDisplayWarning: TextView - private lateinit var bottomSheet: View - private var enabledPressed = false - private val defaultDialogBottomInset = - context.resources.getDimensionPixelSize(R.dimen.dialog_bottom_padding) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.connected_display_dialog) - - mirrorButton = - requireViewById<TextView>(R.id.enable_display).apply { - setOnClickListener(onStartMirroringClickListener) - enabledPressed = true - } - dismissButton = - requireViewById<TextView>(R.id.cancel).apply { setOnClickListener(onCancelMirroring) } - - dualDisplayWarning = - requireViewById<TextView>(R.id.dual_display_warning).apply { - visibility = if (showConcurrentDisplayInfo) View.VISIBLE else View.GONE - } - - bottomSheet = requireViewById(R.id.cd_bottom_sheet) - - setOnDismissListener { - if (!enabledPressed) { - onCancelMirroring.onClick(null) - } - } - setupInsets() - } - - private fun setupInsets(navbarInsets: Int = navbarBottomInsetsProvider()) { - // This avoids overlap between dialog content and navigation bars. - // we only care about the bottom inset as in all other configuration where navigations - // are in other display sides there is no overlap with the dialog. - bottomSheet.updatePadding(bottom = max(navbarInsets, defaultDialogBottomInset)) - } - - override fun onInsetsChanged(changedTypes: Int, insets: WindowInsets) { - val navbarType = WindowInsets.Type.navigationBars() - if (changedTypes and navbarType != 0) { - setupInsets(insets.getInsets(navbarType).bottom) - } - } - - override fun onConfigurationChanged() { - super.onConfigurationChanged() - setupInsets() - } -} diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegate.kt new file mode 100644 index 000000000000..19b267317375 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegate.kt @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.display.ui.view + +import android.app.Dialog +import android.content.Context +import android.content.res.Configuration +import android.os.Bundle +import android.view.View +import android.view.WindowInsets +import android.view.WindowInsetsAnimation +import android.widget.TextView +import androidx.annotation.StyleRes +import androidx.annotation.VisibleForTesting +import androidx.core.view.updatePadding +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.res.R +import com.android.systemui.statusbar.phone.DialogDelegate +import com.android.systemui.statusbar.phone.SystemUIBottomSheetDialog +import javax.inject.Inject +import kotlin.math.max + +/** + * Dialog used to decide what to do with a connected display. + * + * [onCancelMirroring] is called **only** if mirroring didn't start, or when the dismiss button is + * pressed. + */ +class MirroringConfirmationDialogDelegate +@VisibleForTesting +constructor( + context: Context, + private val showConcurrentDisplayInfo: Boolean = false, + private val onStartMirroringClickListener: View.OnClickListener, + private val onCancelMirroring: View.OnClickListener, + private val navbarBottomInsetsProvider: () -> Int, +) : DialogDelegate<Dialog> { + + private lateinit var mirrorButton: TextView + private lateinit var dismissButton: TextView + private lateinit var dualDisplayWarning: TextView + private lateinit var bottomSheet: View + private var enabledPressed = false + private val defaultDialogBottomInset = + context.resources.getDimensionPixelSize(R.dimen.dialog_bottom_padding) + + override fun onCreate(dialog: Dialog, savedInstanceState: Bundle?) { + dialog.setContentView(R.layout.connected_display_dialog) + + mirrorButton = + dialog.requireViewById<TextView>(R.id.enable_display).apply { + setOnClickListener(onStartMirroringClickListener) + enabledPressed = true + } + dismissButton = + dialog.requireViewById<TextView>(R.id.cancel).apply { + setOnClickListener(onCancelMirroring) + } + + dualDisplayWarning = + dialog.requireViewById<TextView>(R.id.dual_display_warning).apply { + visibility = if (showConcurrentDisplayInfo) View.VISIBLE else View.GONE + } + + bottomSheet = dialog.requireViewById(R.id.cd_bottom_sheet) + + dialog.setOnDismissListener { + if (!enabledPressed) { + onCancelMirroring.onClick(null) + } + } + setupInsets() + } + + override fun onStart(dialog: Dialog) { + dialog.window?.decorView?.setWindowInsetsAnimationCallback(insetsAnimationCallback) + } + + override fun onStop(dialog: Dialog) { + dialog.window?.decorView?.setWindowInsetsAnimationCallback(null) + } + + private fun setupInsets(navbarInsets: Int = navbarBottomInsetsProvider()) { + // This avoids overlap between dialog content and navigation bars. + // we only care about the bottom inset as in all other configuration where navigations + // are in other display sides there is no overlap with the dialog. + bottomSheet.updatePadding(bottom = max(navbarInsets, defaultDialogBottomInset)) + } + + override fun onConfigurationChanged(dialog: Dialog, configuration: Configuration) { + setupInsets() + } + + private val insetsAnimationCallback = + object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) { + + private var lastInsets: WindowInsets? = null + + override fun onEnd(animation: WindowInsetsAnimation) { + lastInsets?.let { onInsetsChanged(animation.typeMask, it) } + } + + override fun onProgress( + insets: WindowInsets, + animations: MutableList<WindowInsetsAnimation>, + ): WindowInsets { + lastInsets = insets + onInsetsChanged(changedTypes = allAnimationMasks(animations), insets) + return insets + } + + private fun allAnimationMasks(animations: List<WindowInsetsAnimation>): Int = + animations.fold(0) { acc: Int, it -> acc or it.typeMask } + + private fun onInsetsChanged(changedTypes: Int, insets: WindowInsets) { + val navbarType = WindowInsets.Type.navigationBars() + if (changedTypes and navbarType != 0) { + setupInsets(insets.getInsets(navbarType).bottom) + } + } + } + + class Factory + @Inject + constructor( + @Application private val context: Context, + private val dialogFactory: SystemUIBottomSheetDialog.Factory, + ) { + + fun createDialog( + showConcurrentDisplayInfo: Boolean = false, + onStartMirroringClickListener: View.OnClickListener, + onCancelMirroring: View.OnClickListener, + navbarBottomInsetsProvider: () -> Int, + @StyleRes theme: Int = R.style.Theme_SystemUI_Dialog, + ): Dialog = + dialogFactory.create( + delegate = + MirroringConfirmationDialogDelegate( + context = context, + showConcurrentDisplayInfo = showConcurrentDisplayInfo, + onStartMirroringClickListener = onStartMirroringClickListener, + onCancelMirroring = onCancelMirroring, + navbarBottomInsetsProvider = navbarBottomInsetsProvider, + ), + theme = theme, + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt index fbf0538e4bae..81ea2e74d799 100644 --- a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt @@ -25,8 +25,7 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay -import com.android.systemui.display.ui.view.MirroringConfirmationDialog -import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.display.ui.view.MirroringConfirmationDialogDelegate import dagger.Binds import dagger.Module import dagger.multibindings.ClassKey @@ -54,7 +53,7 @@ constructor( private val connectedDisplayInteractor: ConnectedDisplayInteractor, @Application private val scope: CoroutineScope, @Background private val bgDispatcher: CoroutineDispatcher, - private val configurationController: ConfigurationController, + private val bottomSheetFactory: MirroringConfirmationDialogDelegate.Factory, ) : CoreStartable { private var dialog: Dialog? = null @@ -91,8 +90,8 @@ constructor( private fun showDialog(pendingDisplay: PendingDisplay, concurrentDisplaysInProgess: Boolean) { hideDialog() dialog = - MirroringConfirmationDialog( - context, + bottomSheetFactory + .createDialog( onStartMirroringClickListener = { scope.launch(bgDispatcher) { pendingDisplay.enable() } hideDialog() @@ -102,7 +101,6 @@ constructor( hideDialog() }, navbarBottomInsetsProvider = { Utils.getNavbarInsets(context).bottom }, - configurationController, showConcurrentDisplayInfo = concurrentDisplaysInProgess ) .apply { show() } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 1a855d735a02..95012a2643a5 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -54,8 +54,6 @@ public class DozeUi implements DozeMachine.Part { private final DozeParameters mDozeParameters; private final DozeLog mDozeLog; private final DelayableExecutor mBgExecutor; - - private Runnable mCancelRunnable = null; private long mLastTimeTickElapsed = 0; // If time tick is scheduled and there's not a pending runnable to cancel: private volatile boolean mTimeTickScheduled; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java index d0f255943a84..5a036b17a35b 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java @@ -33,14 +33,14 @@ import android.view.ViewGroup; import com.android.app.animation.Interpolators; import com.android.dream.lowlight.LowLightTransitionCoordinator; -import com.android.systemui.res.R; +import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController; +import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor; +import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback; import com.android.systemui.complication.ComplicationHostViewController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.dagger.DreamOverlayComponent; import com.android.systemui.dreams.dagger.DreamOverlayModule; -import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController; -import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor; -import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback; +import com.android.systemui.res.R; import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.util.ViewController; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 675e8deededf..1135afeb6f83 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -43,11 +43,12 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.policy.PhoneWindow; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.ambient.touch.TouchMonitor; +import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent; import com.android.systemui.complication.Complication; import com.android.systemui.complication.dagger.ComplicationComponent; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.dagger.DreamOverlayComponent; -import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -94,6 +95,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private final ComplicationComponent mComplicationComponent; + private final AmbientTouchComponent mAmbientTouchComponent; + private final com.android.systemui.dreams.complication.dagger.ComplicationComponent mDreamComplicationComponent; @@ -102,7 +105,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private final DreamOverlayLifecycleOwner mLifecycleOwner; private final LifecycleRegistry mLifecycleRegistry; - private DreamOverlayTouchMonitor mDreamOverlayTouchMonitor; + private TouchMonitor mTouchMonitor; private final KeyguardUpdateMonitorCallback mKeyguardCallback = new KeyguardUpdateMonitorCallback() { @@ -162,6 +165,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ com.android.systemui.dreams.complication.dagger.ComplicationComponent.Factory dreamComplicationComponentFactory, DreamOverlayComponent.Factory dreamOverlayComponentFactory, + AmbientTouchComponent.Factory ambientTouchComponentFactory, DreamOverlayStateController stateController, KeyguardUpdateMonitor keyguardUpdateMonitor, UiEventLogger uiEventLogger, @@ -194,9 +198,11 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamComplicationComponent = dreamComplicationComponentFactory.create( mComplicationComponent.getVisibilityController(), touchInsetManager); mDreamOverlayComponent = dreamOverlayComponentFactory.create(lifecycleOwner, - mComplicationComponent.getComplicationHostViewController(), touchInsetManager, + mComplicationComponent.getComplicationHostViewController(), touchInsetManager); + mAmbientTouchComponent = ambientTouchComponentFactory.create(lifecycleOwner, new HashSet<>(Arrays.asList( - mDreamComplicationComponent.getHideComplicationTouchHandler()))); + mDreamComplicationComponent.getHideComplicationTouchHandler(), + mDreamOverlayComponent.getCommunalTouchHandler()))); mLifecycleOwner = lifecycleOwner; mLifecycleRegistry = mLifecycleOwner.getRegistry(); @@ -239,8 +245,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayContainerViewController = mDreamOverlayComponent.getDreamOverlayContainerViewController(); - mDreamOverlayTouchMonitor = mDreamOverlayComponent.getDreamOverlayTouchMonitor(); - mDreamOverlayTouchMonitor.init(); + mTouchMonitor = mAmbientTouchComponent.getTouchMonitor(); + mTouchMonitor.init(); mStateController.setShouldShowComplications(shouldShowComplications()); @@ -370,7 +376,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mStateController.setEntryAnimationsFinished(false); mDreamOverlayContainerViewController = null; - mDreamOverlayTouchMonitor = null; + mTouchMonitor = null; mWindow = null; mStarted = false; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java index ee48ee5f50fd..f8ae5c28d018 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java @@ -16,6 +16,7 @@ package com.android.systemui.dreams.complication; +import static com.android.systemui.Flags.removeDreamOverlayHideOnTouch; import static com.android.systemui.dreams.complication.dagger.ComplicationModule.COMPLICATIONS_FADE_OUT_DELAY; import static com.android.systemui.dreams.complication.dagger.ComplicationModule.COMPLICATIONS_RESTORE_TIMEOUT; @@ -25,11 +26,11 @@ import android.view.View; import androidx.annotation.Nullable; +import com.android.systemui.ambient.touch.TouchHandler; +import com.android.systemui.ambient.touch.TouchMonitor; import com.android.systemui.complication.Complication; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.DreamOverlayStateController; -import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor; -import com.android.systemui.dreams.touch.DreamTouchHandler; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -46,12 +47,12 @@ import javax.inject.Named; * {@link HideComplicationTouchHandler} is responsible for hiding the overlay complications from * visibility whenever there is touch interactions outside the overlay. The overlay interaction * scope includes touches to the complication plus any touch entry region for gestures as specified - * to the {@link DreamOverlayTouchMonitor}. + * to the {@link TouchMonitor}. * - * This {@link DreamTouchHandler} is also responsible for fading in the complications at the end - * of the {@link com.android.systemui.dreams.touch.DreamTouchHandler.TouchSession}. + * This {@link TouchHandler} is also responsible for fading in the complications at the end + * of the {@link TouchHandler.TouchSession}. */ -public class HideComplicationTouchHandler implements DreamTouchHandler { +public class HideComplicationTouchHandler implements TouchHandler { private static final String TAG = "HideComplicationHandler"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -120,7 +121,7 @@ public class HideComplicationTouchHandler implements DreamTouchHandler { final boolean bouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); // If other sessions are interested in this touch, do not fade out elements. - if (session.getActiveSessionCount() > 1 || bouncerShowing + if (removeDreamOverlayHideOnTouch() || session.getActiveSessionCount() > 1 || bouncerShowing || mOverlayStateController.areExitAnimationsRunning()) { if (DEBUG) { Log.d(TAG, "not fading. Active session count: " + session.getActiveSessionCount() diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java index ba74742fc47f..31710ac4cc4f 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java @@ -25,6 +25,7 @@ import android.content.res.Resources; import com.android.dream.lowlight.dagger.LowLightDreamModule; import com.android.settingslib.dream.DreamBackend; +import com.android.systemui.ambient.touch.scrim.dagger.ScrimModule; import com.android.systemui.complication.dagger.RegisteredComplicationsModule; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -34,7 +35,6 @@ import com.android.systemui.dreams.complication.dagger.ComplicationComponent; import com.android.systemui.dreams.homecontrols.DreamActivityProvider; import com.android.systemui.dreams.homecontrols.DreamActivityProviderImpl; import com.android.systemui.dreams.homecontrols.HomeControlsDreamService; -import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule; import com.android.systemui.res.R; import com.android.systemui.touch.TouchInsetManager; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java index cb587c2f96c7..16276fe81afc 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java @@ -16,19 +16,14 @@ package com.android.systemui.dreams.dagger; -import static com.android.systemui.dreams.dagger.DreamOverlayModule.DREAM_TOUCH_HANDLERS; - import static java.lang.annotation.RetentionPolicy.RUNTIME; -import android.annotation.Nullable; - import androidx.lifecycle.LifecycleOwner; import com.android.systemui.complication.ComplicationHostViewController; import com.android.systemui.dreams.DreamOverlayContainerViewController; -import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor; -import com.android.systemui.dreams.touch.DreamTouchHandler; -import com.android.systemui.dreams.touch.dagger.DreamTouchModule; +import com.android.systemui.dreams.touch.CommunalTouchHandler; +import com.android.systemui.dreams.touch.dagger.CommunalTouchModule; import com.android.systemui.touch.TouchInsetManager; import dagger.BindsInstance; @@ -36,17 +31,15 @@ import dagger.Subcomponent; import java.lang.annotation.Documented; import java.lang.annotation.Retention; -import java.util.Set; -import javax.inject.Named; import javax.inject.Scope; /** * Dagger subcomponent for {@link DreamOverlayModule}. */ @Subcomponent(modules = { - DreamTouchModule.class, DreamOverlayModule.class, + CommunalTouchModule.class }) @DreamOverlayComponent.DreamOverlayScope public interface DreamOverlayComponent { @@ -56,9 +49,7 @@ public interface DreamOverlayComponent { DreamOverlayComponent create( @BindsInstance LifecycleOwner lifecycleOwner, @BindsInstance ComplicationHostViewController complicationHostViewController, - @BindsInstance TouchInsetManager touchInsetManager, - @BindsInstance @Named(DREAM_TOUCH_HANDLERS) @Nullable - Set<DreamTouchHandler> dreamTouchHandlers); + @BindsInstance TouchInsetManager touchInsetManager); } /** Scope annotation for singleton items within the {@link DreamOverlayComponent}. */ @@ -70,6 +61,6 @@ public interface DreamOverlayComponent { /** Builds a {@link DreamOverlayContainerViewController}. */ DreamOverlayContainerViewController getDreamOverlayContainerViewController(); - /** Builds a {@link DreamOverlayTouchMonitor} */ - DreamOverlayTouchMonitor getDreamOverlayTouchMonitor(); + /** Builds communal touch handler */ + CommunalTouchHandler getCommunalTouchHandler(); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java index 34dd10084116..999e6813ea55 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java @@ -16,7 +16,6 @@ package com.android.systemui.dreams.dagger; -import android.annotation.Nullable; import android.content.res.Resources; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -25,26 +24,20 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; import com.android.internal.util.Preconditions; -import com.android.systemui.res.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.DreamOverlayContainerView; import com.android.systemui.dreams.DreamOverlayStatusBarView; -import com.android.systemui.dreams.touch.DreamTouchHandler; +import com.android.systemui.res.R; import com.android.systemui.touch.TouchInsetManager; import dagger.Module; import dagger.Provides; -import dagger.multibindings.ElementsIntoSet; - -import java.util.HashSet; -import java.util.Set; import javax.inject.Named; /** Dagger module for {@link DreamOverlayComponent}. */ @Module public abstract class DreamOverlayModule { - public static final String DREAM_TOUCH_HANDLERS = "dream_touch_handlers"; public static final String DREAM_OVERLAY_CONTENT_VIEW = "dream_overlay_content_view"; public static final String MAX_BURN_IN_OFFSET = "max_burn_in_offset"; public static final String BURN_IN_PROTECTION_UPDATE_INTERVAL = @@ -169,11 +162,4 @@ public abstract class DreamOverlayModule { static Lifecycle providesLifecycle(LifecycleOwner lifecycleOwner) { return lifecycleOwner.getLifecycle(); } - - @Provides - @ElementsIntoSet - static Set<DreamTouchHandler> providesDreamTouchHandlers( - @Named(DREAM_TOUCH_HANDLERS) @Nullable Set<DreamTouchHandler> touchHandlers) { - return touchHandlers != null ? touchHandlers : new HashSet<>(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java index 13588c2d45fe..1c047ddcd3d8 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java @@ -16,7 +16,6 @@ package com.android.systemui.dreams.touch; -import static com.android.systemui.dreams.touch.dagger.ShadeModule.COMMUNAL_GESTURE_INITIATION_WIDTH; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.graphics.Rect; @@ -27,7 +26,9 @@ import android.view.MotionEvent; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; +import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.communal.domain.interactor.CommunalInteractor; +import com.android.systemui.dreams.touch.dagger.CommunalTouchModule; import com.android.systemui.statusbar.phone.CentralSurfaces; import java.util.Optional; @@ -36,8 +37,8 @@ import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; -/** {@link DreamTouchHandler} responsible for handling touches to open communal hub. **/ -public class CommunalTouchHandler implements DreamTouchHandler { +/** {@link TouchHandler} responsible for handling touches to open communal hub. **/ +public class CommunalTouchHandler implements TouchHandler { private final int mInitiationWidth; private final Optional<CentralSurfaces> mCentralSurfaces; private final Lifecycle mLifecycle; @@ -53,7 +54,7 @@ public class CommunalTouchHandler implements DreamTouchHandler { @Inject public CommunalTouchHandler( Optional<CentralSurfaces> centralSurfaces, - @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth, + @Named(CommunalTouchModule.COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth, CommunalInteractor communalInteractor, Lifecycle lifecycle) { mInitiationWidth = initiationWidth; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/CommunalTouchModule.kt b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/CommunalTouchModule.kt new file mode 100644 index 000000000000..927ea4ec6d4b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/CommunalTouchModule.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.dreams.touch.dagger + +import android.content.res.Resources +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.res.R +import dagger.Module +import dagger.Provides +import javax.inject.Named + +@Module +interface CommunalTouchModule { + companion object { + /** Provides the width of the gesture area for swiping open communal hub. */ + @JvmStatic + @Provides + @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) + fun providesCommunalGestureInitiationWidth(@Main resources: Resources): Int { + return resources.getDimensionPixelSize(R.dimen.communal_gesture_initiation_width) + } + + /** Width of swipe gesture edge to show communal hub. */ + const val COMMUNAL_GESTURE_INITIATION_WIDTH = "communal_gesture_initiation_width" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt index 037c23b579c3..2d9c14e222e9 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt @@ -21,13 +21,16 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.res.R import com.android.systemui.settings.UserTracker +import com.android.systemui.util.kotlin.FlowDumperImpl import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow @@ -49,7 +52,8 @@ constructor( private val communalInteractor: CommunalInteractor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val userTracker: UserTracker, -) { + dumpManager: DumpManager, +) : FlowDumperImpl(dumpManager) { fun startTransitionFromDream() { val showGlanceableHub = @@ -83,6 +87,7 @@ constructor( toGlanceableHubTransitionViewModel.dreamAlpha, ) .distinctUntilChanged() + .dumpWhileCollecting("dreamAlpha") val dreamOverlayAlpha: Flow<Float> = merge( @@ -93,7 +98,7 @@ constructor( .distinctUntilChanged() val transitionEnded = - keyguardTransitionInteractor.fromDreamingTransition.filter { step -> + keyguardTransitionInteractor.transition(from = DREAMING).filter { step -> step.transitionState == TransitionState.FINISHED || step.transitionState == TransitionState.CANCELED } diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 640534cc9d34..db6b8fea9235 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -153,11 +153,6 @@ object Flags { // TODO(b/267722622): Tracking Bug @JvmField val WALLPAPER_PICKER_UI_FOR_AIWP = releasedFlag("wallpaper_picker_ui_for_aiwp") - /** Whether to use a new data source for intents to run on keyguard dismissal. */ - // TODO(b/275069969): Tracking bug. - @JvmField - val REFACTOR_KEYGUARD_DISMISS_INTENT = unreleasedFlag("refactor_keyguard_dismiss_intent") - /** Whether to allow long-press on the lock screen to directly open wallpaper picker. */ // TODO(b/277220285): Tracking bug. @JvmField @@ -342,11 +337,6 @@ object Flags { namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER, ) - @Keep - @JvmField - val WM_CAPTION_ON_SHELL = - sysPropBooleanFlag("persist.wm.debug.caption_on_shell", default = true) - // TODO(b/256873975): Tracking Bug @JvmField @Keep diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt index f1620d96b159..4327d18da97e 100644 --- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt +++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt @@ -27,40 +27,65 @@ import androidx.annotation.VisibleForTesting import androidx.core.animation.doOnCancel import androidx.core.animation.doOnEnd import androidx.core.animation.doOnStart +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.statusbar.VibratorHelper -import kotlinx.coroutines.CancellationException +import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn /** * A class that handles the long press visuo-haptic effect for a QS tile. * * The class is also a [View.OnTouchListener] to handle the touch events, clicks and long-press - * gestures of the tile. The class also provides a [State] that can be used to determine the current + * gestures of the tile. The class also provides a [State] tha can be used to determine the current * state of the long press effect. * * @property[vibratorHelper] The [VibratorHelper] to deliver haptic effects. * @property[effectDuration] The duration of the effect in ms. */ -class QSLongPressEffect( +// TODO(b/332902869): In addition from being injectable, we can consider making it a singleton +class QSLongPressEffect +@Inject +constructor( private val vibratorHelper: VibratorHelper?, - private val effectDuration: Int, + val keyguardInteractor: KeyguardInteractor, + @Background bgScope: CoroutineScope, ) : View.OnTouchListener { + private var effectDuration = 0 + /** Current state */ - var state = State.IDLE - @VisibleForTesting set + private var _state = MutableStateFlow(State.IDLE) + val state = _state.stateIn(bgScope, SharingStarted.Lazily, State.IDLE) /** Flows for view control and action */ private val _effectProgress = MutableStateFlow<Float?>(null) - val effectProgress = _effectProgress.asStateFlow() + val effectProgress = _effectProgress.stateIn(bgScope, SharingStarted.Lazily, null) + + // Actions to perform + private val _postedActionType = MutableStateFlow<ActionType?>(null) + val actionType: StateFlow<ActionType?> = + combine( + _postedActionType, + keyguardInteractor.isKeyguardDismissible, + ) { action, isDismissible -> + if (!isDismissible && action == ActionType.LONG_PRESS) { + ActionType.RESET_AND_LONG_PRESS + } else { + action + } + } + .stateIn(bgScope, SharingStarted.Lazily, null) - private val _actionType = MutableStateFlow<ActionType?>(null) - val actionType = _actionType.asStateFlow() + // Should a tap timeout countdown begin + val shouldWaitForTapTimeout: Flow<Boolean> = state.map { it == State.TIMEOUT_WAIT } /** Haptic effects */ private val durations = @@ -69,41 +94,33 @@ class QSLongPressEffect( VibrationEffect.Composition.PRIMITIVE_SPIN ) - private val longPressHint = - LongPressHapticBuilder.createLongPressHint( - durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION, - durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION, - effectDuration - ) + private var longPressHint: VibrationEffect? = null private val snapEffect = LongPressHapticBuilder.createSnapEffect() - /* A coroutine scope and a timer job that waits for the pressedTimeout */ - var scope: CoroutineScope? = null - private var waitJob: Job? = null + private var effectAnimator: ValueAnimator? = null - private val effectAnimator = - ValueAnimator.ofFloat(0f, 1f).apply { - duration = effectDuration.toLong() - interpolator = AccelerateDecelerateInterpolator() + val hasInitialized: Boolean + get() = longPressHint != null && effectAnimator != null - doOnStart { handleAnimationStart() } - addUpdateListener { _effectProgress.value = animatedValue as Float } - doOnEnd { handleAnimationComplete() } - doOnCancel { handleAnimationCancel() } - } + @VisibleForTesting + fun setState(state: State) { + _state.value = state + } private fun reverse() { - val pausedProgress = effectAnimator.animatedFraction - val effect = - LongPressHapticBuilder.createReversedEffect( - pausedProgress, - durations?.get(0) ?: 0, - effectDuration, - ) - vibratorHelper?.cancel() - vibrate(effect) - effectAnimator.reverse() + effectAnimator?.let { + val pausedProgress = it.animatedFraction + val effect = + LongPressHapticBuilder.createReversedEffect( + pausedProgress, + durations?.get(0) ?: 0, + effectDuration, + ) + vibratorHelper?.cancel() + vibrate(effect) + it.reverse() + } } private fun vibrate(effect: VibrationEffect?) { @@ -129,52 +146,37 @@ class QSLongPressEffect( } private fun handleActionDown() { - when (state) { + when (_state.value) { State.IDLE -> { - startPressedTimeoutWait() - state = State.TIMEOUT_WAIT + setState(State.TIMEOUT_WAIT) } - State.RUNNING_BACKWARDS -> effectAnimator.cancel() + State.RUNNING_BACKWARDS -> effectAnimator?.cancel() else -> {} } } - private fun startPressedTimeoutWait() { - waitJob = - scope?.launch { - try { - delay(PRESSED_TIMEOUT) - handleTimeoutComplete() - } catch (_: CancellationException) { - state = State.IDLE - } - } - } - private fun handleActionUp() { - when (state) { + when (_state.value) { State.TIMEOUT_WAIT -> { - waitJob?.cancel() - _actionType.value = ActionType.CLICK - state = State.IDLE + _postedActionType.value = ActionType.CLICK + setState(State.IDLE) } State.RUNNING_FORWARD -> { reverse() - state = State.RUNNING_BACKWARDS + setState(State.RUNNING_BACKWARDS) } else -> {} } } private fun handleActionCancel() { - when (state) { + when (_state.value) { State.TIMEOUT_WAIT -> { - waitJob?.cancel() - state = State.IDLE + setState(State.IDLE) } State.RUNNING_FORWARD -> { reverse() - state = State.RUNNING_BACKWARDS + setState(State.RUNNING_BACKWARDS) } else -> {} } @@ -182,54 +184,78 @@ class QSLongPressEffect( private fun handleAnimationStart() { vibrate(longPressHint) - state = State.RUNNING_FORWARD + setState(State.RUNNING_FORWARD) } /** This function is called both when an animator completes or gets cancelled */ private fun handleAnimationComplete() { - if (state == State.RUNNING_FORWARD) { + if (_state.value == State.RUNNING_FORWARD) { vibrate(snapEffect) - _actionType.value = ActionType.LONG_PRESS + _postedActionType.value = ActionType.LONG_PRESS _effectProgress.value = null } - if (state != State.TIMEOUT_WAIT) { + if (_state.value != State.TIMEOUT_WAIT) { // This will happen if the animator did not finish by being cancelled - state = State.IDLE + setState(State.IDLE) } } private fun handleAnimationCancel() { - _effectProgress.value = 0f - startPressedTimeoutWait() - state = State.TIMEOUT_WAIT + _effectProgress.value = null + setState(State.TIMEOUT_WAIT) } - private fun handleTimeoutComplete() { - if (state == State.TIMEOUT_WAIT && !effectAnimator.isRunning) { - effectAnimator.start() + fun handleTimeoutComplete() { + if (_state.value == State.TIMEOUT_WAIT && effectAnimator?.isRunning == false) { + effectAnimator?.start() } } fun clearActionType() { - _actionType.value = null + _postedActionType.value = null + } + + /** Reset the effect by going back to a default [IDLE] state */ + fun resetEffect() { + if (effectAnimator?.isRunning == true) { + effectAnimator?.cancel() + } + longPressHint = null + effectAnimator = null + _effectProgress.value = null + _postedActionType.value = null + setState(State.IDLE) } /** * Reset the effect with a new effect duration. * - * The effect will go back to an [IDLE] state where it can begin its logic with a new duration. - * * @param[duration] New duration for the long-press effect + * @return true if the effect initialized correctly */ - fun resetWithDuration(duration: Int) { + fun initializeEffect(duration: Int): Boolean { // The effect can't reset if it is running - if (effectAnimator.isRunning) return + if (duration <= 0) return false + + resetEffect() + effectDuration = duration + effectAnimator = + ValueAnimator.ofFloat(0f, 1f).apply { + this.duration = effectDuration.toLong() + interpolator = AccelerateDecelerateInterpolator() - effectAnimator.duration = duration.toLong() - _effectProgress.value = 0f - _actionType.value = null - waitJob?.cancel() - state = State.IDLE + doOnStart { handleAnimationStart() } + addUpdateListener { _effectProgress.value = animatedValue as Float } + doOnEnd { handleAnimationComplete() } + doOnCancel { handleAnimationCancel() } + } + longPressHint = + LongPressHapticBuilder.createLongPressHint( + durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION, + durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION, + effectDuration + ) + return true } enum class State { @@ -243,6 +269,7 @@ class QSLongPressEffect( enum class ActionType { CLICK, LONG_PRESS, + RESET_AND_LONG_PRESS, } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt index f4998a7b8789..ddb9f35c74d9 100644 --- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt @@ -21,56 +21,68 @@ import androidx.lifecycle.repeatOnLifecycle import com.android.app.tracing.coroutines.launch import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.qs.tileimpl.QSTileViewImpl +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.launch -class QSLongPressEffectViewBinder { - - private var handle: DisposableHandle? = null - val isBound: Boolean - get() = handle != null - +// TODO(b/332903800) +object QSLongPressEffectViewBinder { fun bind( tile: QSTileViewImpl, + qsLongPressEffect: QSLongPressEffect?, tileSpec: String?, - effect: QSLongPressEffect?, - ) { - if (effect == null) return - - handle = - tile.repeatWhenAttached { - repeatOnLifecycle(Lifecycle.State.CREATED) { - effect.scope = this - val tag = "${tileSpec ?: "unknownTileSpec"}#LongPressEffect" + ): DisposableHandle? { + if (qsLongPressEffect == null) return null - launch("$tag#progress") { - effect.effectProgress.collect { progress -> - progress?.let { - if (it == 0f) { - tile.bringToFront() - } + return tile.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + val tag = "${tileSpec ?: "unknownTileSpec"}#LongPressEffect" + // Progress of the effect + launch("$tag#progress") { + qsLongPressEffect.effectProgress.collect { progress -> + progress?.let { + if (it == 0f) { + tile.bringToFront() + } else { tile.updateLongPressEffectProperties(it) } } } + } - launch("$tag#action") { - effect.actionType.collect { action -> - action?.let { - when (it) { - QSLongPressEffect.ActionType.CLICK -> tile.performClick() - QSLongPressEffect.ActionType.LONG_PRESS -> - tile.performLongClick() + // Action to perform + launch("$tag#action") { + qsLongPressEffect.actionType.collect { action -> + action?.let { + when (it) { + QSLongPressEffect.ActionType.CLICK -> tile.performClick() + QSLongPressEffect.ActionType.LONG_PRESS -> tile.performLongClick() + QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS -> { + tile.resetLongPressEffectProperties() + tile.performLongClick() } - effect.clearActionType() } + qsLongPressEffect.clearActionType() } } } - } - } - fun dispose() { - handle?.dispose() - handle = null + // Tap timeout wait + launch("$tag#timeout") { + qsLongPressEffect.shouldWaitForTapTimeout + .filter { it } + .collect { + try { + delay(QSLongPressEffect.PRESSED_TIMEOUT) + qsLongPressEffect.handleTimeoutComplete() + } catch (_: CancellationException) { + qsLongPressEffect.resetEffect() + } + } + } + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 6b53f4ed554f..a5d7e04bf4d0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -63,6 +63,7 @@ import android.view.SurfaceControl; import android.view.WindowManagerPolicyConstants; import android.window.IRemoteTransition; import android.window.IRemoteTransitionFinishedCallback; +import android.window.RemoteTransitionStub; import android.window.TransitionInfo; import com.android.internal.annotations.GuardedBy; @@ -187,7 +188,7 @@ public class KeyguardService extends Service { // Note: Also used for wrapping occlude by Dream animation. It works (with some redundancy). public static IRemoteTransition wrap(final KeyguardViewMediator keyguardViewMediator, final IRemoteAnimationRunner runner) { - return new IRemoteTransition.Stub() { + return new RemoteTransitionStub() { @GuardedBy("mLeashMap") private final ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = new ArrayMap<>(); @@ -253,11 +254,6 @@ public class KeyguardService extends Service { } } - @Override - public void onTransitionConsumed(IBinder transition, boolean aborted) { - // No-op. - } - private static void initAlphaForAnimationTargets(@NonNull SurfaceControl.Transaction t, @NonNull RemoteAnimationTarget[] targets) { for (RemoteAnimationTarget target : targets) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt index e6e6ff6dcadb..c32c226441fe 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt @@ -41,7 +41,6 @@ import com.android.keyguard.dagger.KeyguardStatusViewComponent import com.android.systemui.CoreStartable import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor @@ -73,7 +72,6 @@ import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator import dagger.Lazy import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -110,7 +108,6 @@ constructor( private val keyguardBlueprintViewBinder: KeyguardBlueprintViewBinder, private val clockInteractor: KeyguardClockInteractor, private val keyguardViewMediator: KeyguardViewMediator, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : CoreStartable { private var rootViewHandle: DisposableHandle? = null @@ -214,7 +211,6 @@ constructor( vibratorHelper, falsingManager, keyguardViewMediator, - mainImmediateDispatcher, ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 654610e8cae8..21af0a07a6d8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -137,6 +137,7 @@ import com.android.systemui.animation.ActivityTransitionAnimator; import com.android.systemui.animation.TransitionAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingCollector; +import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; @@ -584,7 +585,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private CentralSurfaces mCentralSurfaces; - private IRemoteAnimationFinishedCallback mUnoccludeFromDreamFinishedCallback; + private IRemoteAnimationFinishedCallback mUnoccludeFinishedCallback; private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = new DeviceConfig.OnPropertiesChangedListener() { @@ -1234,10 +1235,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mUnoccludeAnimator.cancel(); } - if (isDream) { + if (isDream || mShowCommunalByDefault) { initAlphaForAnimationTargets(wallpapers); - mDreamViewModel.get().startTransitionFromDream(); - mUnoccludeFromDreamFinishedCallback = finishedCallback; + if (isDream) { + mDreamViewModel.get().startTransitionFromDream(); + } + mUnoccludeFinishedCallback = finishedCallback; return; } @@ -1304,7 +1307,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private Consumer<Float> getRemoteSurfaceAlphaApplier() { return (Float alpha) -> { - if (mRemoteAnimationTarget == null) return; + if (mRemoteAnimationTarget == null) { + Log.e(TAG, "Attempting to set alpha on null animation target"); + return; + } final View localView = mKeyguardViewControllerLazy.get().getViewRootImpl().getView(); final SyncRtSurfaceTransactionApplier applier = new SyncRtSurfaceTransactionApplier(localView); @@ -1319,10 +1325,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private Consumer<TransitionStep> getFinishedCallbackConsumer() { return (TransitionStep step) -> { - if (mUnoccludeFromDreamFinishedCallback == null) return; + if (mUnoccludeFinishedCallback == null) return; try { - mUnoccludeFromDreamFinishedCallback.onAnimationFinished(); - mUnoccludeFromDreamFinishedCallback = null; + mUnoccludeFinishedCallback.onAnimationFinished(); + mUnoccludeFinishedCallback = null; } catch (RemoteException e) { Log.e(TAG, "Wasn't able to callback", e); } @@ -1365,7 +1371,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private final SessionTracker mSessionTracker; private final CoroutineDispatcher mMainDispatcher; private final Lazy<DreamViewModel> mDreamViewModel; + private final Lazy<CommunalTransitionViewModel> mCommunalTransitionViewModel; private RemoteAnimationTarget mRemoteAnimationTarget; + private boolean mShowCommunalByDefault = false; private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager; @@ -1414,6 +1422,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, SystemClock systemClock, @Main CoroutineDispatcher mainDispatcher, Lazy<DreamViewModel> dreamViewModel, + Lazy<CommunalTransitionViewModel> communalTransitionViewModel, SystemPropertiesHelper systemPropertiesHelper, Lazy<WindowManagerLockscreenVisibilityManager> wmLockscreenVisibilityManager, SelectedUserInteractor selectedUserInteractor, @@ -1485,6 +1494,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mSessionTracker = sessionTracker; mDreamViewModel = dreamViewModel; + mCommunalTransitionViewModel = communalTransitionViewModel; mWmLockscreenVisibilityManager = wmLockscreenVisibilityManager; mMainDispatcher = mainDispatcher; @@ -1615,11 +1625,21 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, ViewRootImpl viewRootImpl = mKeyguardViewControllerLazy.get().getViewRootImpl(); if (viewRootImpl != null) { - final DreamViewModel viewModel = mDreamViewModel.get(); - collectFlow(viewRootImpl.getView(), viewModel.getDreamAlpha(), + final DreamViewModel dreamViewModel = mDreamViewModel.get(); + final CommunalTransitionViewModel communalViewModel = + mCommunalTransitionViewModel.get(); + collectFlow(viewRootImpl.getView(), dreamViewModel.getDreamAlpha(), getRemoteSurfaceAlphaApplier(), mMainDispatcher); - collectFlow(viewRootImpl.getView(), viewModel.getTransitionEnded(), + collectFlow(viewRootImpl.getView(), dreamViewModel.getTransitionEnded(), getFinishedCallbackConsumer(), mMainDispatcher); + collectFlow(viewRootImpl.getView(), communalViewModel.getShowByDefault(), + (showByDefault) -> + mShowCommunalByDefault = showByDefault, mMainDispatcher); + collectFlow(viewRootImpl.getView(), + communalViewModel.getTransitionFromOccludedEnded(), + getFinishedCallbackConsumer(), mMainDispatcher); + } else { + Log.e(TAG, "Keyguard ViewRootImpl is null"); } } // Most services aren't available until the system reaches the ready state, so we @@ -3539,15 +3559,14 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, ShadeLockscreenInteractor shadeLockscreenInteractor, @Nullable ShadeExpansionStateManager shadeExpansionStateManager, BiometricUnlockController biometricUnlockController, - View notificationContainer, KeyguardBypassController bypassController) { + View notificationContainer) { mCentralSurfaces = centralSurfaces; mKeyguardViewControllerLazy.get().registerCentralSurfaces( centralSurfaces, shadeLockscreenInteractor, shadeExpansionStateManager, biometricUnlockController, - notificationContainer, - bypassController); + notificationContainer); return mKeyguardViewControllerLazy.get(); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt index e101b0ab64aa..a65a8827fa48 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt @@ -29,6 +29,7 @@ import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.utils.GlobalWindowManager @@ -83,7 +84,7 @@ constructor( applicationScope.launch(bgDispatcher) { // We drop 1 to avoid triggering on initial collect(). - keyguardTransitionInteractor.anyStateToGoneTransition.collect { transition -> + keyguardTransitionInteractor.transition(to = GONE).collect { transition -> if (transition.transitionState == TransitionState.FINISHED) { onKeyguardGone() } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index a243b8eec264..7879ab6e1ed2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -39,6 +39,7 @@ import com.android.systemui.animation.ActivityTransitionAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingModule; +import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; @@ -161,6 +162,7 @@ public interface KeyguardModule { SystemClock systemClock, @Main CoroutineDispatcher mainDispatcher, Lazy<DreamViewModel> dreamViewModel, + Lazy<CommunalTransitionViewModel> communalTransitionViewModel, SystemPropertiesHelper systemPropertiesHelper, Lazy<WindowManagerLockscreenVisibilityManager> wmLockscreenVisibilityManager, SelectedUserInteractor selectedUserInteractor, @@ -208,6 +210,7 @@ public interface KeyguardModule { systemClock, mainDispatcher, dreamViewModel, + communalTransitionViewModel, systemPropertiesHelper, wmLockscreenVisibilityManager, selectedUserInteractor, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt index 3f4d3a8544d0..6c29bce616bc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.data.repository +import android.content.Context import android.os.UserHandle import android.provider.Settings import com.android.keyguard.ClockEventController @@ -24,9 +25,12 @@ import com.android.keyguard.KeyguardClockSwitch.LARGE import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.flags.FeatureFlagsClassic +import com.android.systemui.flags.Flags import com.android.systemui.keyguard.shared.model.SettingsClockSize import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.plugins.clocks.ClockId +import com.android.systemui.res.R import com.android.systemui.shared.clocks.ClockRegistry import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow @@ -47,7 +51,11 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext interface KeyguardClockRepository { - /** clock size determined by notificationPanelViewController, LARGE or SMALL */ + /** + * clock size determined by notificationPanelViewController, LARGE or SMALL + * + * @deprecated When scene container flag is on use clockSize from domain level. + */ val clockSize: StateFlow<Int> /** clock size selected in picker, DYNAMIC or SMALL */ @@ -61,6 +69,9 @@ interface KeyguardClockRepository { val previewClock: Flow<ClockController> val clockEventController: ClockEventController + + val shouldForceSmallClock: Boolean + fun setClockSize(@ClockSize size: Int) } @@ -73,6 +84,8 @@ constructor( override val clockEventController: ClockEventController, @Background private val backgroundDispatcher: CoroutineDispatcher, @Application private val applicationScope: CoroutineScope, + @Application private val applicationContext: Context, + private val featureFlags: FeatureFlagsClassic, ) : KeyguardClockRepository { /** Receive SMALL or LARGE clock should be displayed on keyguard. */ @@ -135,6 +148,12 @@ constructor( clockRegistry.createCurrentClock() } + override val shouldForceSmallClock: Boolean + get() = + featureFlags.isEnabled(Flags.LOCKSCREEN_ENABLE_LANDSCAPE) && + // True on small landscape screens + applicationContext.resources.getBoolean(R.bool.force_small_clock_on_lockscreen) + private fun getClockSize(): SettingsClockSize { return if ( secureSettings.getIntForUser( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt index 1298fa5af033..462d8373a430 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt @@ -206,7 +206,11 @@ interface KeyguardRepository { ) val keyguardDoneAnimationsFinished: Flow<Unit> - /** Receive whether clock should be centered on lockscreen. */ + /** + * Receive whether clock should be centered on lockscreen. + * + * @deprecated When scene container flag is on use clockShouldBeCentered from domain level. + */ val clockShouldBeCentered: Flow<Boolean> /** diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt index bf1f07479f34..eef4b97ae34d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt @@ -27,7 +27,7 @@ import com.android.systemui.keyguard.data.repository.BiometricType import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.SceneInteractor -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -52,7 +52,6 @@ constructor( @Application private val applicationScope: CoroutineScope, @Application private val context: Context, deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository, - private val sceneContainerFlags: SceneContainerFlags, private val sceneInteractor: SceneInteractor, private val primaryBouncerInteractor: PrimaryBouncerInteractor, alternateBouncerInteractor: AlternateBouncerInteractor, @@ -75,7 +74,7 @@ constructor( get() = context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer) private val isBouncerSceneActive: Flow<Boolean> = - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { sceneInteractor.currentScene.map { it == Scenes.Bouncer }.distinctUntilChanged() } else { flowOf(false) @@ -115,7 +114,7 @@ constructor( .distinctUntilChanged() private fun isBouncerActive(): Boolean { - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { return sceneInteractor.currentScene.value == Scenes.Bouncer } return primaryBouncerInteractor.isBouncerShowing() && diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index bef5ee507128..b8ceab3f0a38 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -30,6 +30,7 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine +import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds @@ -71,6 +72,7 @@ constructor( listenForDreamingToAodOrDozing() listenForTransitionToCamera(scope, keyguardInteractor) listenForDreamingToGlanceableHub() + listenForDreamingToPrimaryBouncer() } private fun listenForDreamingToGlanceableHub() { @@ -84,6 +86,21 @@ constructor( } } + private fun listenForDreamingToPrimaryBouncer() { + scope.launch { + keyguardInteractor.primaryBouncerShowing + .sample(startedKeyguardTransitionStep, ::Pair) + .collect { pair -> + val (isBouncerShowing, lastStartedTransitionStep) = pair + if ( + isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.DREAMING + ) { + startTransitionTo(KeyguardState.PRIMARY_BOUNCER) + } + } + } + } + fun startToLockscreenTransition() { scope.launch { KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt index b6289d44e2c3..ee589f4a235c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt @@ -87,12 +87,12 @@ constructor( scope.launch { keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop .filterRelevantKeyguardStateAnd { onTop -> !onTop } - .sample(communalInteractor.isIdleOnCommunal, ::Pair) - .collect { (_, isIdleOnCommunal) -> + .sample(communalInteractor.isIdleOnCommunal, communalInteractor.showByDefault) + .collect { (_, isIdleOnCommunal, showCommunalByDefault) -> // Occlusion signals come from the framework, and should interrupt any // existing transition val to = - if (isIdleOnCommunal) { + if (isIdleOnCommunal || showCommunalByDefault) { KeyguardState.GLANCEABLE_HUB } else { KeyguardState.LOCKSCREEN @@ -106,15 +106,16 @@ constructor( .sample( keyguardInteractor.isKeyguardShowing, communalInteractor.isIdleOnCommunal, + communalInteractor.showByDefault, ) - .filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _) -> + .filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _, _) -> !isOccluded && isShowing } - .collect { (_, _, isIdleOnCommunal) -> + .collect { (_, _, isIdleOnCommunal, showCommunalByDefault) -> // Occlusion signals come from the framework, and should interrupt any // existing transition val to = - if (isIdleOnCommunal) { + if (isIdleOnCommunal || showCommunalByDefault) { KeyguardState.GLANCEABLE_HUB } else { KeyguardState.LOCKSCREEN @@ -175,6 +176,7 @@ constructor( duration = when (toState) { KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION + KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION else -> DEFAULT_DURATION }.inWholeMilliseconds } @@ -184,6 +186,7 @@ constructor( const val TAG = "FromOccludedTransitionInteractor" private val DEFAULT_DURATION = 500.milliseconds val TO_LOCKSCREEN_DURATION = 933.milliseconds + val TO_GLANCEABLE_HUB_DURATION = 250.milliseconds val TO_AOD_DURATION = DEFAULT_DURATION val TO_DOZING_DURATION = DEFAULT_DURATION } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt index d39bd3d5eb12..720baec54190 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt @@ -83,19 +83,12 @@ constructor( private fun updateBlueprint() { val useSplitShade = splitShadeStateController.shouldUseSplitNotificationShade(context.resources) - // TODO(b/326098079): Make ID a constant value. - val useWeatherClockLayout = - clockInteractor.currentClock.value?.config?.id == "DIGITAL_CLOCK_WEATHER" && - ComposeLockscreen.isEnabled val blueprintId = when { - useWeatherClockLayout && useSplitShade -> SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID - useWeatherClockLayout -> WEATHER_CLOCK_BLUEPRINT_ID useSplitShade && !ComposeLockscreen.isEnabled -> SplitShadeKeyguardBlueprint.ID else -> DefaultKeyguardBlueprint.DEFAULT } - transitionToBlueprint(blueprintId) } @@ -128,13 +121,4 @@ constructor( fun getCurrentBlueprint(): KeyguardBlueprint { return keyguardBlueprintRepository.blueprint.value } - - companion object { - /** - * These values live here because classes in the composable package do not exist in some - * systems. - */ - const val WEATHER_CLOCK_BLUEPRINT_ID = "weather-clock" - const val SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID = "split-shade-weather-clock" - } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt index d551c9b9a4de..f7f60a5a72a4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt @@ -21,23 +21,48 @@ import android.util.Log import com.android.keyguard.ClockEventController import com.android.keyguard.KeyguardClockSwitch import com.android.keyguard.KeyguardClockSwitch.ClockSize +import com.android.keyguard.KeyguardClockSwitch.LARGE +import com.android.keyguard.KeyguardClockSwitch.SMALL import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardClockRepository +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.SettingsClockSize +import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.plugins.clocks.ClockId +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.shade.domain.interactor.ShadeInteractor +import com.android.systemui.shade.shared.model.ShadeMode +import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor +import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor +import com.android.systemui.util.kotlin.combine import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn private val TAG = KeyguardClockInteractor::class.simpleName -/** Manages and ecapsulates the clock components of the lockscreen root view. */ +/** Manages and encapsulates the clock components of the lockscreen root view. */ @SysUISingleton class KeyguardClockInteractor @Inject constructor( + mediaCarouselInteractor: MediaCarouselInteractor, + activeNotificationsInteractor: ActiveNotificationsInteractor, + shadeInteractor: ShadeInteractor, + keyguardInteractor: KeyguardInteractor, + keyguardTransitionInteractor: KeyguardTransitionInteractor, + headsUpNotificationInteractor: HeadsUpNotificationInteractor, + @Application private val applicationScope: CoroutineScope, private val keyguardClockRepository: KeyguardClockRepository, ) { + private val isOnAod: Flow<Boolean> = + keyguardTransitionInteractor.currentKeyguardState.map { it == KeyguardState.AOD } val selectedClockSize: StateFlow<SettingsClockSize> = keyguardClockRepository.selectedClockSize @@ -51,7 +76,64 @@ constructor( var clock: ClockController? by keyguardClockRepository.clockEventController::clock - val clockSize: StateFlow<Int> = keyguardClockRepository.clockSize + // TODO (b/333389512): Convert this into a more readable enum. + val clockSize: StateFlow<Int> = + if (SceneContainerFlag.isEnabled) { + combine( + shadeInteractor.shadeMode, + activeNotificationsInteractor.areAnyNotificationsPresent, + mediaCarouselInteractor.hasActiveMediaOrRecommendation, + keyguardInteractor.isDozing, + isOnAod, + ) { shadeMode, hasNotifs, hasMedia, isDozing, isOnAod -> + return@combine when { + keyguardClockRepository.shouldForceSmallClock && !isOnAod -> SMALL + shadeMode == ShadeMode.Single && (hasNotifs || hasMedia) -> SMALL + shadeMode == ShadeMode.Single -> LARGE + hasMedia && !isDozing -> SMALL + else -> LARGE + } + } + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = LARGE + ) + } else { + SceneContainerFlag.assertInLegacyMode() + keyguardClockRepository.clockSize + } + + val clockShouldBeCentered: Flow<Boolean> = + if (SceneContainerFlag.isEnabled) { + combine( + shadeInteractor.shadeMode, + activeNotificationsInteractor.areAnyNotificationsPresent, + keyguardInteractor.isActiveDreamLockscreenHosted, + isOnAod, + headsUpNotificationInteractor.isHeadsUpOrAnimatingAway, + keyguardInteractor.isDozing, + ) { + shadeMode, + areAnyNotificationsPresent, + isActiveDreamLockscreenHosted, + isOnAod, + isHeadsUp, + isDozing -> + when { + shadeMode != ShadeMode.Split -> true + !areAnyNotificationsPresent -> true + isActiveDreamLockscreenHosted -> true + // Pulsing notification appears on the right. Move clock left to avoid overlap. + isHeadsUp && isDozing -> false + else -> isOnAod + } + } + } else { + SceneContainerFlag.assertInLegacyMode() + keyguardInteractor.clockShouldBeCentered + } + fun setClockSize(@ClockSize size: Int) { keyguardClockRepository.setClockSize(size) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 2182fe378d2f..7224536cfe70 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -44,7 +44,7 @@ import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.SceneInteractor -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.CommandQueue @@ -84,7 +84,6 @@ constructor( private val repository: KeyguardRepository, private val commandQueue: CommandQueue, powerInteractor: PowerInteractor, - sceneContainerFlags: SceneContainerFlags, bouncerRepository: KeyguardBouncerRepository, configurationInteractor: ConfigurationInteractor, shadeRepository: ShadeRepository, @@ -210,7 +209,8 @@ constructor( keyguardTransitionInteractor .transitionValue(GONE) .map { it == 1f } - .onStart { emit(false) }, + .onStart { emit(false) } + .distinctUntilChanged(), repository.topClippingBounds ) { _, isGone, topClippingBounds -> if (!isGone) { @@ -330,7 +330,7 @@ constructor( /** Whether to animate the next doze mode transition. */ val animateDozingTransitions: Flow<Boolean> by lazy { - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { sceneInteractorProvider .get() .transitioningTo diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt index 80e94a27bec5..20b7b2a91ade 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt @@ -23,12 +23,14 @@ import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVi import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardSurfaceBehindModel import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor +import com.android.systemui.util.kotlin.sample import com.android.systemui.util.kotlin.toPx import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map /** * Distance over which the surface behind the keyguard is animated in during a Y-translation @@ -96,13 +98,21 @@ constructor( .distinctUntilChanged() /** + * Whether a notification launch animation is running when we're not already in the GONE state. + */ + private val isNotificationLaunchAnimationRunningOnKeyguard = + notificationLaunchInteractor.isLaunchAnimationRunning + .sample(transitionInteractor.finishedKeyguardState) + .map { it != KeyguardState.GONE } + + /** * Whether we're animating the surface, or a notification launch animation is running (which * means we're going to animate the surface, even if animators aren't yet running). */ val isAnimatingSurface = combine( repository.isAnimatingSurface, - notificationLaunchInteractor.isLaunchAnimationRunning + isNotificationLaunchAnimationRunningOnKeyguard, ) { animatingSurface, animatingLaunch -> animatingSurface || animatingLaunch } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt index 97081d93892a..a18579d9c8e0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt @@ -20,19 +20,14 @@ package com.android.systemui.keyguard.domain.interactor import android.util.Log import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING -import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING -import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING_LOCKSCREEN_HOSTED -import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB -import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN -import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED import com.android.systemui.keyguard.shared.model.KeyguardState.OFF import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER import com.android.systemui.keyguard.shared.model.TransitionInfo @@ -40,7 +35,6 @@ import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.BufferOverflow @@ -53,6 +47,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -64,7 +59,6 @@ class KeyguardTransitionInteractor @Inject constructor( @Application val scope: CoroutineScope, - @Main private val mainDispatcher: CoroutineDispatcher, private val keyguardRepository: KeyguardRepository, private val repository: KeyguardTransitionRepository, private val fromLockscreenTransitionInteractor: dagger.Lazy<FromLockscreenTransitionInteractor>, @@ -75,14 +69,13 @@ constructor( dagger.Lazy<FromAlternateBouncerTransitionInteractor>, private val fromDozingTransitionInteractor: dagger.Lazy<FromDozingTransitionInteractor>, ) { - private val TAG = this::class.simpleName - - private val transitionValueCache = mutableMapOf<KeyguardState, MutableSharedFlow<Float>>() + private val transitionMap = mutableMapOf<Edge, MutableSharedFlow<TransitionStep>>() /** * Numerous flows are derived from, or care directly about, the transition value in and out of a * single state. This prevent the redundant filters from running. */ + private val transitionValueCache = mutableMapOf<KeyguardState, MutableSharedFlow<Float>>() private fun getTransitionValueFlow(state: KeyguardState): MutableSharedFlow<Float> { return transitionValueCache.getOrPut(state) { MutableSharedFlow<Float>( @@ -94,6 +87,7 @@ constructor( } } + @Deprecated("Not performant - Use something else in this class") val transitions = repository.transitions /** @@ -106,14 +100,14 @@ constructor( * from when we were canceled. */ val startedStepWithPrecedingStep = - transitions + repository.transitions .pairwise() .filter { it.newValue.transitionState == TransitionState.STARTED } .shareIn(scope, SharingStarted.Eagerly) init { // Collect non-canceled steps and emit transition values. - scope.launch(mainDispatcher) { + scope.launch { repository.transitions .filter { it.transitionState != TransitionState.CANCELED } .collect { step -> @@ -122,11 +116,22 @@ constructor( } } + scope.launch { + repository.transitions.collect { + // FROM->TO + transitionMap[Edge(it.from, it.to)]?.emit(it) + // FROM->(ANY) + transitionMap[Edge(it.from, null)]?.emit(it) + // (ANY)->TO + transitionMap[Edge(null, it.to)]?.emit(it) + } + } + // If a transition from state A -> B is canceled in favor of a transition from B -> C, we // need to ensure we emit transitionValue(A) = 0f, since no further steps will be emitted // where the from or to states are A. This would leave transitionValue(A) stuck at an // arbitrary non-zero value. - scope.launch(mainDispatcher) { + scope.launch { startedStepWithPrecedingStep.collect { (prevStep, startedStep) -> if ( prevStep.transitionState == TransitionState.CANCELED && @@ -138,116 +143,42 @@ constructor( } } - /** (any)->GONE transition information */ - val anyStateToGoneTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == GONE } - - /** (any)->AOD transition information */ - val anyStateToAodTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == AOD } - - /** DREAMING->(any) transition information. */ - val fromDreamingTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.from == DREAMING } - - /** LOCKSCREEN->(any) transition information. */ - val fromLockscreenTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.from == LOCKSCREEN } - - /** (any)->Lockscreen transition information */ - val anyStateToLockscreenTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == LOCKSCREEN } - - /** (any)->Occluded transition information */ - val anyStateToOccludedTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == OCCLUDED } - - /** (any)->PrimaryBouncer transition information */ - val anyStateToPrimaryBouncerTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == PRIMARY_BOUNCER } - - /** (any)->Dreaming transition information */ - val anyStateToDreamingTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == DREAMING } - - /** (any)->AlternateBouncer transition information */ - val anyStateToAlternateBouncerTransition: Flow<TransitionStep> = - repository.transitions.filter { step -> step.to == ALTERNATE_BOUNCER } - - /** AOD->LOCKSCREEN transition information. */ - val aodToLockscreenTransition: Flow<TransitionStep> = repository.transition(AOD, LOCKSCREEN) - - /** DREAMING->LOCKSCREEN transition information. */ - val dreamingToLockscreenTransition: Flow<TransitionStep> = - repository.transition(DREAMING, LOCKSCREEN) - - /** DREAMING_LOCKSCREEN_HOSTED->LOCKSCREEN transition information. */ - val dreamingLockscreenHostedToLockscreenTransition: Flow<TransitionStep> = - repository.transition(DREAMING_LOCKSCREEN_HOSTED, LOCKSCREEN) - - /** GONE->AOD transition information. */ - val goneToAodTransition: Flow<TransitionStep> = repository.transition(GONE, AOD) - - /** GONE->DREAMING transition information. */ - val goneToDreamingTransition: Flow<TransitionStep> = repository.transition(GONE, DREAMING) - - /** GONE->DREAMING_LOCKSCREEN_HOSTED transition information. */ - val goneToDreamingLockscreenHostedTransition: Flow<TransitionStep> = - repository.transition(GONE, DREAMING_LOCKSCREEN_HOSTED) - - /** GONE->LOCKSCREEN transition information. */ - val goneToLockscreenTransition: Flow<TransitionStep> = repository.transition(GONE, LOCKSCREEN) - - /** LOCKSCREEN->AOD transition information. */ - val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD) - - /** LOCKSCREEN->DOZING transition information. */ - val lockscreenToDozingTransition: Flow<TransitionStep> = - repository.transition(LOCKSCREEN, DOZING) - - /** LOCKSCREEN->DREAMING transition information. */ - val lockscreenToDreamingTransition: Flow<TransitionStep> = - repository.transition(LOCKSCREEN, DREAMING) - - /** LOCKSCREEN->DREAMING_LOCKSCREEN_HOSTED transition information. */ - val lockscreenToDreamingLockscreenHostedTransition: Flow<TransitionStep> = - repository.transition(LOCKSCREEN, DREAMING_LOCKSCREEN_HOSTED) - - /** LOCKSCREEN->GLANCEABLE_HUB transition information. */ - val lockscreenToGlanceableHubTransition: Flow<TransitionStep> = - repository.transition(LOCKSCREEN, GLANCEABLE_HUB) - - /** LOCKSCREEN->OCCLUDED transition information. */ - val lockscreenToOccludedTransition: Flow<TransitionStep> = - repository.transition(LOCKSCREEN, OCCLUDED) - - /** GLANCEABLE_HUB->LOCKSCREEN transition information. */ - val glanceableHubToLockscreenTransition: Flow<TransitionStep> = - repository.transition(GLANCEABLE_HUB, LOCKSCREEN) - - /** OCCLUDED->LOCKSCREEN transition information. */ - val occludedToLockscreenTransition: Flow<TransitionStep> = - repository.transition(OCCLUDED, LOCKSCREEN) - - /** PRIMARY_BOUNCER->GONE transition information. */ - val primaryBouncerToGoneTransition: Flow<TransitionStep> = - repository.transition(PRIMARY_BOUNCER, GONE) - - /** OFF->LOCKSCREEN transition information. */ - val offToLockscreenTransition: Flow<TransitionStep> = repository.transition(OFF, LOCKSCREEN) + /** Given an [edge], return a SharedFlow to collect only relevant [TransitionStep]. */ + fun getOrCreateFlow(edge: Edge): MutableSharedFlow<TransitionStep> { + return transitionMap.getOrPut(edge) { + MutableSharedFlow<TransitionStep>( + extraBufferCapacity = 10, + onBufferOverflow = BufferOverflow.DROP_OLDEST + ) + } + } - /** DOZING->LOCKSCREEN transition information. */ - val dozingToLockscreenTransition: Flow<TransitionStep> = - repository.transition(DOZING, LOCKSCREEN) + /** + * Receive all [TransitionStep] matching a filter of [from]->[to]. Allow nulls in order to match + * any transition, for instance (any)->GONE. + */ + fun transition(from: KeyguardState? = null, to: KeyguardState? = null): Flow<TransitionStep> { + if (from == null && to == null) { + throw IllegalArgumentException("from and to cannot both be null") + } + return getOrCreateFlow(Edge(from = from, to = to)) + } - /** Receive all [TransitionStep] matching a filter of [from]->[to] */ - fun transition(from: KeyguardState, to: KeyguardState): Flow<TransitionStep> { - return repository.transition(from, to) + /** + * The amount of transition into or out of the given [KeyguardState]. + * + * The value will be `0` (or close to `0`, due to float point arithmetic) if not in this step or + * `1` when fully in the given state. + */ + fun transitionValue( + state: KeyguardState, + ): Flow<Float> { + return getTransitionValueFlow(state) } /** - * AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <-> - * Lockscreen (0f). + * AOD<->* transition information, mapped to dozeAmount range of AOD (1f) <-> + * * (0f). */ val dozeAmountTransition: Flow<TransitionStep> = repository.transitions @@ -265,10 +196,6 @@ constructor( val startedKeyguardTransitionStep: Flow<TransitionStep> = repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED } - /** The last [TransitionStep] with a [TransitionState] of CANCELED */ - val canceledKeyguardTransitionStep: Flow<TransitionStep> = - repository.transitions.filter { step -> step.transitionState == TransitionState.CANCELED } - /** The last [TransitionStep] with a [TransitionState] of FINISHED */ val finishedKeyguardTransitionStep: Flow<TransitionStep> = repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED } @@ -364,10 +291,6 @@ constructor( * case, the smartspace will never be set to alpha = 1f and you'll have a half-faded smartspace * during the LS -> GONE transition. * - * If you need special-case handling for cancellations (such as conditional handling depending - * on which [KeyguardState] was canceled) you can collect [canceledKeyguardTransitionStep] - * directly. - * * As a helpful footnote, here's the values of [finishedKeyguardState] and * [currentKeyguardState] during a sequence with two cancellations: * 1. We're FINISHED in GONE. currentKeyguardState=GONE; finishedKeyguardState=GONE. @@ -390,7 +313,7 @@ constructor( } } .distinctUntilChanged() - .shareIn(scope, SharingStarted.Eagerly, replay = 1) + .stateIn(scope, SharingStarted.Eagerly, KeyguardState.OFF) /** * The [TransitionInfo] of the most recent call to @@ -420,24 +343,12 @@ constructor( /** Whether we've currently STARTED a transition and haven't yet FINISHED it. */ val isInTransitionToAnyState = isInTransitionWhere({ true }, { true }) - /** - * The amount of transition into or out of the given [KeyguardState]. - * - * The value will be `0` (or close to `0`, due to float point arithmetic) if not in this step or - * `1` when fully in the given state. - */ - fun transitionValue( - state: KeyguardState, - ): Flow<Float> { - return getTransitionValueFlow(state) - } - fun transitionStepsFromState(fromState: KeyguardState): Flow<TransitionStep> { - return repository.transitions.filter { step -> step.from == fromState } + return getOrCreateFlow(Edge(from = fromState, to = null)) } fun transitionStepsToState(toState: KeyguardState): Flow<TransitionStep> { - return repository.transitions.filter { step -> step.to == toState } + return getOrCreateFlow(Edge(from = null, to = toState)) } /** @@ -464,17 +375,24 @@ constructor( fun isInTransitionToState( state: KeyguardState, ): Flow<Boolean> { - return isInTransitionToStateWhere { it == state } + return getOrCreateFlow(Edge(from = null, to = state)) + .mapLatest { it.transitionState.isTransitioning() } + .onStart { emit(false) } + .distinctUntilChanged() } /** - * Whether we're in a transition to a [KeyguardState] that matches the given predicate, but - * haven't yet completed it. + * Whether we're in a transition to and from the given [KeyguardState]s, but haven't yet + * completed it. */ - fun isInTransitionToStateWhere( - stateMatcher: (KeyguardState) -> Boolean, + fun isInTransition( + from: KeyguardState, + to: KeyguardState, ): Flow<Boolean> { - return isInTransitionWhere(fromStatePredicate = { true }, toStatePredicate = stateMatcher) + return getOrCreateFlow(Edge(from = from, to = to)) + .mapLatest { it.transitionState.isTransitioning() } + .onStart { emit(false) } + .distinctUntilChanged() } /** @@ -483,12 +401,29 @@ constructor( fun isInTransitionFromState( state: KeyguardState, ): Flow<Boolean> { - return isInTransitionFromStateWhere { it == state } + return getOrCreateFlow(Edge(from = state, to = null)) + .mapLatest { it.transitionState.isTransitioning() } + .onStart { emit(false) } + .distinctUntilChanged() + } + + /** + * Whether we're in a transition to a [KeyguardState] that matches the given predicate, but + * haven't yet completed it. + * + * If you only care about a single state, instead use the optimized [isInTransitionToState]. + */ + fun isInTransitionToStateWhere( + stateMatcher: (KeyguardState) -> Boolean, + ): Flow<Boolean> { + return isInTransitionWhere(fromStatePredicate = { true }, toStatePredicate = stateMatcher) } /** * Whether we're in a transition out of a [KeyguardState] that matches the given predicate, but * haven't yet completed it. + * + * If you only care about a single state, instead use the optimized [isInTransitionFromState]. */ fun isInTransitionFromStateWhere( stateMatcher: (KeyguardState) -> Boolean, @@ -499,6 +434,9 @@ constructor( /** * Whether we're in a transition between two [KeyguardState]s that match the given predicates, * but haven't yet completed it. + * + * If you only care about a single state for both from and to, instead use the optimized + * [isInTransition]. */ fun isInTransitionWhere( fromStatePredicate: (KeyguardState) -> Boolean, @@ -507,6 +445,13 @@ constructor( return isInTransitionWhere { from, to -> fromStatePredicate(from) && toStatePredicate(to) } } + /** + * Whether we're in a transition between two [KeyguardState]s that match the given predicates, + * but haven't yet completed it. + * + * If you only care about a single state for both from and to, instead use the optimized + * [isInTransition]. + */ fun isInTransitionWhere( fromToStatePredicate: (KeyguardState, KeyguardState) -> Boolean ): Flow<Boolean> { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt new file mode 100644 index 000000000000..a43eb710e880 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.shared + +import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken +import com.android.systemui.flags.RefactorFlagUtils + +/** Helper for reading or using the refactor_keyguard_dismiss_intent flag. */ +@Suppress("NOTHING_TO_INLINE") +object RefactorKeyguardDismissIntent { + /** The aconfig flag name */ + const val FLAG_NAME = Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT + + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + + /** Is the refactor enabled */ + @JvmStatic + inline val isEnabled + get() = Flags.refactorKeyguardDismissIntent() + + /** + * Called to ensure code is only run when the flag is enabled. This protects users from the + * unintended behaviors caused by accidentally running new logic, while also crashing on an eng + * build to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun isUnexpectedlyInLegacyMode() = + RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) + + /** + * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is enabled to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt index 38a93b50ea97..1cd188c9dc1a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt @@ -18,11 +18,21 @@ package com.android.systemui.keyguard.shared.model /** Possible states for a running transition between [State] */ enum class TransitionState { /* Transition has begun. */ - STARTED, + STARTED { + override fun isTransitioning() = true + }, /* Transition is actively running. */ - RUNNING, + RUNNING { + override fun isTransitioning() = true + }, /* Transition has completed successfully. */ - FINISHED, + FINISHED { + override fun isTransitioning() = false + }, /* Transition has been interrupted, and not completed successfully. */ - CANCELED, + CANCELED { + override fun isTransitioning() = false + }; + + abstract fun isTransitioning(): Boolean } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt index 5de1a61d61b5..735b10907c73 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt @@ -19,8 +19,6 @@ import android.view.animation.Interpolator import com.android.app.animation.Interpolators.LINEAR import com.android.keyguard.logging.KeyguardTransitionAnimationLogger import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState @@ -35,15 +33,10 @@ import kotlin.math.max import kotlin.math.min import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull -import kotlinx.coroutines.launch /** * Assists in creating sub-flows for a KeyguardTransition. Call [setup] once for a transition, and @@ -53,35 +46,9 @@ import kotlinx.coroutines.launch class KeyguardTransitionAnimationFlow @Inject constructor( - @Application private val scope: CoroutineScope, - @Main private val mainDispatcher: CoroutineDispatcher, private val transitionInteractor: KeyguardTransitionInteractor, private val logger: KeyguardTransitionAnimationLogger, ) { - private val transitionMap = mutableMapOf<Edge, MutableSharedFlow<TransitionStep>>() - - init { - scope.launch(mainDispatcher) { - transitionInteractor.transitions.collect { - // FROM->TO - transitionMap[Edge(it.from, it.to)]?.emit(it) - // FROM->(ANY) - transitionMap[Edge(it.from, null)]?.emit(it) - // (ANY)->TO - transitionMap[Edge(null, it.to)]?.emit(it) - } - } - } - - private fun getOrCreateFlow(edge: Edge): MutableSharedFlow<TransitionStep> { - return transitionMap.getOrPut(edge) { - MutableSharedFlow<TransitionStep>( - extraBufferCapacity = 10, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - } - } - /** Invoke once per transition between FROM->TO states to get access to a shared flow. */ fun setup( duration: Duration, @@ -185,7 +152,8 @@ constructor( }?.let { onStep(interpolator.getInterpolation(it)) } } - return getOrCreateFlow(edge) + return transitionInteractor + .getOrCreateFlow(edge) .map { step -> StateToValue( from = step.from, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt index e423fe0bd8a0..f46a207b273a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt @@ -25,7 +25,6 @@ import android.view.View import androidx.core.view.isInvisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle -import com.android.app.tracing.coroutines.launch import com.android.systemui.common.ui.view.LongPressHandlingView import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.ui.view.DeviceEntryIconView @@ -35,15 +34,13 @@ import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager import com.android.systemui.statusbar.VibratorHelper -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch @ExperimentalCoroutinesApi object DeviceEntryIconViewBinder { - private const val TAG = "DeviceEntryIconViewBinder" - /** * Updates UI for: * - device entry containing view (parent view for the below views) @@ -61,7 +58,6 @@ object DeviceEntryIconViewBinder { bgViewModel: DeviceEntryBackgroundViewModel, falsingManager: FalsingManager, vibratorHelper: VibratorHelper, - mainImmediateDispatcher: CoroutineDispatcher, ) { DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode() val longPressHandlingView = view.longPressHandlingView @@ -77,33 +73,31 @@ object DeviceEntryIconViewBinder { view, HapticFeedbackConstants.CONFIRM, ) - applicationScope.launch("$TAG#viewModel.onLongPress") { - viewModel.onLongPress() - } + applicationScope.launch { viewModel.onLongPress() } } } - view.repeatWhenAttached(mainImmediateDispatcher) { + view.repeatWhenAttached { // Repeat on CREATED so that the view will always observe the entire // GONE => AOD transition (even though the view may not be visible until the middle // of the transition. repeatOnLifecycle(Lifecycle.State.CREATED) { - launch("$TAG#viewModel.isVisible") { + launch { viewModel.isVisible.collect { isVisible -> longPressHandlingView.isInvisible = !isVisible } } - launch("$TAG#viewModel.isLongPressEnabled") { + launch { viewModel.isLongPressEnabled.collect { isEnabled -> longPressHandlingView.setLongPressHandlingEnabled(isEnabled) } } - launch("$TAG#viewModel.accessibilityDelegateHint") { + launch { viewModel.accessibilityDelegateHint.collect { hint -> view.accessibilityHintType = hint } } - launch("$TAG#viewModel.useBackgroundProtection") { + launch { viewModel.useBackgroundProtection.collect { useBackgroundProtection -> if (useBackgroundProtection) { bgView.visibility = View.VISIBLE @@ -112,7 +106,7 @@ object DeviceEntryIconViewBinder { } } } - launch("$TAG#viewModel.burnInOffsets") { + launch { viewModel.burnInOffsets.collect { burnInOffsets -> view.translationX = burnInOffsets.x.toFloat() view.translationY = burnInOffsets.y.toFloat() @@ -120,17 +114,15 @@ object DeviceEntryIconViewBinder { } } - launch("$TAG#viewModel.deviceEntryViewAlpha") { - viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } - } + launch { viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } } } } - fgIconView.repeatWhenAttached(mainImmediateDispatcher) { + fgIconView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { // Start with an empty state fgIconView.setImageState(StateSet.NOTHING, /* merge */ false) - launch("$TAG#fgViewModel.viewModel") { + launch { fgViewModel.viewModel.collect { viewModel -> fgIconView.setImageState( view.getIconState(viewModel.type, viewModel.useAodVariant), @@ -150,10 +142,8 @@ object DeviceEntryIconViewBinder { bgView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch("$TAG#bgViewModel.alpha") { - bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } - } - launch("$TAG#bgViewModel.color") { + launch { bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } } + launch { bgViewModel.color.collect { color -> bgView.imageTintList = ColorStateList.valueOf(color) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt index b5d61773d9af..6b8e896c937d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt @@ -38,6 +38,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R +import com.android.systemui.shared.R as sharedR import javax.inject.Inject import kotlin.math.max @@ -217,15 +218,21 @@ constructor( if (!DEBUG || currentClock == null) return val smallClockViewId = R.id.lockscreen_clock_view val largeClockViewId = currentClock.largeClock.layout.views[0].id + val smartspaceDateId = sharedR.id.date_smartspace_view Log.i( TAG, "applyCsToSmallClock: vis=${cs.getVisibility(smallClockViewId)} " + - "alpha=${cs.getConstraint(smallClockViewId).propertySet}" + "alpha=${cs.getConstraint(smallClockViewId).propertySet.alpha}" ) Log.i( TAG, "applyCsToLargeClock: vis=${cs.getVisibility(largeClockViewId)} " + - "alpha=${cs.getConstraint(largeClockViewId).propertySet}" + "alpha=${cs.getConstraint(largeClockViewId).propertySet.alpha}" + ) + Log.i( + TAG, + "applyCsToSmartspaceDate: vis=${cs.getVisibility(smartspaceDateId)} " + + "alpha=${cs.getConstraint(smartspaceDateId).propertySet.alpha}" ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt index 1b06a69213b9..7178e1bd9357 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt @@ -26,7 +26,6 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle -import com.android.app.tracing.coroutines.launch import com.android.keyguard.KeyguardClockSwitch.LARGE import com.android.keyguard.KeyguardClockSwitch.SMALL import com.android.systemui.keyguard.MigrateClocksToBlueprint @@ -37,11 +36,10 @@ import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.clocks.ClockController -import com.android.systemui.shared.clocks.DEFAULT_CLOCK_ID -import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.launch object KeyguardClockViewBinder { - private const val TAG = "KeyguardClockViewBinder" + private val TAG = KeyguardClockViewBinder::class.simpleName!! // When changing to new clock, we need to remove old clock views from burnInLayer private var lastClock: ClockController? = null @JvmStatic @@ -51,12 +49,15 @@ object KeyguardClockViewBinder { viewModel: KeyguardClockViewModel, keyguardClockInteractor: KeyguardClockInteractor, blueprintInteractor: KeyguardBlueprintInteractor, - ): DisposableHandle { - keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView) - - return keyguardRootView.repeatWhenAttached { + ) { + keyguardRootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch("$TAG#viewModel.currentClock") { + keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView) + } + } + keyguardRootView.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + launch { if (!MigrateClocksToBlueprint.isEnabled) return@launch viewModel.currentClock.collect { currentClock -> cleanupClockViews(currentClock, keyguardRootView, viewModel.burnInLayer) @@ -65,22 +66,22 @@ object KeyguardClockViewBinder { applyConstraints(clockSection, keyguardRootView, true) } } - launch("$TAG#viewModel.clockSize") { + launch { if (!MigrateClocksToBlueprint.isEnabled) return@launch viewModel.clockSize.collect { updateBurnInLayer(keyguardRootView, viewModel) blueprintInteractor.refreshBlueprint(Type.ClockSize) } } - launch("$TAG#viewModel.clockShouldBeCentered") { + launch { if (!MigrateClocksToBlueprint.isEnabled) return@launch - viewModel.clockShouldBeCentered.collect { clockShouldBeCentered -> + viewModel.clockShouldBeCentered.collect { viewModel.currentClock.value?.let { - // Weather clock also has hasCustomPositionUpdatedAnimation as true - // TODO(b/323020908): remove ID check + // TODO(b/301502635): remove "!it.config.useCustomClockScene" when + // migrate clocks to blueprint is fully rolled out if ( it.largeClock.config.hasCustomPositionUpdatedAnimation && - it.config.id == DEFAULT_CLOCK_ID + !it.config.useCustomClockScene ) { blueprintInteractor.refreshBlueprint(Type.DefaultClockStepping) } else { @@ -89,14 +90,11 @@ object KeyguardClockViewBinder { } } } - launch("$TAG#viewModel.isAodIconsVisible") { + launch { if (!MigrateClocksToBlueprint.isEnabled) return@launch - viewModel.isAodIconsVisible.collect { isAodIconsVisible -> + viewModel.isAodIconsVisible.collect { viewModel.currentClock.value?.let { - // Weather clock also has hasCustomPositionUpdatedAnimation as true - if ( - viewModel.useLargeClock && it.config.id == "DIGITAL_CLOCK_WEATHER" - ) { + if (viewModel.useLargeClock && it.config.useCustomClockScene) { blueprintInteractor.refreshBlueprint(Type.DefaultTransition) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt index d5add61822b1..93b3ba561eb3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt @@ -19,9 +19,8 @@ import com.android.keyguard.logging.KeyguardLogger import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent import com.android.systemui.log.core.LogLevel import com.android.systemui.util.kotlin.sample import javax.inject.Inject @@ -38,11 +37,10 @@ constructor( private val interactor: KeyguardDismissActionInteractor, @Application private val scope: CoroutineScope, private val keyguardLogger: KeyguardLogger, - private val featureFlags: FeatureFlagsClassic, ) : CoreStartable { override fun start() { - if (!featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (!RefactorKeyguardDismissIntent.isEnabled) { return } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt index 87d8164e1cb9..f77d01208dc2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt @@ -21,8 +21,8 @@ import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent import com.android.systemui.keyguard.shared.model.KeyguardDone import com.android.systemui.log.core.LogLevel import com.android.systemui.user.domain.interactor.SelectedUserInteractor @@ -44,7 +44,7 @@ constructor( ) : CoreStartable { override fun start() { - if (!featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (!RefactorKeyguardDismissIntent.isEnabled) { return } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt index 486320af45a2..3ff32bfcfd46 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt @@ -44,6 +44,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.res.R +import com.android.systemui.shared.clocks.ClockRegistry import com.android.systemui.util.Utils import kotlin.reflect.KSuspendFunction1 @@ -77,37 +78,42 @@ object KeyguardPreviewClockViewBinder { context: Context, rootView: ConstraintLayout, viewModel: KeyguardPreviewClockViewModel, + clockRegistry: ClockRegistry, updateClockAppearance: KSuspendFunction1<ClockController, Unit>, ) { rootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { + var lastClock: ClockController? = null launch("$TAG#viewModel.previewClock") { - var lastClock: ClockController? = null - viewModel.previewClock.collect { currentClock -> - lastClock?.let { clock -> - (clock.largeClock.layout.views + clock.smallClock.layout.views) - .forEach { rootView.removeView(it) } - } - lastClock = currentClock - updateClockAppearance(currentClock) + viewModel.previewClock.collect { currentClock -> + lastClock?.let { clock -> + (clock.largeClock.layout.views + clock.smallClock.layout.views) + .forEach { rootView.removeView(it) } + } + lastClock = currentClock + updateClockAppearance(currentClock) - if (viewModel.shouldHighlightSelectedAffordance) { - (currentClock.largeClock.layout.views + - currentClock.smallClock.layout.views) - .forEach { it.alpha = KeyguardPreviewRenderer.DIM_ALPHA } - } - currentClock.largeClock.layout.views.forEach { - (it.parent as? ViewGroup)?.removeView(it) - rootView.addView(it) - } + if (viewModel.shouldHighlightSelectedAffordance) { + (currentClock.largeClock.layout.views + + currentClock.smallClock.layout.views) + .forEach { it.alpha = KeyguardPreviewRenderer.DIM_ALPHA } + } + currentClock.largeClock.layout.views.forEach { + (it.parent as? ViewGroup)?.removeView(it) + rootView.addView(it) + } - currentClock.smallClock.layout.views.forEach { - (it.parent as? ViewGroup)?.removeView(it) - rootView.addView(it) + currentClock.smallClock.layout.views.forEach { + (it.parent as? ViewGroup)?.removeView(it) + rootView.addView(it) + } + applyPreviewConstraints(context, rootView, currentClock, viewModel) } - applyPreviewConstraints(context, rootView, currentClock, viewModel) } - } + .invokeOnCompletion { + // recover seed color especially for Transit clock + lastClock?.events?.onSeedColorChanged(clockRegistry.seedColor) + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt index 49ae35a43c23..88d907469f69 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt @@ -32,7 +32,7 @@ object KeyguardPreviewSmartspaceViewBinder { @JvmStatic fun bind( - context: Context, + previewContext: Context, smartspace: View, splitShadePreview: Boolean, viewModel: KeyguardPreviewSmartspaceViewModel, @@ -46,10 +46,12 @@ object KeyguardPreviewSmartspaceViewBinder { SettingsClockSize.DYNAMIC -> viewModel.getLargeClockSmartspaceTopPadding( splitShadePreview, + previewContext, ) SettingsClockSize.SMALL -> viewModel.getSmallClockSmartspaceTopPadding( splitShadePreview, + previewContext, ) } smartspace.setTopPadding(topPadding) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt index 6c21e6cdb3bc..abd79ab793d5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt @@ -30,7 +30,6 @@ import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle -import com.android.app.tracing.coroutines.launch import com.android.settingslib.Utils import com.android.systemui.animation.Expandable import com.android.systemui.animation.view.LaunchableImageView @@ -42,11 +41,11 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.doOnEnd -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch /** This is only for a SINGLE Quick affordance */ object KeyguardQuickAffordanceViewBinder { @@ -54,7 +53,6 @@ object KeyguardQuickAffordanceViewBinder { private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L private const val SCALE_SELECTED_BUTTON = 1.23f private const val DIM_ALPHA = 0.3f - private const val TAG = "KeyguardQuickAffordanceViewBinder" /** * Defines interface for an object that acts as the binding between the view and its view-model. @@ -76,15 +74,14 @@ object KeyguardQuickAffordanceViewBinder { alpha: Flow<Float>, falsingManager: FalsingManager?, vibratorHelper: VibratorHelper?, - mainImmediateDispatcher: CoroutineDispatcher, messageDisplayer: (Int) -> Unit, ): Binding { val button = view as ImageView val configurationBasedDimensions = MutableStateFlow(loadFromResources(view)) val disposableHandle = - view.repeatWhenAttached(mainImmediateDispatcher) { + view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch("$TAG#viewModel.collect") { + launch { viewModel.collect { buttonModel -> updateButton( view = button, @@ -96,7 +93,7 @@ object KeyguardQuickAffordanceViewBinder { } } - launch("$TAG#updateButtonAlpha") { + launch { updateButtonAlpha( view = button, viewModel = viewModel, @@ -104,7 +101,7 @@ object KeyguardQuickAffordanceViewBinder { ) } - launch("$TAG#configurationBasedDimensions") { + launch { configurationBasedDimensions.collect { dimensions -> button.updateLayoutParams<ViewGroup.LayoutParams> { width = dimensions.buttonSizePx.width diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index 44fd58267250..cc54920236da 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -30,10 +30,12 @@ import android.view.ViewGroup import android.view.ViewGroup.OnHierarchyChangeListener import android.view.ViewPropertyAnimator import android.view.WindowInsets +import androidx.activity.OnBackPressedDispatcher +import androidx.activity.OnBackPressedDispatcherOwner +import androidx.activity.setViewTreeOnBackPressedDispatcherOwner import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.animation.Interpolators -import com.android.app.tracing.coroutines.launch import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD import com.android.systemui.Flags.newAodTransition @@ -50,6 +52,7 @@ import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor +import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters @@ -73,7 +76,6 @@ import com.android.systemui.util.ui.isAnimating import com.android.systemui.util.ui.stopAnimating import com.android.systemui.util.ui.value import kotlin.math.min -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.coroutineScope @@ -81,6 +83,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch /** Bind occludingAppDeviceEntryMessageViewModel to run whenever the keyguard view is attached. */ @OptIn(ExperimentalCoroutinesApi::class) @@ -101,7 +104,6 @@ object KeyguardRootViewBinder { vibratorHelper: VibratorHelper?, falsingManager: FalsingManager?, keyguardViewMediator: KeyguardViewMediator?, - mainImmediateDispatcher: CoroutineDispatcher, ): DisposableHandle { val disposables = DisposableHandles() val childViews = mutableMapOf<Int, View>() @@ -125,9 +127,24 @@ object KeyguardRootViewBinder { ) disposables += - view.repeatWhenAttached(mainImmediateDispatcher) { + view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch("$TAG#occludingAppDeviceEntryMessageViewModel.message") { + if (ComposeLockscreen.isEnabled) { + view.setViewTreeOnBackPressedDispatcherOwner( + object : OnBackPressedDispatcherOwner { + override val onBackPressedDispatcher = + OnBackPressedDispatcher().apply { + setOnBackInvokedDispatcher( + view.viewRootImpl.onBackInvokedDispatcher + ) + } + + override val lifecycle: Lifecycle = + this@repeatWhenAttached.lifecycle + } + ) + } + launch { occludingAppDeviceEntryMessageViewModel.message.collect { biometricMessage -> if (biometricMessage?.message != null) { @@ -146,7 +163,7 @@ object KeyguardRootViewBinder { if ( KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled ) { - launch("$TAG#viewModel.alpha") { + launch { viewModel.alpha(viewState).collect { alpha -> view.alpha = alpha if (KeyguardBottomAreaRefactor.isEnabled) { @@ -158,21 +175,21 @@ object KeyguardRootViewBinder { } if (MigrateClocksToBlueprint.isEnabled) { - launch("$TAG#viewModel.burnInLayerVisibility") { + launch { viewModel.burnInLayerVisibility.collect { visibility -> childViews[burnInLayerId]?.visibility = visibility childViews[aodNotificationIconContainerId]?.visibility = visibility } } - launch("$TAG#viewModel.burnInLayerAlpha") { + launch { viewModel.burnInLayerAlpha.collect { alpha -> childViews[statusViewId]?.alpha = alpha childViews[aodNotificationIconContainerId]?.alpha = alpha } } - launch("$TAG#viewModel.topClippingBounds") { + launch { val clipBounds = Rect() viewModel.topClippingBounds.collect { clipTop -> if (clipTop == null) { @@ -189,13 +206,13 @@ object KeyguardRootViewBinder { } } - launch("$TAG#viewModel.lockscreenStateAlpha") { + launch { viewModel.lockscreenStateAlpha(viewState).collect { alpha -> childViews[statusViewId]?.alpha = alpha } } - launch("$TAG#viewModel.translationY") { + launch { // When translation happens in burnInLayer, it won't be weather clock // large clock isn't added to burnInLayer due to its scale transition // so we also need to add translation to it here @@ -207,7 +224,7 @@ object KeyguardRootViewBinder { } } - launch("$TAG#viewModel.translationX") { + launch { viewModel.translationX.collect { state -> val px = state.value ?: return@collect when { @@ -234,7 +251,7 @@ object KeyguardRootViewBinder { } } - launch("$TAG#viewModel.scale") { + launch { viewModel.scale.collect { scaleViewModel -> if (scaleViewModel.scaleClockOnly) { // For clocks except weather clock, we have scale transition @@ -265,7 +282,7 @@ object KeyguardRootViewBinder { } if (NotificationIconContainerRefactor.isEnabled) { - launch("$TAG#viewModel.isNotifIconContainerVisible") { + launch { val iconsAppearTranslationPx = configuration .getDimensionPixelSize(R.dimen.shelf_appear_translation) @@ -282,7 +299,7 @@ object KeyguardRootViewBinder { } interactionJankMonitor?.let { jankMonitor -> - launch("$TAG#viewModel.goneToAodTransition") { + launch { viewModel.goneToAodTransition.collect { when (it.transitionState) { TransitionState.STARTED -> { @@ -308,7 +325,7 @@ object KeyguardRootViewBinder { } } - launch("$TAG#shadeInteractor.isAnyFullyExpanded") { + launch { shadeInteractor.isAnyFullyExpanded.collect { isFullyAnyExpanded -> view.visibility = if (isFullyAnyExpanded) { @@ -319,12 +336,10 @@ object KeyguardRootViewBinder { } } - launch("$TAG#burnInParams.collect") { - burnInParams.collect { viewModel.updateBurnInParams(it) } - } + launch { burnInParams.collect { viewModel.updateBurnInParams(it) } } if (deviceEntryHapticsInteractor != null && vibratorHelper != null) { - launch("$TAG#deviceEntryHapticsInteractor.playSuccessHaptic") { + launch { deviceEntryHapticsInteractor.playSuccessHaptic.collect { vibratorHelper.performHapticFeedback( view, @@ -334,7 +349,7 @@ object KeyguardRootViewBinder { } } - launch("$TAG#deviceEntryHapticsInteractor.playErrorHaptic") { + launch { deviceEntryHapticsInteractor.playErrorHaptic.collect { vibratorHelper.performHapticFeedback( view, @@ -589,5 +604,4 @@ object KeyguardRootViewBinder { private const val ID = "occluding_app_device_entry_unlock_msg" private const val AOD_ICONS_APPEAR_DURATION: Long = 200 - private const val TAG = "KeyguardRootViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt index ce1aed08ab49..bda5be4f6533 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -327,9 +327,12 @@ constructor( smartSpaceView = lockscreenSmartspaceController.buildAndConnectDateView(parentView) val topPadding: Int = - smartspaceViewModel.getLargeClockSmartspaceTopPadding(previewInSplitShade()) - val startPadding: Int = smartspaceViewModel.getSmartspaceStartPadding() - val endPadding: Int = smartspaceViewModel.getSmartspaceEndPadding() + smartspaceViewModel.getLargeClockSmartspaceTopPadding( + previewInSplitShade(), + previewContext, + ) + val startPadding: Int = smartspaceViewModel.getSmartspaceStartPadding(previewContext) + val endPadding: Int = smartspaceViewModel.getSmartspaceEndPadding(previewContext) smartSpaceView?.let { it.setPaddingRelative(startPadding, topPadding, endPadding, 0) @@ -387,7 +390,6 @@ constructor( null, // device entry haptics not required for preview mode null, // falsing manager not required for preview mode null, // keyguard view mediator is not required for preview mode - mainDispatcher, ) } rootView.addView( @@ -411,10 +413,11 @@ constructor( setUpClock(previewContext, rootView) if (MigrateClocksToBlueprint.isEnabled) { KeyguardPreviewClockViewBinder.bind( - context, + previewContext, keyguardRootView, clockViewModel, - ::updateClockAppearance + clockRegistry, + ::updateClockAppearance, ) } else { KeyguardPreviewClockViewBinder.bind( @@ -429,7 +432,7 @@ constructor( smartSpaceView?.let { KeyguardPreviewSmartspaceViewBinder.bind( - context, + previewContext, it, previewInSplitShade(), smartspaceViewModel @@ -454,7 +457,6 @@ constructor( alpha = flowOf(1f), falsingManager = falsingManager, vibratorHelper = vibratorHelper, - mainImmediateDispatcher = mainDispatcher, ) { message -> indicationController.showTransientIndication(message) } @@ -469,7 +471,6 @@ constructor( alpha = flowOf(1f), falsingManager = falsingManager, vibratorHelper = vibratorHelper, - mainImmediateDispatcher = mainDispatcher, ) { message -> indicationController.showTransientIndication(message) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt index b4e57cc93962..04ac7bf1178e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt @@ -17,13 +17,9 @@ package com.android.systemui.keyguard.ui.view.layout.blueprints -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID import com.android.systemui.keyguard.shared.model.KeyguardBlueprint -import com.android.systemui.keyguard.shared.model.KeyguardSection import dagger.Binds import dagger.Module -import dagger.Provides import dagger.multibindings.IntoSet @Module @@ -45,26 +41,4 @@ abstract class KeyguardBlueprintModule { abstract fun bindShortcutsBesideUdfpsLockscreenBlueprint( shortcutsBesideUdfpsLockscreenBlueprint: ShortcutsBesideUdfpsKeyguardBlueprint ): KeyguardBlueprint - - companion object { - /** This is a place holder for weather clock in compose. */ - @Provides - @IntoSet - fun bindWeatherClockBlueprintPlaceHolder(): KeyguardBlueprint { - return object : KeyguardBlueprint { - override val id: String = WEATHER_CLOCK_BLUEPRINT_ID - override val sections: List<KeyguardSection> = listOf() - } - } - - /** This is a place holder for weather clock in compose. */ - @Provides - @IntoSet - fun bindSplitShadeWeatherClockBlueprintPlaceHolder(): KeyguardBlueprint { - return object : KeyguardBlueprint { - override val id: String = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID - override val sections: List<KeyguardSection> = listOf() - } - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt index 5404729d1819..2e9663897f89 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt @@ -36,7 +36,6 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher class AlignShortcutsToUdfpsSection @Inject @@ -48,7 +47,6 @@ constructor( private val falsingManager: FalsingManager, private val indicationController: KeyguardIndicationController, private val vibratorHelper: VibratorHelper, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : BaseShortcutSection() { override fun addViews(constraintLayout: ConstraintLayout) { if (KeyguardBottomAreaRefactor.isEnabled) { @@ -66,7 +64,6 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, - mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } @@ -77,7 +74,6 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, - mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt index e0bf8152d11f..78a1fcfe4258 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt @@ -45,7 +45,6 @@ import com.android.systemui.res.R import com.android.systemui.shared.R as sharedR import dagger.Lazy import javax.inject.Inject -import kotlinx.coroutines.DisposableHandle internal fun ConstraintSet.setVisibility( views: Iterable<View>, @@ -66,23 +65,19 @@ constructor( val smartspaceViewModel: KeyguardSmartspaceViewModel, val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>, ) : KeyguardSection() { - private var handle: DisposableHandle? = null - override fun addViews(constraintLayout: ConstraintLayout) {} override fun bindData(constraintLayout: ConstraintLayout) { if (!MigrateClocksToBlueprint.isEnabled) { return } - handle?.dispose() - handle = - KeyguardClockViewBinder.bind( - this, - constraintLayout, - keyguardClockViewModel, - clockInteractor, - blueprintInteractor.get() - ) + KeyguardClockViewBinder.bind( + this, + constraintLayout, + keyguardClockViewModel, + clockInteractor, + blueprintInteractor.get() + ) } override fun applyConstraints(constraintSet: ConstraintSet) { @@ -94,13 +89,7 @@ constructor( } } - override fun removeViews(constraintLayout: ConstraintLayout) { - if (!MigrateClocksToBlueprint.isEnabled) { - return - } - handle?.dispose() - handle = null - } + override fun removeViews(constraintLayout: ConstraintLayout) {} private fun buildConstraints( clock: ClockController, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt index 865e989c5b68..29041d1665c3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt @@ -30,7 +30,6 @@ import com.android.keyguard.LockIconView import com.android.keyguard.LockIconViewController import com.android.systemui.biometrics.AuthController import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -48,7 +47,6 @@ import com.android.systemui.shade.NotificationPanelView import com.android.systemui.statusbar.VibratorHelper import dagger.Lazy import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -69,7 +67,6 @@ constructor( private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>, private val falsingManager: Lazy<FalsingManager>, private val vibratorHelper: Lazy<VibratorHelper>, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : KeyguardSection() { private val deviceEntryIconViewId = R.id.device_entry_icon_view @@ -107,7 +104,6 @@ constructor( deviceEntryBackgroundViewModel.get(), falsingManager.get(), vibratorHelper.get(), - mainImmediateDispatcher, ) } } else { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt index 27ca5cdbad17..45b82576c6c4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt @@ -35,7 +35,6 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher class DefaultShortcutsSection @Inject @@ -47,7 +46,6 @@ constructor( private val falsingManager: FalsingManager, private val indicationController: KeyguardIndicationController, private val vibratorHelper: VibratorHelper, - @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : BaseShortcutSection() { override fun addViews(constraintLayout: ConstraintLayout) { if (KeyguardBottomAreaRefactor.isEnabled) { @@ -65,7 +63,6 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, - mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } @@ -76,7 +73,6 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, - mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt index eaa5e3367f49..9ec7a65cf240 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt @@ -18,7 +18,6 @@ package com.android.systemui.keyguard.ui.view.layout.sections import android.content.Context import android.view.View -import android.view.View.GONE import android.view.ViewTreeObserver.OnGlobalLayoutListener import androidx.constraintlayout.widget.Barrier import androidx.constraintlayout.widget.ConstraintLayout @@ -205,8 +204,7 @@ constructor( smartspaceController.requestSmartspaceUpdate() constraintSet.apply { - setVisibility( - sharedR.id.weather_smartspace_view, + val weatherVisibility = when (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) { true -> ConstraintSet.GONE false -> @@ -215,11 +213,18 @@ constructor( false -> ConstraintSet.GONE } } + setVisibility(sharedR.id.weather_smartspace_view, weatherVisibility) + setAlpha( + sharedR.id.weather_smartspace_view, + if (weatherVisibility == ConstraintSet.VISIBLE) 1f else 0f ) - setVisibility( - sharedR.id.date_smartspace_view, + val dateVisibility = if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) ConstraintSet.GONE else ConstraintSet.VISIBLE + setVisibility(sharedR.id.date_smartspace_view, dateVisibility) + setAlpha( + sharedR.id.date_smartspace_view, + if (dateVisibility == ConstraintSet.VISIBLE) 1f else 0f ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt index 4d3a78d32b3a..91f76a4df771 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt @@ -169,10 +169,7 @@ class ClockSizeTransition( return@OnPreDrawListener true } - anim.duration = duration - anim.startDelay = startDelay - anim.interpolator = interpolator - anim.addListener( + val listener = object : AnimatorListenerAdapter() { override fun onAnimationStart(anim: Animator) { assignAnimValues("start", 0f, fromVis) @@ -183,8 +180,21 @@ class ClockSizeTransition( if (sendToBack) toView.translationZ = 0f toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback) } + + override fun onAnimationPause(anim: Animator) { + toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback) + } + + override fun onAnimationResume(anim: Animator) { + toView.viewTreeObserver.addOnPreDrawListener(predrawCallback) + } } - ) + + anim.duration = duration + anim.startDelay = startDelay + anim.interpolator = interpolator + anim.addListener(listener) + anim.addPauseListener(listener) assignAnimValues("init", 0f, fromVis) toView.viewTreeObserver.addOnPreDrawListener(predrawCallback) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt index 7814576eff01..5cf100e78e6e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt @@ -19,7 +19,6 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState -import com.android.systemui.keyguard.shared.model.TransitionState import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow @@ -38,12 +37,9 @@ constructor( private val deviceSupportsAlternateBouncer: Flow<Boolean> = alternateBouncerInteractor.alternateBouncerSupported private val isTransitioningToOrFromOrShowingAlternateBouncer: Flow<Boolean> = - keyguardTransitionInteractor.transitions - .map { - it.to == KeyguardState.ALTERNATE_BOUNCER || - (it.from == KeyguardState.ALTERNATE_BOUNCER && - it.transitionState != TransitionState.FINISHED) - } + keyguardTransitionInteractor + .transitionValue(KeyguardState.ALTERNATE_BOUNCER) + .map { it > 0f } .distinctUntilChanged() val alternateBouncerWindowRequired: Flow<Boolean> = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt index 4ddd57110b38..d4844e2af335 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt @@ -29,9 +29,6 @@ import com.android.systemui.keyguard.domain.interactor.BurnInInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.BurnInModel -import com.android.systemui.keyguard.shared.model.TransitionState -import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING -import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.ui.StateToValue import com.android.systemui.res.R import javax.inject.Inject @@ -97,9 +94,9 @@ constructor( occludedToLockscreen, aodToLockscreen -> val translationY = - if (isInTransition(aodToLockscreen.transitionState)) { + if (aodToLockscreen.transitionState.isTransitioning()) { aodToLockscreen.value ?: 0f - } else if (isInTransition(goneToAod.transitionState)) { + } else if (goneToAod.transitionState.isTransitioning()) { (goneToAod.value ?: 0f) + burnInModel.translationY } else { burnInModel.translationY + occludedToLockscreen + keyguardTranslationY @@ -110,10 +107,6 @@ constructor( .distinctUntilChanged() } - private fun isInTransition(state: TransitionState): Boolean { - return state == STARTED || state == RUNNING - } - private fun burnIn( params: BurnInParameters, ): Flow<BurnInModel> { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt index fe88b8169c89..24429fae93ac 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt @@ -18,9 +18,8 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.ScrimAlpha @@ -44,13 +43,12 @@ constructor( private val statusBarStateController: SysuiStatusBarStateController, private val primaryBouncerInteractor: PrimaryBouncerInteractor, private val keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>, - private val featureFlags: FeatureFlagsClassic, private val shadeInteractor: ShadeInteractor, private val animationFlow: KeyguardTransitionAnimationFlow, ) { /** Common fade for scrim alpha values during *BOUNCER->GONE */ fun scrimAlpha(duration: Duration, fromState: KeyguardState): Flow<ScrimAlpha> { - return if (featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + return if (RefactorKeyguardDismissIntent.isEnabled) { keyguardDismissActionInteractor .get() .willAnimateDismissActionOnLockscreen @@ -104,7 +102,7 @@ constructor( to = GONE, ) - return shadeInteractor.shadeExpansion.flatMapLatest { shadeExpansion -> + return shadeInteractor.isAnyExpanded.flatMapLatest { isAnyExpanded -> transitionAnimation .sharedFlow( duration = duration, @@ -112,7 +110,7 @@ constructor( onStart = { leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide() willRunDismissFromKeyguard = willRunAnimationOnKeyguard() - isShadeExpanded = shadeExpansion > 0f + isShadeExpanded = isAnyExpanded }, onStep = { 1f - it }, ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt index 49fffdd9ce9b..45dca99b7acc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt @@ -30,7 +30,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import com.android.systemui.keyguard.ui.view.DeviceEntryIconView -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.util.kotlin.sample import dagger.Lazy @@ -64,7 +64,6 @@ constructor( transitionInteractor: KeyguardTransitionInteractor, val keyguardInteractor: KeyguardInteractor, val viewModel: AodToLockscreenTransitionViewModel, - private val sceneContainerFlags: SceneContainerFlags, private val keyguardViewController: Lazy<KeyguardViewController>, private val deviceEntryInteractor: DeviceEntryInteractor, private val deviceEntrySourceInteractor: DeviceEntrySourceInteractor, @@ -242,7 +241,7 @@ constructor( } suspend fun onLongPress() { - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { deviceEntryInteractor.attemptDeviceEntry() } else { keyguardViewController.get().showPrimaryBouncer(/* scrim */ true) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt index c9251c7c5473..a6d3312fd6d2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt @@ -26,7 +26,6 @@ import com.android.systemui.customization.R as customizationR import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.SettingsClockSize import com.android.systemui.res.R @@ -46,11 +45,10 @@ import kotlinx.coroutines.flow.stateIn class KeyguardClockViewModel @Inject constructor( - keyguardInteractor: KeyguardInteractor, - private val keyguardClockInteractor: KeyguardClockInteractor, + keyguardClockInteractor: KeyguardClockInteractor, @Application private val applicationScope: CoroutineScope, notifsKeyguardInteractor: NotificationsKeyguardInteractor, - @VisibleForTesting val shadeInteractor: ShadeInteractor, + @get:VisibleForTesting val shadeInteractor: ShadeInteractor, ) { var burnInLayer: Layer? = null val useLargeClock: Boolean @@ -99,7 +97,7 @@ constructor( ) val clockShouldBeCentered: StateFlow<Boolean> = - keyguardInteractor.clockShouldBeCentered.stateIn( + keyguardClockInteractor.clockShouldBeCentered.stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), initialValue = false @@ -113,18 +111,37 @@ constructor( ) val currentClockLayout: StateFlow<ClockLayout> = - combine(isLargeClockVisible, clockShouldBeCentered, shadeInteractor.shadeMode) { + combine( isLargeClockVisible, clockShouldBeCentered, - shadeMode -> + shadeInteractor.shadeMode, + currentClock + ) { isLargeClockVisible, clockShouldBeCentered, shadeMode, currentClock -> val shouldUseSplitShade = shadeMode == ShadeMode.Split - when { - shouldUseSplitShade && clockShouldBeCentered -> ClockLayout.LARGE_CLOCK - shouldUseSplitShade && isLargeClockVisible -> - ClockLayout.SPLIT_SHADE_LARGE_CLOCK - shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK - isLargeClockVisible -> ClockLayout.LARGE_CLOCK - else -> ClockLayout.SMALL_CLOCK + if (currentClock?.config?.useCustomClockScene == true) { + val weatherClockLayout = + when { + shouldUseSplitShade && clockShouldBeCentered -> + ClockLayout.WEATHER_LARGE_CLOCK + shouldUseSplitShade && isLargeClockVisible -> + ClockLayout.SPLIT_SHADE_WEATHER_LARGE_CLOCK + shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK + isLargeClockVisible -> ClockLayout.WEATHER_LARGE_CLOCK + else -> ClockLayout.SMALL_CLOCK + } + weatherClockLayout + } else { + val clockLayout = + when { + shouldUseSplitShade && clockShouldBeCentered -> ClockLayout.LARGE_CLOCK + shouldUseSplitShade && isLargeClockVisible -> + ClockLayout.SPLIT_SHADE_LARGE_CLOCK + shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK + isLargeClockVisible -> ClockLayout.LARGE_CLOCK + else -> ClockLayout.SMALL_CLOCK + } + + clockLayout } } .stateIn( @@ -179,5 +196,7 @@ constructor( SMALL_CLOCK, SPLIT_SHADE_LARGE_CLOCK, SPLIT_SHADE_SMALL_CLOCK, + WEATHER_LARGE_CLOCK, + SPLIT_SHADE_WEATHER_LARGE_CLOCK, } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt index 4f2c6f576904..730015202a21 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt @@ -16,13 +16,10 @@ package com.android.systemui.keyguard.ui.viewmodel -import android.content.Context -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.shared.model.SettingsClockSize import com.android.systemui.plugins.clocks.ClockController import javax.inject.Inject -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map @@ -31,9 +28,7 @@ import kotlinx.coroutines.flow.map class KeyguardPreviewClockViewModel @Inject constructor( - @Application private val context: Context, interactor: KeyguardClockInteractor, - @Application private val applicationScope: CoroutineScope, ) { var shouldHighlightSelectedAffordance: Boolean = false diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt index b57e3ecbe05b..528b14c6bbd7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt @@ -17,7 +17,6 @@ package com.android.systemui.keyguard.ui.viewmodel import android.content.Context -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.shared.model.SettingsClockSize import com.android.systemui.res.R @@ -31,7 +30,6 @@ import kotlinx.coroutines.flow.map class KeyguardPreviewSmartspaceViewModel @Inject constructor( - @Application private val context: Context, interactor: KeyguardClockInteractor, val smartspaceViewModel: KeyguardSmartspaceViewModel, val clockViewModel: KeyguardClockViewModel, @@ -55,29 +53,29 @@ constructor( } } - fun getSmartspaceStartPadding(): Int { + fun getSmartspaceStartPadding(context: Context): Int { return KeyguardSmartspaceViewModel.getSmartspaceStartMargin(context) } - fun getSmartspaceEndPadding(): Int { + fun getSmartspaceEndPadding(context: Context): Int { return KeyguardSmartspaceViewModel.getSmartspaceEndMargin(context) } - fun getSmallClockSmartspaceTopPadding(splitShadePreview: Boolean): Int { - return getSmallClockTopPadding(splitShadePreview) + + fun getSmallClockSmartspaceTopPadding(splitShadePreview: Boolean, context: Context): Int { + return getSmallClockTopPadding(splitShadePreview, context) + context.resources.getDimensionPixelSize( com.android.systemui.customization.R.dimen.small_clock_height ) } - fun getLargeClockSmartspaceTopPadding(splitShadePreview: Boolean): Int { - return getSmallClockTopPadding(splitShadePreview) + fun getLargeClockSmartspaceTopPadding(splitShadePreview: Boolean, context: Context): Int { + return getSmallClockTopPadding(splitShadePreview, context) } /* * SmallClockTopPadding decides the top position of smartspace */ - private fun getSmallClockTopPadding(splitShadePreview: Boolean): Int { + private fun getSmallClockTopPadding(splitShadePreview: Boolean, context: Context): Int { return with(context.resources) { if (splitShadePreview) { getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index 64e15659d08b..24a7c512a6a9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -42,6 +42,7 @@ import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.ScreenOffAnimationController +import com.android.systemui.util.kotlin.BooleanFlowOperators.or import com.android.systemui.util.kotlin.pairwise import com.android.systemui.util.kotlin.sample import com.android.systemui.util.ui.AnimatableEvent @@ -133,22 +134,18 @@ constructor( private val isOnLockscreen: Flow<Boolean> = combine( keyguardTransitionInteractor.isFinishedInState(LOCKSCREEN).onStart { emit(false) }, - keyguardTransitionInteractor - .isInTransitionWhere { from, to -> from == LOCKSCREEN || to == LOCKSCREEN } - .onStart { emit(false) } + or( + keyguardTransitionInteractor.isInTransitionToState(LOCKSCREEN), + keyguardTransitionInteractor.isInTransitionFromState(LOCKSCREEN), + ), ) { onLockscreen, transitioningToOrFromLockscreen -> onLockscreen || transitioningToOrFromLockscreen } .distinctUntilChanged() - private val lockscreenToGoneTransitionRunning: Flow<Boolean> = - keyguardTransitionInteractor - .isInTransitionWhere { from, to -> from == LOCKSCREEN && to == GONE } - .onStart { emit(false) } - private val alphaOnShadeExpansion: Flow<Float> = combineTransform( - lockscreenToGoneTransitionRunning, + keyguardTransitionInteractor.isInTransition(from = LOCKSCREEN, to = GONE), isOnLockscreen, shadeInteractor.qsExpansion, shadeInteractor.shadeExpansion, @@ -185,8 +182,12 @@ constructor( .transitionValue(OCCLUDED) .map { it == 1f } .onStart { emit(false) }, - ) { isIdleOnCommunal, isGone, isOccluded -> - isIdleOnCommunal || isGone || isOccluded + keyguardTransitionInteractor + .transitionValue(KeyguardState.DREAMING) + .map { it == 1f } + .onStart { emit(false) }, + ) { isIdleOnCommunal, isGone, isOccluded, isDreaming -> + isIdleOnCommunal || isGone || isOccluded || isDreaming } .distinctUntilChanged() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt index 993e81bfbf69..d4c8456e0d71 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt @@ -37,6 +37,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn /** Models UI state and handles user input for the lockscreen scene. */ @@ -52,16 +54,23 @@ constructor( val notifications: NotificationsPlaceholderViewModel, ) { val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> = - combine( - deviceEntryInteractor.isUnlocked, - communalInteractor.isCommunalAvailable, - shadeInteractor.shadeMode, - ) { isDeviceUnlocked, isCommunalAvailable, shadeMode -> - destinationScenes( - isDeviceUnlocked = isDeviceUnlocked, - isCommunalAvailable = isCommunalAvailable, - shadeMode = shadeMode, - ) + shadeInteractor.isShadeTouchable + .flatMapLatest { isShadeTouchable -> + if (!isShadeTouchable) { + flowOf(emptyMap()) + } else { + combine( + deviceEntryInteractor.isUnlocked, + communalInteractor.isCommunalAvailable, + shadeInteractor.shadeMode, + ) { isDeviceUnlocked, isCommunalAvailable, shadeMode -> + destinationScenes( + isDeviceUnlocked = isDeviceUnlocked, + isCommunalAvailable = isCommunalAvailable, + shadeMode = shadeMode, + ) + } + } } .stateIn( scope = applicationScope, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt new file mode 100644 index 000000000000..d2c9cfbd71b8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow + +/** Breaks down OCCLUDED->GONE transition into discrete steps for corresponding views to consume. */ +@ExperimentalCoroutinesApi +@SysUISingleton +class OccludedToGoneTransitionViewModel +@Inject +constructor( + animationFlow: KeyguardTransitionAnimationFlow, +) { + private val transitionAnimation = + animationFlow.setup( + duration = DEFAULT_DURATION, + from = KeyguardState.OCCLUDED, + to = KeyguardState.GONE, + ) + + fun notificationAlpha(viewState: ViewStateAccessor): Flow<Float> { + var currentAlpha = 0f + return transitionAnimation.sharedFlow( + duration = DEFAULT_DURATION, + onStart = { currentAlpha = viewState.alpha() }, + onStep = { currentAlpha }, + onFinish = { 1f }, + ) + } + + companion object { + val DEFAULT_DURATION = 300.milliseconds + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt index 3a19780c7017..a09d58ac381b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt @@ -21,15 +21,21 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import com.android.systemui.res.R +import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge /** * Breaks down OCCLUDED->LOCKSCREEN transition into discrete steps for corresponding views to @@ -43,6 +49,8 @@ constructor( deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor, configurationInteractor: ConfigurationInteractor, animationFlow: KeyguardTransitionAnimationFlow, + keyguardInteractor: KeyguardInteractor, + keyguardTransitionInteractor: KeyguardTransitionInteractor, ) : DeviceEntryIconTransition { private val transitionAnimation = @@ -74,11 +82,28 @@ constructor( /** Lockscreen views alpha */ val lockscreenAlpha: Flow<Float> = - transitionAnimation.sharedFlow( - startTime = 233.milliseconds, - duration = 250.milliseconds, - onStep = { it }, - name = "OCCLUDED->LOCKSCREEN: lockscreenAlpha", + merge( + transitionAnimation.sharedFlow( + startTime = 233.milliseconds, + duration = 250.milliseconds, + onStep = { it }, + name = "OCCLUDED->LOCKSCREEN: lockscreenAlpha", + ), + // Required to fix a bug where the shade expands while lockscreenAlpha=1f, due to a call + // to setOccluded(false) triggering a reset() call in KeyguardViewMediator. The + // permanent solution is to only expand the shade once the keyguard transition from + // OCCLUDED starts, but that requires more refactoring of expansion amounts. For now, + // emit alpha = 0f for OCCLUDED -> LOCKSCREEN whenever isOccluded flips from true to + // false while currentState == OCCLUDED, so that alpha = 0f when that expansion occurs. + // TODO(b/332946323): Remove this once it's no longer needed. + keyguardInteractor.isKeyguardOccluded + .pairwise() + .filter { (wasOccluded, isOccluded) -> + wasOccluded && + !isOccluded && + keyguardTransitionInteractor.getCurrentState() == KeyguardState.OCCLUDED + } + .map { 0f } ) val deviceEntryBackgroundViewAlpha: Flow<Float> = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt index 05878265dd6d..a08a234f85d4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt @@ -18,10 +18,9 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER import com.android.systemui.keyguard.shared.model.ScrimAlpha @@ -46,7 +45,6 @@ constructor( private val statusBarStateController: SysuiStatusBarStateController, private val primaryBouncerInteractor: PrimaryBouncerInteractor, keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>, - featureFlags: FeatureFlagsClassic, bouncerToGoneFlows: BouncerToGoneFlows, animationFlow: KeyguardTransitionAnimationFlow, ) { @@ -82,7 +80,7 @@ constructor( /** Bouncer container alpha */ val bouncerAlpha: Flow<Float> = - if (featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled) { keyguardDismissActionInteractor .get() .willAnimateDismissActionOnLockscreen @@ -106,7 +104,7 @@ constructor( /** Lockscreen alpha */ val lockscreenAlpha: Flow<Float> = - if (featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled) { keyguardDismissActionInteractor .get() .willAnimateDismissActionOnLockscreen diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/model/MediaSortKeyModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/model/MediaSortKeyModel.kt new file mode 100644 index 000000000000..cfe5cde79ec7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/model/MediaSortKeyModel.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.data.model + +import com.android.internal.logging.InstanceId +import com.android.systemui.media.controls.shared.model.MediaData.Companion.PLAYBACK_LOCAL + +data class MediaSortKeyModel( + /** Whether the item represents a Smartspace media recommendation that should be prioritized. */ + val isPrioritizedRec: Boolean = false, + val isPlaying: Boolean? = null, + val playbackLocation: Int = PLAYBACK_LOCAL, + val active: Boolean = true, + val isResume: Boolean = false, + val lastActive: Long = 0L, + val notificationKey: String? = null, + val updateTime: Long = 0, + val instanceId: InstanceId? = null, +) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt index df34169c9a50..7e57cf4af4a3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt @@ -18,8 +18,14 @@ package com.android.systemui.media.controls.data.repository import com.android.internal.logging.InstanceId import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.media.controls.data.model.MediaSortKeyModel +import com.android.systemui.media.controls.shared.model.MediaCommonModel import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData +import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel +import com.android.systemui.util.time.SystemClock +import java.util.TreeMap import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -27,7 +33,7 @@ import kotlinx.coroutines.flow.asStateFlow /** A repository that holds the state of filtered media data on the device. */ @SysUISingleton -class MediaFilterRepository @Inject constructor() { +class MediaFilterRepository @Inject constructor(private val systemClock: SystemClock) { /** Instance id of media control that recommendations card reactivated. */ private val _reactivatedId: MutableStateFlow<InstanceId?> = MutableStateFlow(null) @@ -46,6 +52,36 @@ class MediaFilterRepository @Inject constructor() { MutableStateFlow(LinkedHashMap()) val allUserEntries: StateFlow<Map<String, MediaData>> = _allUserEntries.asStateFlow() + private val _mediaDataLoadedStates: MutableStateFlow<List<MediaDataLoadingModel>> = + MutableStateFlow(mutableListOf()) + val mediaDataLoadedStates: StateFlow<List<MediaDataLoadingModel>> = + _mediaDataLoadedStates.asStateFlow() + + private val _recommendationsLoadingState: MutableStateFlow<SmartspaceMediaLoadingModel> = + MutableStateFlow(SmartspaceMediaLoadingModel.Unknown) + val recommendationsLoadingState: StateFlow<SmartspaceMediaLoadingModel> = + _recommendationsLoadingState.asStateFlow() + + private val comparator = + compareByDescending<MediaSortKeyModel> { + it.isPlaying == true && it.playbackLocation == MediaData.PLAYBACK_LOCAL + } + .thenByDescending { + it.isPlaying == true && it.playbackLocation == MediaData.PLAYBACK_CAST_LOCAL + } + .thenByDescending { it.active } + .thenByDescending { it.isPrioritizedRec } + .thenByDescending { !it.isResume } + .thenByDescending { it.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE } + .thenByDescending { it.lastActive } + .thenByDescending { it.updateTime } + .thenByDescending { it.notificationKey } + + private val _sortedMedia: MutableStateFlow<TreeMap<MediaSortKeyModel, MediaCommonModel>> = + MutableStateFlow(TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator)) + val sortedMedia: StateFlow<Map<MediaSortKeyModel, MediaCommonModel>> = + _sortedMedia.asStateFlow() + fun addMediaEntry(key: String, data: MediaData) { val entries = LinkedHashMap<String, MediaData>(_allUserEntries.value) entries[key] = data @@ -110,4 +146,107 @@ class MediaFilterRepository @Inject constructor() { fun setReactivatedId(instanceId: InstanceId?) { _reactivatedId.value = instanceId } + + fun addMediaDataLoadingState(mediaDataLoadingModel: MediaDataLoadingModel) { + // Filter out previous loading state that has same [InstanceId]. + val loadedStates = + _mediaDataLoadedStates.value.filter { loadedModel -> + loadedModel !is MediaDataLoadingModel.Loaded || + !loadedModel.equalInstanceIds(mediaDataLoadingModel) + } + + _mediaDataLoadedStates.value = + loadedStates + + if (mediaDataLoadingModel is MediaDataLoadingModel.Loaded) { + listOf(mediaDataLoadingModel) + } else { + emptyList() + } + + addMediaLoadingToSortedMap(mediaDataLoadingModel) + } + + fun setRecommendationsLoadingState(smartspaceMediaLoadingModel: SmartspaceMediaLoadingModel) { + _recommendationsLoadingState.value = smartspaceMediaLoadingModel + + addRecsLoadingToSortedMap(smartspaceMediaLoadingModel) + } + + private fun addMediaLoadingToSortedMap(mediaDataLoadingModel: MediaDataLoadingModel) { + val instanceId = + when (mediaDataLoadingModel) { + is MediaDataLoadingModel.Loaded -> mediaDataLoadingModel.instanceId + is MediaDataLoadingModel.Removed -> mediaDataLoadingModel.instanceId + MediaDataLoadingModel.Unknown -> null + } + val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator) + sortedMap.putAll( + _sortedMedia.value.filter { (_, commonModel) -> + commonModel !is MediaCommonModel.MediaControl || + commonModel.instanceId != instanceId + } + ) + + _selectedUserEntries.value[instanceId]?.let { + val sortKey = + MediaSortKeyModel( + isPrioritizedRec = false, + it.isPlaying, + it.playbackLocation, + it.active, + it.resumption, + it.lastActive, + it.notificationKey, + systemClock.currentTimeMillis(), + it.instanceId, + ) + + if (mediaDataLoadingModel is MediaDataLoadingModel.Loaded) { + sortedMap[sortKey] = MediaCommonModel.MediaControl(it.instanceId) + } + } + + _sortedMedia.value = sortedMap + } + + private fun addRecsLoadingToSortedMap( + smartspaceMediaLoadingModel: SmartspaceMediaLoadingModel + ) { + val isPrioritized: Boolean + val key: String? + when (smartspaceMediaLoadingModel) { + is SmartspaceMediaLoadingModel.Loaded -> { + isPrioritized = smartspaceMediaLoadingModel.isPrioritized + key = smartspaceMediaLoadingModel.key + } + is SmartspaceMediaLoadingModel.Removed -> { + isPrioritized = false + key = smartspaceMediaLoadingModel.key + } + SmartspaceMediaLoadingModel.Unknown -> { + isPrioritized = false + key = null + } + } + val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator) + sortedMap.putAll( + _sortedMedia.value.filter { (_, commonModel) -> + commonModel !is MediaCommonModel.MediaRecommendations || commonModel.key != key + } + ) + + key?.let { + val sortKey = + MediaSortKeyModel( + isPrioritizedRec = isPrioritized, + isPlaying = false, + active = _smartspaceMediaData.value.isActive, + ) + if (smartspaceMediaLoadingModel is SmartspaceMediaLoadingModel.Loaded) { + sortedMap[sortKey] = MediaCommonModel.MediaRecommendations(key) + } + } + + _sortedMedia.value = sortedMap + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt index d40069c4b3da..5432a189cf7c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt @@ -28,7 +28,9 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.controls.data.repository.MediaFilterRepository import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData +import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.settings.UserTracker @@ -67,10 +69,11 @@ constructor( private val mediaFlags: MediaFlags, private val mediaFilterRepository: MediaFilterRepository, ) : MediaDataManager.Listener { - private val _listeners: MutableSet<Listener> = mutableSetOf() - val listeners: Set<Listener> + /** Non-UI listeners to media changes. */ + private val _listeners: MutableSet<MediaDataProcessor.Listener> = mutableSetOf() + val listeners: Set<MediaDataProcessor.Listener> get() = _listeners.toSet() - lateinit var mediaDataManager: MediaDataManager + lateinit var mediaDataProcessor: MediaDataProcessor // Ensure the field (and associated reference) isn't removed during optimization. @KeepForWeakReference @@ -111,8 +114,12 @@ constructor( mediaFilterRepository.addSelectedUserMediaEntry(data) + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Loaded(data.instanceId) + ) + // Notify listeners - listeners.forEach { it.onMediaDataLoaded(data.instanceId) } + listeners.forEach { it.onMediaDataLoaded(key, oldKey, data) } } override fun onSmartspaceMediaDataLoaded( @@ -159,7 +166,7 @@ constructor( // reactivate. if (shouldReactivate) { val lastActiveId = sorted.lastKey() // most recently active id - // Notify listeners to consider this media active + // Update loading state to consider this media active Log.d(TAG, "reactivating $lastActiveId instead of smartspace") mediaFilterRepository.setReactivatedId(lastActiveId) val mediaData = sorted[lastActiveId]!!.copy(active = true) @@ -168,14 +175,22 @@ constructor( mediaData.packageName, mediaData.instanceId ) - listeners.forEach { - it.onMediaDataLoaded( - lastActiveId, - receivedSmartspaceCardLatency = - (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis) - .toInt(), - isSsReactivated = true - ) + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Loaded(lastActiveId) + ) + listeners.forEach { listener -> + getKey(lastActiveId)?.let { lastActiveKey -> + listener.onMediaDataLoaded( + lastActiveKey, + lastActiveKey, + mediaData, + receivedSmartspaceCardLatency = + (systemClock.currentTimeMillis() - + data.headphoneConnectionTimeMillis) + .toInt(), + isSsReactivated = true + ) + } } } } else if (data.isActive) { @@ -192,15 +207,21 @@ constructor( smartspaceMediaData.packageName, smartspaceMediaData.instanceId ) - listeners.forEach { it.onSmartspaceMediaDataLoaded(key, shouldPrioritizeMutable) } + mediaFilterRepository.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Loaded(key, shouldPrioritizeMutable) + ) + listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) } } override fun onMediaDataRemoved(key: String) { mediaFilterRepository.removeMediaEntry(key)?.let { mediaData -> val instanceId = mediaData.instanceId mediaFilterRepository.removeSelectedUserMediaEntry(instanceId)?.let { + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Removed(instanceId) + ) // Only notify listeners if something actually changed - listeners.forEach { it.onMediaDataRemoved(instanceId) } + listeners.forEach { it.onMediaDataRemoved(key) } } } } @@ -210,10 +231,15 @@ constructor( mediaFilterRepository.reactivatedId.value?.let { lastActiveId -> mediaFilterRepository.setReactivatedId(null) Log.d(TAG, "expiring reactivated key $lastActiveId") - // Notify listeners to update with actual active value + // Update loading state with actual active value mediaFilterRepository.selectedUserEntries.value[lastActiveId]?.let { + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Loaded(lastActiveId, immediately) + ) listeners.forEach { listener -> - listener.onMediaDataLoaded(lastActiveId, immediately) + getKey(lastActiveId)?.let { lastActiveKey -> + listener.onMediaDataLoaded(lastActiveKey, lastActiveKey, it, immediately) + } } } } @@ -227,6 +253,9 @@ constructor( ) ) } + mediaFilterRepository.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Removed(key, immediately) + ) listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) } } @@ -238,29 +267,43 @@ constructor( // Only remove media when the profile is unavailable. if (DEBUG) Log.d(TAG, "Removing $key after profile change") mediaFilterRepository.removeSelectedUserMediaEntry(data.instanceId, data) - listeners.forEach { listener -> listener.onMediaDataRemoved(data.instanceId) } + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Removed(data.instanceId) + ) + listeners.forEach { listener -> listener.onMediaDataRemoved(key) } } } } @VisibleForTesting internal fun handleUserSwitched() { - // If the user changes, remove all current MediaData objects and inform listeners + // If the user changes, remove all current MediaData objects. val listenersCopy = listeners val keyCopy = mediaFilterRepository.selectedUserEntries.value.keys.toMutableList() - // Clear the list first, to make sure callbacks from listeners if we have any entries - // are up to date + // Clear the list first and update loading state to remove media from UI. mediaFilterRepository.clearSelectedUserMedia() keyCopy.forEach { instanceId -> if (DEBUG) Log.d(TAG, "Removing $instanceId after user change") - listenersCopy.forEach { listener -> listener.onMediaDataRemoved(instanceId) } + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Removed(instanceId) + ) + getKey(instanceId)?.let { + listenersCopy.forEach { listener -> listener.onMediaDataRemoved(it) } + } } mediaFilterRepository.allUserEntries.value.forEach { (key, data) -> if (lockscreenUserManager.isCurrentProfile(data.userId)) { - if (DEBUG) Log.d(TAG, "Re-adding $key after user change") + if (DEBUG) + Log.d( + TAG, + "Re-adding $key with instanceId=${data.instanceId} after user change" + ) mediaFilterRepository.addSelectedUserMediaEntry(data) - listenersCopy.forEach { listener -> listener.onMediaDataLoaded(data.instanceId) } + mediaFilterRepository.addMediaDataLoadingState( + MediaDataLoadingModel.Loaded(data.instanceId) + ) + listenersCopy.forEach { listener -> listener.onMediaDataLoaded(key, null, data) } } } } @@ -272,7 +315,7 @@ constructor( mediaEntries.forEach { (key, data) -> if (mediaFilterRepository.selectedUserEntries.value.containsKey(data.instanceId)) { // Force updates to listeners, needed for re-activated card - mediaDataManager.setInactive(key, timedOut = true, forceUpdate = true) + mediaDataProcessor.setInactive(key, timedOut = true, forceUpdate = true) } } val smartspaceMediaData = mediaFilterRepository.smartspaceMediaData.value @@ -294,7 +337,7 @@ constructor( if (mediaFlags.isPersistentSsCardEnabled()) { mediaFilterRepository.setRecommendation(smartspaceMediaData.copy(isActive = false)) - mediaDataManager.setRecommendationInactive(smartspaceMediaData.targetId) + mediaDataProcessor.setRecommendationInactive(smartspaceMediaData.targetId) } else { mediaFilterRepository.setRecommendation( EMPTY_SMARTSPACE_MEDIA_DATA.copy( @@ -302,7 +345,7 @@ constructor( instanceId = smartspaceMediaData.instanceId, ) ) - mediaDataManager.dismissSmartspaceRecommendation( + mediaDataProcessor.dismissSmartspaceRecommendation( smartspaceMediaData.targetId, delay = 0L, ) @@ -311,10 +354,10 @@ constructor( } /** Add a listener for filtered [MediaData] changes */ - fun addListener(listener: Listener) = _listeners.add(listener) + fun addListener(listener: MediaDataProcessor.Listener) = _listeners.add(listener) /** Remove a listener that was registered with addListener */ - fun removeListener(listener: Listener) = _listeners.remove(listener) + fun removeListener(listener: MediaDataProcessor.Listener) = _listeners.remove(listener) /** * Return the time since last active for the most-recent media. @@ -335,46 +378,14 @@ constructor( return sortedEntries[lastActiveInstanceId]?.let { now - it.lastActive } ?: Long.MAX_VALUE } - interface Listener { - /** - * Called whenever there's new MediaData Loaded for the consumption in views. - * - * @param immediately indicates should apply the UI changes immediately, otherwise wait - * until the next refresh-round before UI becomes visible. True by default to take in - * place immediately. - * @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI - * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace - * signal. - * @param isSsReactivated indicates resume media card is reactivated by Smartspace - * recommendation signal - */ - fun onMediaDataLoaded( - instanceId: InstanceId, - immediately: Boolean = true, - receivedSmartspaceCardLatency: Int = 0, - isSsReactivated: Boolean = false, - ) - - /** - * Called whenever there's new Smartspace media data loaded. - * - * @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true, - * it will be prioritized as the first card. Otherwise, it will show up as the last card - * as default. - */ - fun onSmartspaceMediaDataLoaded(key: String, shouldPrioritize: Boolean = false) - - /** Called whenever a previously existing Media notification was removed. */ - fun onMediaDataRemoved(instanceId: InstanceId) - - /** - * Called whenever a previously existing Smartspace media data was removed. - * - * @param immediately indicates should apply the UI changes immediately, otherwise wait - * until the next refresh-round before UI becomes visible. True by default to take in - * place immediately. - */ - fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true) + private fun getKey(instanceId: InstanceId): String? { + val allEntries = mediaFilterRepository.allUserEntries.value + val filteredEntries = allEntries.filter { (_, data) -> data.instanceId == instanceId } + return if (filteredEntries.isNotEmpty()) { + filteredEntries.keys.first() + } else { + null + } } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt index 7412290e8fc5..1d7c0256b2ef 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt @@ -590,7 +590,7 @@ class MediaDataProcessor( } /** Dismiss a media entry. Returns false if the key was not found. */ - fun dismissMediaData(key: String, delay: Long): Boolean { + fun dismissMediaData(key: String, delayMs: Long): Boolean { val existed = mediaDataRepository.mediaEntries.value[key] != null backgroundExecutor.execute { mediaDataRepository.mediaEntries.value[key]?.let { mediaData -> @@ -602,10 +602,21 @@ class MediaDataProcessor( } } } - foregroundExecutor.executeDelayed({ removeEntry(key) }, delay) + foregroundExecutor.executeDelayed({ removeEntry(key) }, delayMs) return existed } + /** Dismiss a media entry. Returns false if the corresponding key was not found. */ + fun dismissMediaData(instanceId: InstanceId, delayMs: Long): Boolean { + val mediaEntries = mediaDataRepository.mediaEntries.value + val filteredEntries = mediaEntries.filter { (_, data) -> data.instanceId == instanceId } + return if (filteredEntries.isNotEmpty()) { + dismissMediaData(filteredEntries.keys.first(), delayMs) + } else { + false + } + } + /** * Called whenever the recommendation has been expired or removed by the user. This will remove * the recommendation card entirely from the carousel. diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt index 7dbca0ae4cda..b04e93835418 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt @@ -34,15 +34,21 @@ import com.android.systemui.media.controls.domain.pipeline.MediaDeviceManager import com.android.systemui.media.controls.domain.pipeline.MediaSessionBasedFilter import com.android.systemui.media.controls.domain.pipeline.MediaTimeoutListener import com.android.systemui.media.controls.domain.resume.MediaResumeListener +import com.android.systemui.media.controls.shared.model.MediaCommonModel +import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel +import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel +import com.android.systemui.media.controls.util.MediaControlsRefactorFlag import com.android.systemui.media.controls.util.MediaFlags import java.io.PrintWriter import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.stateIn @@ -109,6 +115,18 @@ constructor( .distinctUntilChanged() .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false) + /** The most recent list of loaded media controls. */ + val mediaDataLoadedStates: Flow<List<MediaDataLoadingModel>> = + mediaFilterRepository.mediaDataLoadedStates + + /** The most recent change to loaded media recommendations. */ + val recommendationsLoadingState: Flow<SmartspaceMediaLoadingModel> = + mediaFilterRepository.recommendationsLoadingState + + /** The most recent sorted set for user media instances */ + val sortedMedia: Flow<List<MediaCommonModel>> = + mediaFilterRepository.sortedMedia.map { it.values.toList() } + override fun start() { if (!mediaFlags.isMediaControlsRefactorEnabled()) { return @@ -139,13 +157,19 @@ constructor( mediaDataProcessor.onSessionDestroyed(key) } mediaResumeListener.setManager(this) - mediaDataFilter.mediaDataManager = this + mediaDataFilter.mediaDataProcessor = mediaDataProcessor + } + + override fun addListener(listener: MediaDataManager.Listener) { + mediaDataFilter.addListener(listener) } - override fun setInactive(key: String, timedOut: Boolean, forceUpdate: Boolean) { - mediaDataProcessor.setInactive(key, timedOut, forceUpdate) + override fun removeListener(listener: MediaDataManager.Listener) { + mediaDataFilter.removeListener(listener) } + override fun setInactive(key: String, timedOut: Boolean, forceUpdate: Boolean) = unsupported + override fun onNotificationAdded(key: String, sbn: StatusBarNotification) { mediaDataProcessor.onNotificationAdded(key, sbn) } @@ -190,9 +214,7 @@ constructor( return mediaDataProcessor.dismissSmartspaceRecommendation(key, delay) } - override fun setRecommendationInactive(key: String) { - mediaDataProcessor.setRecommendationInactive(key) - } + override fun setRecommendationInactive(key: String) = unsupported override fun onNotificationRemoved(key: String) { mediaDataProcessor.onNotificationRemoved(key) @@ -223,4 +245,12 @@ constructor( override fun dump(pw: PrintWriter, args: Array<out String>) { mediaDeviceManager.dump(pw) } + + companion object { + val unsupported: Nothing + get() = + error( + "Code path not supported when ${MediaControlsRefactorFlag.FLAG_NAME} is enabled" + ) + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt index 5a0388de444e..74cd2fee94ec 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt @@ -16,20 +16,49 @@ package com.android.systemui.media.controls.domain.pipeline.interactor +import android.app.ActivityOptions +import android.app.BroadcastOptions +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.media.session.MediaController +import android.media.session.MediaSession +import android.media.session.PlaybackState +import android.provider.Settings +import android.util.Log +import com.android.internal.jank.Cuj import com.android.internal.logging.InstanceId +import com.android.systemui.ActivityIntentHelper +import com.android.systemui.animation.DialogCuj +import com.android.systemui.animation.DialogTransitionAnimator +import com.android.systemui.animation.Expandable +import com.android.systemui.bluetooth.BroadcastDialogController +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.media.controls.data.repository.MediaFilterRepository import com.android.systemui.media.controls.domain.pipeline.MediaDataProcessor import com.android.systemui.media.controls.shared.model.MediaControlModel import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.dialog.MediaOutputDialogManager +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.kotlin.pairwiseBy import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map /** Encapsulates business logic for single media control. */ class MediaControlInteractor( - instanceId: InstanceId, + @Application applicationContext: Context, + private val instanceId: InstanceId, repository: MediaFilterRepository, private val mediaDataProcessor: MediaDataProcessor, + private val keyguardStateController: KeyguardStateController, + private val activityStarter: ActivityStarter, + private val activityIntentHelper: ActivityIntentHelper, + private val lockscreenUserManager: NotificationLockscreenUserManager, + private val mediaOutputDialogManager: MediaOutputDialogManager, + private val broadcastDialogController: BroadcastDialogController, ) { val mediaControl: Flow<MediaControlModel?> = @@ -37,8 +66,32 @@ class MediaControlInteractor( .map { entries -> entries[instanceId]?.let { toMediaControlModel(it) } } .distinctUntilChanged() - fun removeMediaControl(key: String, delayMs: Long): Boolean { - return mediaDataProcessor.dismissMediaData(key, delayMs) + val isStartedPlaying: Flow<Boolean> = + mediaControl + .map { mediaControl -> + mediaControl?.token?.let { token -> + MediaController(applicationContext, token).playbackState?.let { + it.state == PlaybackState.STATE_PLAYING + } + } + ?: false + } + .pairwiseBy(initialValue = false) { wasPlaying, isPlaying -> !wasPlaying && isPlaying } + .distinctUntilChanged() + + fun removeMediaControl( + token: MediaSession.Token?, + instanceId: InstanceId, + delayMs: Long + ): Boolean { + val dismissed = mediaDataProcessor.dismissMediaData(instanceId, delayMs) + if (!dismissed) { + Log.w( + TAG, + "Manager failed to dismiss media of instanceId=$instanceId, Token uid=${token?.uid}" + ) + } + return dismissed } private fun toMediaControlModel(data: MediaData): MediaControlModel { @@ -53,14 +106,89 @@ class MediaControlInteractor( appName = app, songName = song, artistName = artist, + showExplicit = isExplicit, artwork = artwork, deviceData = device, semanticActionButtons = semanticActions, notificationActionButtons = actions, actionsToShowInCollapsed = actionsToShowInCompact, + isDismissible = isClearable, isResume = resumption, resumeProgress = resumeProgress, ) } } + + fun startSettings() { + activityStarter.startActivity(SETTINGS_INTENT, /* dismissShade= */ true) + } + + fun startClickIntent(expandable: Expandable, clickIntent: PendingIntent) { + if (!launchOverLockscreen(clickIntent)) { + activityStarter.postStartActivityDismissingKeyguard( + clickIntent, + expandable.activityTransitionController(Cuj.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER) + ) + } + } + + fun startDeviceIntent(deviceIntent: PendingIntent) { + if (deviceIntent.isActivity) { + if (!launchOverLockscreen(deviceIntent)) { + activityStarter.postStartActivityDismissingKeyguard(deviceIntent) + } + } else { + Log.w(TAG, "Device pending intent of instanceId=$instanceId is not an activity.") + } + } + + private fun launchOverLockscreen(pendingIntent: PendingIntent): Boolean { + val showOverLockscreen = + keyguardStateController.isShowing && + activityIntentHelper.wouldPendingShowOverLockscreen( + pendingIntent, + lockscreenUserManager.currentUserId + ) + if (showOverLockscreen) { + try { + val options = BroadcastOptions.makeBasic() + options.isInteractive = true + options.pendingIntentBackgroundActivityStartMode = + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + pendingIntent.send(options.toBundle()) + } catch (e: PendingIntent.CanceledException) { + Log.e(TAG, "pending intent of $instanceId was canceled") + } + return true + } + return false + } + + fun startMediaOutputDialog(expandable: Expandable, packageName: String) { + mediaOutputDialogManager.createAndShowWithController( + packageName, + true, + expandable.dialogController() + ) + } + + fun startBroadcastDialog(expandable: Expandable, broadcastApp: String, packageName: String) { + broadcastDialogController.createBroadcastDialogWithController( + broadcastApp, + packageName, + expandable.dialogTransitionController() + ) + } + + private fun Expandable.dialogController(): DialogTransitionAnimator.Controller? { + return dialogTransitionController( + cuj = + DialogCuj(Cuj.CUJ_SHADE_DIALOG_OPEN, MediaOutputDialogManager.INTERACTION_JANK_TAG) + ) + } + + companion object { + private const val TAG = "MediaControlInteractor" + private val SETTINGS_INTENT = Intent(Settings.ACTION_MEDIA_CONTROLS_SETTINGS) + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt new file mode 100644 index 000000000000..83e2765bc832 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.shared.model + +import com.android.internal.logging.InstanceId + +/** Models any type of media. */ +sealed class MediaCommonModel { + data class MediaControl(val instanceId: InstanceId) : MediaCommonModel() + + data class MediaRecommendations(val key: String) : MediaCommonModel() +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt index d4e34b5af260..f9134f52b58f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt @@ -33,6 +33,7 @@ data class MediaControlModel( val appName: String?, val songName: CharSequence?, val artistName: CharSequence?, + val showExplicit: Boolean, val artwork: Icon?, val deviceData: MediaDeviceData?, /** [MediaButton] contains [MediaAction] objects which represent specific buttons in the UI */ @@ -43,6 +44,7 @@ data class MediaControlModel( * [Notification.MediaStyle.setShowActionsInCompactView]. */ val actionsToShowInCollapsed: List<Int>, + val isDismissible: Boolean, /** Whether player is in resumption state. */ val isResume: Boolean, /** Track seek bar progress (0 - 1) when [isResume] is true. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt new file mode 100644 index 000000000000..bd42a4df7262 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.shared.model + +import com.android.internal.logging.InstanceId + +/** Models media data loading state. */ +sealed class MediaDataLoadingModel { + /** The initial loading state when no media data has yet loaded. */ + data object Unknown : MediaDataLoadingModel() + + /** Media data has been loaded. */ + data class Loaded( + val instanceId: InstanceId, + val immediatelyUpdateUi: Boolean = true, + ) : MediaDataLoadingModel() { + + /** Returns true if [other] has the same instance id, false otherwise. */ + fun equalInstanceIds(other: MediaDataLoadingModel): Boolean { + return when (other) { + is Loaded -> other.instanceId == instanceId + is Removed -> other.instanceId == instanceId + Unknown -> false + } + } + } + + /** Media data has been removed. */ + data class Removed( + val instanceId: InstanceId, + ) : MediaDataLoadingModel() +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaLoadingModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaLoadingModel.kt new file mode 100644 index 000000000000..6c1e536f8c02 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaLoadingModel.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.shared.model + +/** Models smartspace media loading state. */ +sealed class SmartspaceMediaLoadingModel { + /** The initial loading state when no smartspace media has yet loaded. */ + data object Unknown : SmartspaceMediaLoadingModel() + + /** Smartspace media has been loaded. */ + data class Loaded( + val key: String, + val isPrioritized: Boolean = false, + ) : SmartspaceMediaLoadingModel() + + /** Smartspace media has been removed. */ + data class Removed( + val key: String, + val immediatelyUpdateUi: Boolean = true, + ) : SmartspaceMediaLoadingModel() +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt new file mode 100644 index 000000000000..14a917999bb7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.binder + +import android.widget.ImageButton +import androidx.constraintlayout.widget.ConstraintSet +import com.android.systemui.res.R + +object MediaControlViewBinder { + + fun setVisibleAndAlpha(set: ConstraintSet, resId: Int, visible: Boolean) { + setVisibleAndAlpha(set, resId, visible, ConstraintSet.GONE) + } + + private fun setVisibleAndAlpha( + set: ConstraintSet, + resId: Int, + visible: Boolean, + notVisibleValue: Int + ) { + set.setVisibility(resId, if (visible) ConstraintSet.VISIBLE else notVisibleValue) + set.setAlpha(resId, if (visible) 1.0f else 0.0f) + } + + fun updateSeekBarVisibility(constraintSet: ConstraintSet, isSeekBarEnabled: Boolean) { + if (isSeekBarEnabled) { + constraintSet.setVisibility(R.id.media_progress_bar, ConstraintSet.VISIBLE) + constraintSet.setAlpha(R.id.media_progress_bar, 1.0f) + } else { + constraintSet.setVisibility(R.id.media_progress_bar, ConstraintSet.INVISIBLE) + constraintSet.setAlpha(R.id.media_progress_bar, 0.0f) + } + } + + fun setSemanticButtonVisibleAndAlpha( + button: ImageButton, + expandedSet: ConstraintSet, + collapsedSet: ConstraintSet, + visible: Boolean, + notVisibleValue: Int, + showInCollapsed: Boolean + ) { + if (notVisibleValue == ConstraintSet.INVISIBLE) { + // Since time views should appear instead of buttons. + button.isFocusable = visible + button.isClickable = visible + } + setVisibleAndAlpha(expandedSet, button.id, visible, notVisibleValue) + setVisibleAndAlpha(collapsedSet, button.id, visible = visible && showInCollapsed) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt new file mode 100644 index 000000000000..9c6d59e59acc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.binder + +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.Configuration +import android.graphics.Matrix +import android.util.TypedValue +import android.view.View +import android.view.ViewGroup +import androidx.constraintlayout.widget.ConstraintSet +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.android.systemui.animation.Expandable +import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.media.controls.shared.model.NUM_REQUIRED_RECOMMENDATIONS +import com.android.systemui.media.controls.ui.controller.MediaViewController +import com.android.systemui.media.controls.ui.view.RecommendationViewHolder +import com.android.systemui.media.controls.ui.viewmodel.MediaRecViewModel +import com.android.systemui.media.controls.ui.viewmodel.MediaRecommendationsViewModel +import com.android.systemui.media.controls.ui.viewmodel.MediaRecsCardViewModel +import com.android.systemui.plugins.FalsingManager +import com.android.systemui.res.R +import com.android.systemui.util.animation.TransitionLayout +import kotlin.math.min +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +object MediaRecommendationsViewBinder { + + /** Binds recommendations view holder to the given view-model */ + fun bind( + viewHolder: RecommendationViewHolder, + viewModel: MediaRecommendationsViewModel, + mediaViewController: MediaViewController, + falsingManager: FalsingManager, + ) { + mediaViewController.recsConfigurationChangeListener = this::updateRecommendationsVisibility + val cardView = viewHolder.recommendations + cardView.repeatWhenAttached { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + launch { + viewModel.mediaRecsCard.collectLatest { viewModel -> + viewModel?.let { + bindRecsCard(viewHolder, it, mediaViewController, falsingManager) + } + } + } + } + } + } + } + + private fun bindRecsCard( + viewHolder: RecommendationViewHolder, + viewModel: MediaRecsCardViewModel, + mediaViewController: MediaViewController, + falsingManager: FalsingManager, + ) { + // Bind main card. + viewHolder.cardTitle.setTextColor(viewModel.cardTitleColor) + viewHolder.recommendations.backgroundTintList = ColorStateList.valueOf(viewModel.cardColor) + viewHolder.recommendations.contentDescription = + viewModel.contentDescription.invoke(mediaViewController.isGutsVisible) + + viewHolder.recommendations.setOnClickListener { + if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@setOnClickListener + viewModel.onClicked(Expandable.fromView(it)) + } + + viewHolder.recommendations.setOnLongClickListener { + if (falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) + return@setOnLongClickListener true + if (!mediaViewController.isGutsVisible) { + openGuts(viewHolder, viewModel, mediaViewController) + } else { + closeGuts(viewHolder, viewModel, mediaViewController) + } + return@setOnLongClickListener true + } + + // Bind all recommendations. + bindRecommendationsList(viewHolder, viewModel.mediaRecs, falsingManager) + updateRecommendationsVisibility(mediaViewController, viewHolder.recommendations) + + // Set visibility of recommendations. + val expandedSet: ConstraintSet = mediaViewController.expandedLayout + val collapsedSet: ConstraintSet = mediaViewController.collapsedLayout + viewHolder.mediaTitles.forEach { + setVisibleAndAlpha(expandedSet, it.id, viewModel.areTitlesVisible) + setVisibleAndAlpha(collapsedSet, it.id, viewModel.areTitlesVisible) + } + viewHolder.mediaSubtitles.forEach { + setVisibleAndAlpha(expandedSet, it.id, viewModel.areSubtitlesVisible) + setVisibleAndAlpha(collapsedSet, it.id, viewModel.areSubtitlesVisible) + } + + bindRecommendationsGuts(viewHolder, viewModel, mediaViewController, falsingManager) + + mediaViewController.refreshState() + } + + private fun bindRecommendationsGuts( + viewHolder: RecommendationViewHolder, + viewModel: MediaRecsCardViewModel, + mediaViewController: MediaViewController, + falsingManager: FalsingManager, + ) { + val gutsViewHolder = viewHolder.gutsViewHolder + val gutsViewModel = viewModel.gutsMenu + + gutsViewHolder.gutsText.text = gutsViewModel.gutsText + gutsViewHolder.dismissText.visibility = View.VISIBLE + gutsViewHolder.dismiss.isEnabled = true + gutsViewHolder.dismiss.setOnClickListener { + if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@setOnClickListener + closeGuts(viewHolder, viewModel, mediaViewController) + gutsViewModel.onDismissClicked.invoke() + } + + gutsViewHolder.cancelText.background = gutsViewModel.cancelTextBackground + gutsViewHolder.cancel.setOnClickListener { + if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + closeGuts(viewHolder, viewModel, mediaViewController) + } + } + + gutsViewHolder.settings.setOnClickListener { + if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + gutsViewModel.onSettingsClicked.invoke() + } + } + + gutsViewHolder.setDismissible(gutsViewModel.isDismissEnabled) + gutsViewHolder.setTextPrimaryColor(gutsViewModel.textPrimaryColor) + gutsViewHolder.setAccentPrimaryColor(gutsViewModel.accentPrimaryColor) + gutsViewHolder.setSurfaceColor(gutsViewModel.surfaceColor) + } + + private fun bindRecommendationsList( + viewHolder: RecommendationViewHolder, + mediaRecs: List<MediaRecViewModel>, + falsingManager: FalsingManager + ) { + mediaRecs.forEachIndexed { index, mediaRecViewModel -> + if (index >= NUM_REQUIRED_RECOMMENDATIONS) return@forEachIndexed + + val appIconView = viewHolder.mediaAppIcons[index] + appIconView.clearColorFilter() + if (mediaRecViewModel.appIcon != null) { + appIconView.setImageDrawable(mediaRecViewModel.appIcon) + } else { + appIconView.setImageResource(R.drawable.ic_music_note) + } + + val mediaCoverContainer = viewHolder.mediaCoverContainers[index] + mediaCoverContainer.setOnClickListener { + if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@setOnClickListener + mediaRecViewModel.onClicked.invoke(Expandable.fromView(it), index) + } + mediaCoverContainer.setOnLongClickListener { + if (falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) + return@setOnLongClickListener true + (it.parent as View).performLongClick() + return@setOnLongClickListener true + } + + val mediaCover = viewHolder.mediaCoverItems[index] + val width: Int = + mediaCover.context.resources.getDimensionPixelSize(R.dimen.qs_media_rec_album_width) + val height: Int = + mediaCover.context.resources.getDimensionPixelSize( + R.dimen.qs_media_rec_album_height_expanded + ) + val coverMatrix = Matrix(mediaCover.imageMatrix) + coverMatrix.postScale(1.25f, 1.25f, 0.5f * width, 0.5f * height) + mediaCover.imageMatrix = coverMatrix + mediaCover.setImageDrawable(mediaRecViewModel.albumIcon) + mediaCover.contentDescription = mediaRecViewModel.contentDescription + + val title = viewHolder.mediaTitles[index] + title.text = mediaRecViewModel.title + title.setTextColor(ColorStateList.valueOf(mediaRecViewModel.titleColor)) + + val subtitle = viewHolder.mediaSubtitles[index] + subtitle.text = mediaRecViewModel.subtitle + subtitle.setTextColor(ColorStateList.valueOf(mediaRecViewModel.subtitleColor)) + + val progressBar = viewHolder.mediaProgressBars[index] + progressBar.progress = mediaRecViewModel.progress + progressBar.progressTintList = ColorStateList.valueOf(mediaRecViewModel.progressColor) + if (mediaRecViewModel.progress == 0) { + progressBar.visibility = View.GONE + } + } + } + + private fun openGuts( + viewHolder: RecommendationViewHolder, + viewModel: MediaRecsCardViewModel, + mediaViewController: MediaViewController, + ) { + viewHolder.marquee(true, MediaViewController.GUTS_ANIMATION_DURATION) + mediaViewController.openGuts() + viewHolder.recommendations.contentDescription = viewModel.contentDescription.invoke(true) + viewModel.onLongClicked.invoke() + } + + private fun closeGuts( + viewHolder: RecommendationViewHolder, + mediaRecsCardViewModel: MediaRecsCardViewModel, + mediaViewController: MediaViewController, + ) { + viewHolder.marquee(false, MediaViewController.GUTS_ANIMATION_DURATION) + mediaViewController.closeGuts(false) + viewHolder.recommendations.contentDescription = + mediaRecsCardViewModel.contentDescription.invoke(false) + } + + private fun setVisibleAndAlpha(set: ConstraintSet, resId: Int, visible: Boolean) { + set.setVisibility(resId, if (visible) ConstraintSet.VISIBLE else ConstraintSet.GONE) + set.setAlpha(resId, if (visible) 1.0f else 0.0f) + } + + private fun updateRecommendationsVisibility( + mediaViewController: MediaViewController, + cardView: TransitionLayout, + ) { + val fittedRecsNum = getNumberOfFittedRecommendations(cardView.context) + val expandedSet = mediaViewController.expandedLayout + val collapsedSet = mediaViewController.collapsedLayout + val mediaCoverContainers = getMediaCoverContainers(cardView) + // Hide media cover that cannot fit in the recommendation card. + mediaCoverContainers.forEachIndexed { index, container -> + setVisibleAndAlpha(expandedSet, container.id, index < fittedRecsNum) + setVisibleAndAlpha(collapsedSet, container.id, index < fittedRecsNum) + } + } + + private fun getMediaCoverContainers(cardView: TransitionLayout): List<ViewGroup> { + return listOf<ViewGroup>( + cardView.requireViewById(R.id.media_cover1_container), + cardView.requireViewById(R.id.media_cover2_container), + cardView.requireViewById(R.id.media_cover3_container), + ) + } + + private fun getNumberOfFittedRecommendations(context: Context): Int { + val res = context.resources + val config = res.configuration + val defaultDpWidth = res.getInteger(R.integer.default_qs_media_rec_width_dp) + val recCoverWidth = + (res.getDimensionPixelSize(R.dimen.qs_media_rec_album_width) + + res.getDimensionPixelSize(R.dimen.qs_media_info_spacing) * 2) + + // On landscape, media controls should take half of the screen width. + val displayAvailableDpWidth = + if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { + config.screenWidthDp / 2 + } else { + config.screenWidthDp + } + val fittedNum = + if (displayAvailableDpWidth > defaultDpWidth) { + val recCoverDefaultWidth = + res.getDimensionPixelSize(R.dimen.qs_media_rec_default_width) + recCoverDefaultWidth / recCoverWidth + } else { + val displayAvailableWidth = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + displayAvailableDpWidth.toFloat(), + res.displayMetrics + ) + .toInt() + displayAvailableWidth / recCoverWidth + } + return min(fittedNum.toDouble(), NUM_REQUIRED_RECOMMENDATIONS.toDouble()).toInt() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt index 963c602b3d1e..c02ce3b0a6c0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt @@ -297,6 +297,7 @@ constructor( } } - private val activeContainer: ViewGroup? = - if (useSplitShade) splitShadeContainer else singlePaneContainer + // This field is only used to log current active container. + private val activeContainer: ViewGroup? + get() = if (useSplitShade) splitShadeContainer else singlePaneContainer } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt index c3c1e83546df..d15d45a477d7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt @@ -46,6 +46,8 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.KeyguardState.GONE +import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.media.controls.domain.pipeline.MediaDataManager @@ -600,7 +602,8 @@ constructor( @VisibleForTesting internal fun listenForAnyStateToGoneKeyguardTransition(scope: CoroutineScope): Job { return scope.launch { - keyguardTransitionInteractor.anyStateToGoneTransition + keyguardTransitionInteractor + .transition(to = GONE) .filter { it.transitionState == TransitionState.FINISHED } .collect { showMediaCarousel() @@ -612,7 +615,8 @@ constructor( @VisibleForTesting internal fun listenForAnyStateToLockscreenTransition(scope: CoroutineScope): Job { return scope.launch { - keyguardTransitionInteractor.anyStateToLockscreenTransition + keyguardTransitionInteractor + .transition(to = LOCKSCREEN) .filter { it.transitionState == TransitionState.FINISHED } .collect { if (!allowMediaPlayerOnLockScreen) { diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java index 899b9ed103cd..bd3893bd2701 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java @@ -118,8 +118,9 @@ import com.android.systemui.res.R; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.surfaceeffects.PaintDrawCallback; import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect; -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState; +import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.AnimationState; import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView; import com.android.systemui.surfaceeffects.ripple.MultiRippleController; import com.android.systemui.surfaceeffects.ripple.MultiRippleView; @@ -264,15 +265,15 @@ public class MediaControlPanel { private boolean mWasPlaying = false; private boolean mButtonClicked = false; - private final LoadingEffect.Companion.PaintDrawCallback mNoiseDrawCallback = - new LoadingEffect.Companion.PaintDrawCallback() { + private final PaintDrawCallback mNoiseDrawCallback = + new PaintDrawCallback() { @Override - public void onDraw(@NonNull Paint loadingPaint) { - mMediaViewHolder.getLoadingEffectView().draw(loadingPaint); + public void onDraw(@NonNull Paint paint) { + mMediaViewHolder.getLoadingEffectView().draw(paint); } }; - private final LoadingEffect.Companion.AnimationStateChangedCallback mStateChangedCallback = - new LoadingEffect.Companion.AnimationStateChangedCallback() { + private final LoadingEffect.AnimationStateChangedCallback mStateChangedCallback = + new LoadingEffect.AnimationStateChangedCallback() { @Override public void onStateChanged(@NonNull AnimationState oldState, @NonNull AnimationState newState) { @@ -737,8 +738,11 @@ public class MediaControlPanel { mPackageName, mMediaViewHolder.getSeamlessButton()); } else { mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId); - mMediaOutputDialogManager.createAndShow(mPackageName, true, - mMediaViewHolder.getSeamlessButton()); + // TODO: b/321969740 - Populate the userHandle parameter. The user + // handle is necessary to disambiguate the same package running on + // different users. + mMediaOutputDialogManager.createAndShow( + mPackageName, true, mMediaViewHolder.getSeamlessButton(), null); } } else { mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId); @@ -747,22 +751,30 @@ public class MediaControlPanel { boolean showOverLockscreen = mKeyguardStateController.isShowing() && mActivityIntentHelper.wouldPendingShowOverLockscreen( deviceIntent, mLockscreenUserManager.getCurrentUserId()); - if (deviceIntent.isActivity() && !showOverLockscreen) { - mActivityStarter.postStartActivityDismissingKeyguard(deviceIntent); - } else { - try { - BroadcastOptions options = BroadcastOptions.makeBasic(); - options.setInteractive(true); - options.setPendingIntentBackgroundActivityStartMode( + if (deviceIntent.isActivity()) { + if (!showOverLockscreen) { + mActivityStarter.postStartActivityDismissingKeyguard( + deviceIntent); + } else { + try { + BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setInteractive(true); + options.setPendingIntentBackgroundActivityStartMode( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - deviceIntent.send(options.toBundle()); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Device pending intent was canceled"); + deviceIntent.send(options.toBundle()); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Device pending intent was canceled"); + } } + } else { + Log.w(TAG, "Device pending intent is not an activity."); } } else { - mMediaOutputDialogManager.createAndShow(mPackageName, true, - mMediaViewHolder.getSeamlessButton()); + // TODO: b/321969740 - Populate the userHandle parameter. The user + // handle is necessary to disambiguate the same package running on + // different users. + mMediaOutputDialogManager.createAndShow( + mPackageName, true, mMediaViewHolder.getSeamlessButton(), null); } } }); diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt index ad7990b92931..7fced5f8036f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt @@ -16,41 +16,73 @@ package com.android.systemui.media.controls.ui.controller +import android.animation.Animator +import android.animation.AnimatorInflater +import android.animation.AnimatorSet import android.content.Context import android.content.res.Configuration +import android.graphics.Color +import android.graphics.Paint +import android.graphics.drawable.Drawable +import android.provider.Settings +import android.view.View +import android.view.animation.Interpolator import androidx.annotation.VisibleForTesting import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT +import com.android.app.animation.Interpolators import com.android.app.tracing.traceSection +import com.android.systemui.Flags +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.media.controls.ui.animation.ColorSchemeTransition +import com.android.systemui.media.controls.ui.animation.MetadataAnimationHandler +import com.android.systemui.media.controls.ui.binder.MediaControlViewBinder +import com.android.systemui.media.controls.ui.binder.SeekBarObserver import com.android.systemui.media.controls.ui.controller.MediaCarouselController.Companion.calculateAlpha import com.android.systemui.media.controls.ui.view.GutsViewHolder import com.android.systemui.media.controls.ui.view.MediaHostState import com.android.systemui.media.controls.ui.view.MediaViewHolder import com.android.systemui.media.controls.ui.view.RecommendationViewHolder +import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel +import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.surfaceeffects.PaintDrawCallback +import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect +import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView +import com.android.systemui.surfaceeffects.ripple.MultiRippleController +import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig +import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController +import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader +import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView import com.android.systemui.util.animation.MeasurementInput import com.android.systemui.util.animation.MeasurementOutput import com.android.systemui.util.animation.TransitionLayout import com.android.systemui.util.animation.TransitionLayoutController import com.android.systemui.util.animation.TransitionViewState +import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.settings.GlobalSettings import java.lang.Float.max import java.lang.Float.min +import java.util.Random import javax.inject.Inject /** * A class responsible for controlling a single instance of a media player handling interactions * with the view instance and keeping the media view states up to date. */ -class MediaViewController +open class MediaViewController @Inject constructor( private val context: Context, private val configurationController: ConfigurationController, private val mediaHostStatesManager: MediaHostStatesManager, private val logger: MediaViewLogger, + private val seekBarViewModel: SeekBarViewModel, + @Main private val mainExecutor: DelayableExecutor, private val mediaFlags: MediaFlags, + private val globalSettings: GlobalSettings, ) { /** @@ -69,6 +101,7 @@ constructor( /** A listener when the current dimensions of the player change */ lateinit var sizeChangedListener: () -> Unit lateinit var configurationChangeListener: () -> Unit + lateinit var recsConfigurationChangeListener: (MediaViewController, TransitionLayout) -> Unit private var firstRefresh: Boolean = true @VisibleForTesting private var transitionLayout: TransitionLayout? = null private val layoutController = TransitionLayoutController() @@ -130,6 +163,72 @@ constructor( return transitionLayout?.translationY ?: 0.0f } + /** Whether artwork is bound. */ + var isArtworkBound: Boolean = false + + /** previous background artwork */ + var prevArtwork: Drawable? = null + + /** Whether scrubbing time can show */ + var canShowScrubbingTime: Boolean = false + + /** Whether user is touching the seek bar to change the position */ + var isScrubbing: Boolean = false + + var isSeekBarEnabled: Boolean = false + + /** Not visible value for previous button when scrubbing */ + private var prevNotVisibleValue = ConstraintSet.GONE + private var isPrevButtonAvailable = false + + /** Not visible value for next button when scrubbing */ + private var nextNotVisibleValue = ConstraintSet.GONE + private var isNextButtonAvailable = false + + private lateinit var mediaViewHolder: MediaViewHolder + private lateinit var seekBarObserver: SeekBarObserver + private lateinit var turbulenceNoiseController: TurbulenceNoiseController + private lateinit var loadingEffect: LoadingEffect + private lateinit var turbulenceNoiseAnimationConfig: TurbulenceNoiseAnimationConfig + private lateinit var noiseDrawCallback: PaintDrawCallback + private lateinit var stateChangedCallback: LoadingEffect.AnimationStateChangedCallback + internal lateinit var metadataAnimationHandler: MetadataAnimationHandler + internal lateinit var colorSchemeTransition: ColorSchemeTransition + internal lateinit var multiRippleController: MultiRippleController + + private val scrubbingChangeListener = + object : SeekBarViewModel.ScrubbingChangeListener { + override fun onScrubbingChanged(scrubbing: Boolean) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + if (isScrubbing == scrubbing) return + isScrubbing = scrubbing + updateDisplayForScrubbingChange() + } + } + + private val enabledChangeListener = + object : SeekBarViewModel.EnabledChangeListener { + override fun onEnabledChanged(enabled: Boolean) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + if (isSeekBarEnabled == enabled) return + isSeekBarEnabled = enabled + MediaControlViewBinder.updateSeekBarVisibility(expandedLayout, isSeekBarEnabled) + } + } + + /** + * Sets the listening state of the player. + * + * Should be set to true when the QS panel is open. Otherwise, false. This is a signal to avoid + * unnecessary work when the QS panel is closed. + * + * @param listening True when player should be active. Otherwise, false. + */ + fun setListening(listening: Boolean) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + seekBarViewModel.listening = listening + } + /** A callback for config changes */ private val configurationListener = object : ConfigurationController.ConfigurationListener { @@ -160,7 +259,17 @@ constructor( ) ) } - if (this@MediaViewController::configurationChangeListener.isInitialized) { + if (mediaFlags.isMediaControlsRefactorEnabled()) { + if ( + this@MediaViewController::recsConfigurationChangeListener.isInitialized + ) { + transitionLayout?.let { + recsConfigurationChangeListener.invoke(this@MediaViewController, it) + } + } + } else if ( + this@MediaViewController::configurationChangeListener.isInitialized + ) { configurationChangeListener.invoke() refreshState() } @@ -221,6 +330,14 @@ constructor( * Notify this controller that the view has been removed and all listeners should be destroyed */ fun onDestroy() { + if (mediaFlags.isMediaControlsRefactorEnabled()) { + if (this::seekBarObserver.isInitialized) { + seekBarViewModel.progress.removeObserver(seekBarObserver) + } + seekBarViewModel.removeScrubbingChangeListener(scrubbingChangeListener) + seekBarViewModel.removeEnabledChangeListener(enabledChangeListener) + seekBarViewModel.onDestroy() + } mediaHostStatesManager.removeController(this) configurationController.removeCallback(configurationListener) } @@ -535,6 +652,178 @@ constructor( ) } + fun attachPlayer(mediaViewHolder: MediaViewHolder) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + this.mediaViewHolder = mediaViewHolder + + // Setting up seek bar. + seekBarObserver = SeekBarObserver(mediaViewHolder) + seekBarViewModel.progress.observeForever(seekBarObserver) + seekBarViewModel.attachTouchHandlers(mediaViewHolder.seekBar) + seekBarViewModel.setScrubbingChangeListener(scrubbingChangeListener) + seekBarViewModel.setEnabledChangeListener(enabledChangeListener) + + val mediaCard = mediaViewHolder.player + attach(mediaViewHolder.player, TYPE.PLAYER) + + val turbulenceNoiseView = mediaViewHolder.turbulenceNoiseView + turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView) + + multiRippleController = MultiRippleController(mediaViewHolder.multiRippleView) + + // Metadata Animation + val titleText = mediaViewHolder.titleText + val artistText = mediaViewHolder.artistText + val explicitIndicator = mediaViewHolder.explicitIndicator + val enter = + loadAnimator( + mediaCard.context, + R.anim.media_metadata_enter, + Interpolators.EMPHASIZED_DECELERATE, + titleText, + artistText, + explicitIndicator + ) + val exit = + loadAnimator( + mediaCard.context, + R.anim.media_metadata_exit, + Interpolators.EMPHASIZED_ACCELERATE, + titleText, + artistText, + explicitIndicator + ) + metadataAnimationHandler = MetadataAnimationHandler(exit, enter) + + colorSchemeTransition = + ColorSchemeTransition( + mediaCard.context, + mediaViewHolder, + multiRippleController, + turbulenceNoiseController + ) + + // For Turbulence noise. + val loadingEffectView = mediaViewHolder.loadingEffectView + turbulenceNoiseAnimationConfig = + createTurbulenceNoiseConfig( + loadingEffectView, + turbulenceNoiseView, + colorSchemeTransition + ) + noiseDrawCallback = + object : PaintDrawCallback { + override fun onDraw(paint: Paint) { + loadingEffectView.draw(paint) + } + } + stateChangedCallback = + object : LoadingEffect.AnimationStateChangedCallback { + override fun onStateChanged( + oldState: LoadingEffect.AnimationState, + newState: LoadingEffect.AnimationState + ) { + if (newState === LoadingEffect.AnimationState.NOT_PLAYING) { + loadingEffectView.visibility = View.INVISIBLE + } else { + loadingEffectView.visibility = View.VISIBLE + } + } + } + } + + fun updateAnimatorDurationScale() { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + if (this::seekBarObserver.isInitialized) { + seekBarObserver.animationEnabled = + globalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f + } + } + + /** update view with the needed UI changes when user touches seekbar. */ + private fun updateDisplayForScrubbingChange() { + mainExecutor.execute { + val isTimeVisible = canShowScrubbingTime && isScrubbing + MediaControlViewBinder.setVisibleAndAlpha( + expandedLayout, + mediaViewHolder.scrubbingTotalTimeView.id, + isTimeVisible + ) + MediaControlViewBinder.setVisibleAndAlpha( + expandedLayout, + mediaViewHolder.scrubbingElapsedTimeView.id, + isTimeVisible + ) + + MediaControlViewModel.SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach { id -> + val isButtonVisible: Boolean + val notVisibleValue: Int + when (id) { + R.id.actionPrev -> { + isButtonVisible = isPrevButtonAvailable && !isTimeVisible + notVisibleValue = prevNotVisibleValue + } + R.id.actionNext -> { + isButtonVisible = isNextButtonAvailable && !isTimeVisible + notVisibleValue = nextNotVisibleValue + } + else -> { + isButtonVisible = !isTimeVisible + notVisibleValue = ConstraintSet.GONE + } + } + MediaControlViewBinder.setSemanticButtonVisibleAndAlpha( + mediaViewHolder.getAction(id), + expandedLayout, + collapsedLayout, + isButtonVisible, + notVisibleValue, + showInCollapsed = true + ) + } + + if (!metadataAnimationHandler.isRunning) { + refreshState() + } + } + } + + fun bindSeekBar(onSeek: () -> Unit, onBindSeekBar: (SeekBarViewModel) -> Unit) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + seekBarViewModel.logSeek = onSeek + onBindSeekBar.invoke(seekBarViewModel) + } + + fun setUpTurbulenceNoise() { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + if (Flags.shaderlibLoadingEffectRefactor()) { + if (!this::loadingEffect.isInitialized) { + loadingEffect = + LoadingEffect( + TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, + turbulenceNoiseAnimationConfig, + noiseDrawCallback, + stateChangedCallback + ) + } + colorSchemeTransition.loadingEffect = loadingEffect + loadingEffect.play() + mainExecutor.executeDelayed( + loadingEffect::finish, + MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION + ) + } else { + turbulenceNoiseController.play( + TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, + turbulenceNoiseAnimationConfig + ) + mainExecutor.executeDelayed( + turbulenceNoiseController::finish, + MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION + ) + } + } + /** * Obtain a measurement for a given location. This makes sure that the state is up to date and * all widgets know their location. Calling this method may create a measurement if we don't @@ -790,6 +1079,75 @@ constructor( applyImmediately = true ) } + + @VisibleForTesting + protected open fun loadAnimator( + context: Context, + animId: Int, + motionInterpolator: Interpolator?, + vararg targets: View? + ): AnimatorSet { + val animators = ArrayList<Animator>() + for (target in targets) { + val animator = AnimatorInflater.loadAnimator(context, animId) as AnimatorSet + animator.childAnimations[0].interpolator = motionInterpolator + animator.setTarget(target) + animators.add(animator) + } + val result = AnimatorSet() + result.playTogether(animators) + return result + } + + private fun createTurbulenceNoiseConfig( + loadingEffectView: LoadingEffectView, + turbulenceNoiseView: TurbulenceNoiseView, + colorSchemeTransition: ColorSchemeTransition + ): TurbulenceNoiseAnimationConfig { + val targetView: View = + if (Flags.shaderlibLoadingEffectRefactor()) { + loadingEffectView + } else { + turbulenceNoiseView + } + val width = targetView.width + val height = targetView.height + val random = Random() + return TurbulenceNoiseAnimationConfig( + gridCount = 2.14f, + TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER, + random.nextFloat(), + random.nextFloat(), + random.nextFloat(), + noiseMoveSpeedX = 0.42f, + noiseMoveSpeedY = 0f, + TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z, + // Color will be correctly updated in ColorSchemeTransition. + colorSchemeTransition.accentPrimary.currentColor, + screenColor = Color.BLACK, + width.toFloat(), + height.toFloat(), + TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS, + easeInDuration = 1350f, + easeOutDuration = 1350f, + targetView.context.resources.displayMetrics.density, + lumaMatteBlendFactor = 0.26f, + lumaMatteOverallBrightness = 0.09f, + shouldInverseNoiseLuminosity = false + ) + } + + fun setUpPrevButtonInfo(isAvailable: Boolean, notVisibleValue: Int = ConstraintSet.GONE) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + isPrevButtonAvailable = isAvailable + prevNotVisibleValue = notVisibleValue + } + + fun setUpNextButtonInfo(isAvailable: Boolean, notVisibleValue: Int = ConstraintSet.GONE) { + if (!mediaFlags.isMediaControlsRefactorEnabled()) return + isNextButtonAvailable = isAvailable + nextNotVisibleValue = notVisibleValue + } } /** An internal key for the cache of mediaViewStates. This is a subset of the full host state. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt index eec43a68adfd..3b09f4138658 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt @@ -18,6 +18,7 @@ package com.android.systemui.media.controls.ui.util import android.app.WallpaperColors import android.content.Context +import android.content.pm.PackageManager import android.graphics.Rect import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable @@ -27,6 +28,7 @@ import android.util.Log import com.android.systemui.media.controls.ui.animation.backgroundEndFromScheme import com.android.systemui.media.controls.ui.animation.backgroundStartFromScheme import com.android.systemui.monet.ColorScheme +import com.android.systemui.monet.Style import com.android.systemui.util.getColorWithAlpha import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext @@ -94,4 +96,21 @@ object MediaArtworkHelper { ) return LayerDrawable(arrayOf(albumArt, gradient)) } + + /** Returns [ColorScheme] of media app given its [packageName]. */ + fun getColorScheme( + applicationContext: Context, + packageName: String, + tag: String, + style: Style = Style.TONAL_SPOT + ): ColorScheme? { + return try { + // Set up media source app's logo. + val icon = applicationContext.packageManager.getApplicationIcon(packageName) + ColorScheme(WallpaperColors.fromDrawable(icon), darkTheme = true, style) + } catch (e: PackageManager.NameNotFoundException) { + Log.w(tag, "Fail to get media app info", e) + null + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt index e508e1bb1b67..6c7c31c41eeb 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt @@ -22,9 +22,9 @@ import android.graphics.drawable.Drawable /** Models UI state for media guts menu */ data class GutsViewModel( val gutsText: CharSequence, - @ColorInt val textColor: Int, - @ColorInt val buttonBackgroundColor: Int, - @ColorInt val buttonTextColor: Int, + @ColorInt val textPrimaryColor: Int, + @ColorInt val accentPrimaryColor: Int, + @ColorInt val surfaceColor: Int, val isDismissEnabled: Boolean = true, val onDismissClicked: () -> Unit, val cancelTextBackground: Drawable?, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt new file mode 100644 index 000000000000..82099e61009f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.viewmodel + +import android.graphics.drawable.Drawable +import androidx.constraintlayout.widget.ConstraintSet + +/** Models UI state of media buttons in media control. */ +data class MediaActionViewModel( + val icon: Drawable?, + val contentDescription: CharSequence?, + val background: Drawable?, + /** whether action is visible if user is touching seekbar to change position. */ + val isVisibleWhenScrubbing: Boolean = true, + val notVisibleValue: Int = ConstraintSet.GONE, + val showInCollapsed: Boolean, + val rebindId: Int? = null, + val buttonId: Int? = null, + val isEnabled: Boolean, + val onClicked: (Int) -> Unit, +) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt new file mode 100644 index 000000000000..d74506dc2e8d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.viewmodel + +import android.content.Context +import android.content.pm.PackageManager +import android.media.session.MediaController +import android.media.session.MediaSession.Token +import android.text.TextUtils +import android.util.Log +import androidx.constraintlayout.widget.ConstraintSet +import com.android.internal.logging.InstanceId +import com.android.settingslib.flags.Flags.legacyLeAudioSharing +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.media.controls.domain.pipeline.interactor.MediaControlInteractor +import com.android.systemui.media.controls.shared.model.MediaAction +import com.android.systemui.media.controls.shared.model.MediaButton +import com.android.systemui.media.controls.shared.model.MediaControlModel +import com.android.systemui.media.controls.ui.animation.accentPrimaryFromScheme +import com.android.systemui.media.controls.ui.animation.surfaceFromScheme +import com.android.systemui.media.controls.ui.animation.textPrimaryFromScheme +import com.android.systemui.media.controls.ui.util.MediaArtworkHelper +import com.android.systemui.media.controls.util.MediaUiEventLogger +import com.android.systemui.monet.ColorScheme +import com.android.systemui.monet.Style +import com.android.systemui.res.R +import com.android.systemui.util.kotlin.sample +import java.util.concurrent.Executor +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOn + +/** Models UI state and handles user input for a media control. */ +class MediaControlViewModel( + @Application private val applicationContext: Context, + @Background private val backgroundDispatcher: CoroutineDispatcher, + @Background private val backgroundExecutor: Executor, + private val interactor: MediaControlInteractor, + private val logger: MediaUiEventLogger, +) { + + private val isAnyButtonClicked: MutableStateFlow<Boolean> = MutableStateFlow(false) + + private val playTurbulenceNoise: Flow<Boolean> = + interactor.mediaControl.sample( + combine(isAnyButtonClicked, interactor.isStartedPlaying) { + isButtonClicked, + isStartedPlaying -> + isButtonClicked && isStartedPlaying + } + .distinctUntilChanged() + ) + + val player: Flow<MediaPlayerViewModel?> = + combine(playTurbulenceNoise, interactor.mediaControl) { playTurbulenceNoise, mediaControl -> + mediaControl?.let { toViewModel(it, playTurbulenceNoise) } + } + .distinctUntilChanged() + .flowOn(backgroundDispatcher) + + private fun onDismissMediaData( + token: Token?, + uid: Int, + packageName: String, + instanceId: InstanceId + ) { + logger.logLongPressDismiss(uid, packageName, instanceId) + interactor.removeMediaControl(token, instanceId, MEDIA_PLAYER_ANIMATION_DELAY) + } + + private suspend fun toViewModel( + model: MediaControlModel, + playTurbulenceNoise: Boolean + ): MediaPlayerViewModel? { + val wallpaperColors = + MediaArtworkHelper.getWallpaperColor( + applicationContext, + backgroundDispatcher, + model.artwork, + TAG + ) + val scheme = + wallpaperColors?.let { ColorScheme(it, true, Style.CONTENT) } + ?: MediaArtworkHelper.getColorScheme( + applicationContext, + model.packageName, + TAG, + Style.CONTENT + ) + ?: return null + + val gutsViewModel = toGutsViewModel(model, scheme) + + // Resetting button clicks state. + isAnyButtonClicked.value = false + + return MediaPlayerViewModel( + contentDescription = { gutsVisible -> + if (gutsVisible) { + gutsViewModel.gutsText + } else { + applicationContext.getString( + R.string.controls_media_playing_item_description, + model.songName, + model.artistName, + model.appName + ) + } + }, + backgroundCover = model.artwork, + appIcon = model.appIcon, + launcherIcon = getIconFromApp(model.packageName), + useGrayColorFilter = model.appIcon == null || model.isResume, + artistName = model.artistName ?: "", + titleName = model.songName ?: "", + isExplicitVisible = model.showExplicit, + shouldAddGradient = wallpaperColors != null, + colorScheme = scheme, + canShowTime = canShowScrubbingTimeViews(model.semanticActionButtons), + playTurbulenceNoise = playTurbulenceNoise, + useSemanticActions = model.semanticActionButtons != null, + actionButtons = toActionViewModels(model), + outputSwitcher = toOutputSwitcherViewModel(model), + gutsMenu = gutsViewModel, + onClicked = { expandable -> + model.clickIntent?.let { clickIntent -> + logger.logTapContentView(model.uid, model.packageName, model.instanceId) + // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT) + interactor.startClickIntent(expandable, clickIntent) + } + }, + onLongClicked = { + logger.logLongPressOpen(model.uid, model.packageName, model.instanceId) + }, + onSeek = { + logger.logSeek(model.uid, model.packageName, model.instanceId) + // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT) + }, + onBindSeekbar = { seekBarViewModel -> + if (model.isResume && model.resumeProgress != null) { + seekBarViewModel.updateStaticProgress(model.resumeProgress) + } else { + backgroundExecutor.execute { + seekBarViewModel.updateController( + model.token?.let { MediaController(applicationContext, it) } + ) + } + } + } + ) + } + + private fun toOutputSwitcherViewModel(model: MediaControlModel): MediaOutputSwitcherViewModel { + val device = model.deviceData + val showBroadcastButton = legacyLeAudioSharing() && device?.showBroadcastButton == true + + // TODO(b/233698402): Use the package name instead of app label to avoid the unexpected + // result. + val isCurrentBroadcastApp = + device?.name?.let { + TextUtils.equals( + it, + applicationContext.getString(R.string.broadcasting_description_is_broadcasting) + ) + } + ?: false + val useDisabledAlpha = + if (showBroadcastButton) { + !isCurrentBroadcastApp + } else { + device?.enabled == false || model.isResume + } + val deviceString = + device?.name + ?: if (showBroadcastButton) { + applicationContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name) + } else { + applicationContext.getString(R.string.media_seamless_other_device) + } + return MediaOutputSwitcherViewModel( + isTapEnabled = showBroadcastButton || !useDisabledAlpha, + deviceString = deviceString, + deviceIcon = device?.icon?.let { Icon.Loaded(it, null) } + ?: if (showBroadcastButton) { + Icon.Resource(R.drawable.settings_input_antenna, null) + } else { + Icon.Resource(R.drawable.ic_media_home_devices, null) + }, + isCurrentBroadcastApp = isCurrentBroadcastApp, + isIntentValid = device?.intent != null, + alpha = + if (useDisabledAlpha) { + DISABLED_ALPHA + } else { + 1.0f + }, + isVisible = showBroadcastButton, + onClicked = { expandable -> + if (showBroadcastButton) { + // If the current media app is not broadcasted and users press the outputer + // button, we should pop up the broadcast dialog to check do they want to + // switch broadcast to the other media app, otherwise we still pop up the + // media output dialog. + if (!isCurrentBroadcastApp) { + logger.logOpenBroadcastDialog( + model.uid, + model.packageName, + model.instanceId + ) + interactor.startBroadcastDialog( + expandable, + device?.name.toString(), + model.packageName + ) + } else { + logger.logOpenOutputSwitcher(model.uid, model.packageName, model.instanceId) + interactor.startMediaOutputDialog(expandable, model.packageName) + } + } else { + logger.logOpenOutputSwitcher(model.uid, model.packageName, model.instanceId) + device?.intent?.let { interactor.startDeviceIntent(it) } + ?: interactor.startMediaOutputDialog(expandable, model.packageName) + } + } + ) + } + + private fun toGutsViewModel(model: MediaControlModel, scheme: ColorScheme): GutsViewModel { + return GutsViewModel( + gutsText = + if (model.isDismissible) { + applicationContext.getString( + R.string.controls_media_close_session, + model.appName + ) + } else { + applicationContext.getString(R.string.controls_media_active_session) + }, + textPrimaryColor = textPrimaryFromScheme(scheme), + accentPrimaryColor = accentPrimaryFromScheme(scheme), + surfaceColor = surfaceFromScheme(scheme), + isDismissEnabled = model.isDismissible, + onDismissClicked = { + onDismissMediaData(model.token, model.uid, model.packageName, model.instanceId) + }, + cancelTextBackground = + if (model.isDismissible) { + applicationContext.getDrawable(R.drawable.qs_media_outline_button) + } else { + applicationContext.getDrawable(R.drawable.qs_media_solid_button) + }, + onSettingsClicked = { + logger.logLongPressSettings(model.uid, model.packageName, model.instanceId) + interactor.startSettings() + }, + ) + } + + private fun toActionViewModels(model: MediaControlModel): List<MediaActionViewModel?> { + val semanticActionButtons = + model.semanticActionButtons?.let { mediaButton -> + with(mediaButton) { + val isScrubbingTimeEnabled = canShowScrubbingTimeViews(mediaButton) + SEMANTIC_ACTIONS_ALL.map { buttonId -> + getActionById(buttonId)?.let { + toSemanticActionViewModel(model, it, buttonId, isScrubbingTimeEnabled) + } + } + } + } + val notifActionButtons = + model.notificationActionButtons.mapIndexed { index, mediaAction -> + toNotifActionViewModel(model, mediaAction, index) + } + return semanticActionButtons ?: notifActionButtons + } + + private fun toSemanticActionViewModel( + model: MediaControlModel, + mediaAction: MediaAction, + buttonId: Int, + canShowScrubbingTimeViews: Boolean + ): MediaActionViewModel { + val showInCollapsed = SEMANTIC_ACTIONS_COMPACT.contains(buttonId) + val hideWhenScrubbing = SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.contains(buttonId) + val shouldHideWhenScrubbing = canShowScrubbingTimeViews && hideWhenScrubbing + return MediaActionViewModel( + icon = mediaAction.icon, + contentDescription = mediaAction.contentDescription, + background = mediaAction.background, + isVisibleWhenScrubbing = !shouldHideWhenScrubbing, + notVisibleValue = + if ( + (buttonId == R.id.actionPrev && model.semanticActionButtons!!.reservePrev) || + (buttonId == R.id.actionNext && model.semanticActionButtons!!.reserveNext) + ) { + ConstraintSet.INVISIBLE + } else { + ConstraintSet.GONE + }, + showInCollapsed = showInCollapsed, + rebindId = mediaAction.rebindId, + buttonId = buttonId, + isEnabled = mediaAction.action != null, + onClicked = { id -> + mediaAction.action?.let { + onButtonClicked(id, model.uid, model.packageName, model.instanceId, it) + } + }, + ) + } + + private fun toNotifActionViewModel( + model: MediaControlModel, + mediaAction: MediaAction, + index: Int + ): MediaActionViewModel { + return MediaActionViewModel( + icon = mediaAction.icon, + contentDescription = mediaAction.contentDescription, + background = mediaAction.background, + showInCollapsed = model.actionsToShowInCollapsed.contains(index), + rebindId = mediaAction.rebindId, + isEnabled = mediaAction.action != null, + onClicked = { id -> + mediaAction.action?.let { + onButtonClicked(id, model.uid, model.packageName, model.instanceId, it) + } + }, + ) + } + + private fun onButtonClicked( + id: Int, + uid: Int, + packageName: String, + instanceId: InstanceId, + action: Runnable + ) { + logger.logTapAction(id, uid, packageName, instanceId) + // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT) + isAnyButtonClicked.value = true + action.run() + } + + private fun getIconFromApp(packageName: String): Icon { + return try { + Icon.Loaded(applicationContext.packageManager.getApplicationIcon(packageName), null) + } catch (e: PackageManager.NameNotFoundException) { + Log.w(TAG, "Cannot find icon for package $packageName", e) + Icon.Resource(R.drawable.ic_music_note, null) + } + } + + private fun canShowScrubbingTimeViews(semanticActions: MediaButton?): Boolean { + // The scrubbing time views replace the SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING action views, + // so we should only allow scrubbing times to be shown if those action views are present. + return semanticActions?.let { + SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.stream().allMatch { id: Int -> + semanticActions.getActionById(id) != null + } + } + ?: false + } + + companion object { + private const val TAG = "MediaControlViewModel" + private const val MEDIA_PLAYER_ANIMATION_DELAY = 334L + private const val DISABLED_ALPHA = 0.38f + + /** Buttons to show in small player when using semantic actions */ + val SEMANTIC_ACTIONS_COMPACT = + listOf(R.id.actionPlayPause, R.id.actionPrev, R.id.actionNext) + + /** + * Buttons that should get hidden when we are scrubbing (they will be replaced with the + * views showing scrubbing time) + */ + val SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING = listOf(R.id.actionPrev, R.id.actionNext) + + /** Buttons to show in player when using semantic actions. */ + val SEMANTIC_ACTIONS_ALL = + listOf( + R.id.actionPlayPause, + R.id.actionPrev, + R.id.actionNext, + R.id.action0, + R.id.action1 + ) + + const val TURBULENCE_NOISE_PLAY_MS_DURATION = 7500L + const val MEDIA_PLAYER_SCRIM_START_ALPHA = 0.25f + const val MEDIA_PLAYER_SCRIM_END_ALPHA = 1.0f + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt new file mode 100644 index 000000000000..9df9bccdf522 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.viewmodel + +import com.android.systemui.animation.Expandable +import com.android.systemui.common.shared.model.Icon + +/** Models UI state of output switcher chip. */ +data class MediaOutputSwitcherViewModel( + val isTapEnabled: Boolean, + val deviceString: CharSequence, + val deviceIcon: Icon, + val isCurrentBroadcastApp: Boolean, + val isIntentValid: Boolean, + val alpha: Float, + val isVisible: Boolean, + val onClicked: (Expandable) -> Unit, +) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt new file mode 100644 index 000000000000..d1014e83ea11 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.viewmodel + +import com.android.systemui.animation.Expandable +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.monet.ColorScheme + +/** Models UI state for media player. */ +data class MediaPlayerViewModel( + val contentDescription: (Boolean) -> CharSequence, + val backgroundCover: android.graphics.drawable.Icon?, + val appIcon: android.graphics.drawable.Icon?, + val launcherIcon: Icon, + val useGrayColorFilter: Boolean, + val artistName: CharSequence, + val titleName: CharSequence, + val isExplicitVisible: Boolean, + val shouldAddGradient: Boolean, + val colorScheme: ColorScheme, + val canShowTime: Boolean, + val playTurbulenceNoise: Boolean, + val useSemanticActions: Boolean, + val actionButtons: List<MediaActionViewModel?>, + val outputSwitcher: MediaOutputSwitcherViewModel, + val gutsMenu: GutsViewModel, + val onClicked: (Expandable) -> Unit, + val onLongClicked: () -> Unit, + val onSeek: () -> Unit, + val onBindSeekbar: (SeekBarViewModel) -> Unit, +) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt index 19ea00d439b2..a2307d407396 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt @@ -16,10 +16,8 @@ package com.android.systemui.media.controls.ui.viewmodel -import android.app.WallpaperColors import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.Color import android.graphics.drawable.BitmapDrawable @@ -122,7 +120,9 @@ constructor( return null } - val scheme = getColorScheme(model.packageName) ?: return null + val scheme = + MediaArtworkHelper.getColorScheme(applicationContext, model.packageName, TAG) + ?: return null // Capture width & height from views in foreground for artwork scaling in background val width = @@ -213,9 +213,9 @@ constructor( return GutsViewModel( gutsText = applicationContext.getString(R.string.controls_media_close_session, model.appName), - textColor = textPrimaryFromScheme(scheme), - buttonBackgroundColor = accentPrimaryFromScheme(scheme), - buttonTextColor = surfaceFromScheme(scheme), + textPrimaryColor = textPrimaryFromScheme(scheme), + accentPrimaryColor = accentPrimaryFromScheme(scheme), + surfaceColor = surfaceFromScheme(scheme), onDismissClicked = { onMediaRecommendationsDismissed( model.key, @@ -304,20 +304,6 @@ constructor( } } - private fun getColorScheme(packageName: String): ColorScheme? { - // Set up recommendation card's header. - return try { - val packageManager = applicationContext.packageManager - val applicationInfo = packageManager.getApplicationInfo(packageName, 0 /* flags */) - // Set up media source app's logo. - val icon = packageManager.getApplicationIcon(applicationInfo) - ColorScheme(WallpaperColors.fromDrawable(icon), darkTheme = true) - } catch (e: PackageManager.NameNotFoundException) { - Log.w(TAG, "Fail to get media recommendation's app info", e) - null - } - } - /** Returns a [Drawable] of a given [artworkIcon] scaled to [width]x[height] size, . */ private fun getScaledRecommendationCover( artworkIcon: Icon, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt index 452cb7e29f20..ff8e903b6637 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt @@ -31,8 +31,9 @@ constructor( ) { /** Creates a [LocalMediaManager] for the given package. */ fun create(packageName: String?): LocalMediaManager { - return InfoMediaManager.createInstance(context, packageName, localBluetoothManager).run { - LocalMediaManager(context, localBluetoothManager, this, packageName) - } + // TODO: b/321969740 - Populate the userHandle parameter in InfoMediaManager. The user + // handle is necessary to disambiguate the same package running on different users. + return InfoMediaManager.createInstance(context, packageName, null, localBluetoothManager) + .run { LocalMediaManager(context, localBluetoothManager, this, packageName) } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt index d4bd6daedfab..4e77d13b3303 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt @@ -21,16 +21,11 @@ import android.os.UserHandle import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import javax.inject.Inject @SysUISingleton -class MediaFlags -@Inject -constructor( - private val featureFlags: FeatureFlagsClassic, - private val sceneContainerFlags: SceneContainerFlags -) { +class MediaFlags @Inject constructor(private val featureFlags: FeatureFlagsClassic) { /** * Check whether media control actions should be based on PlaybackState instead of notification */ @@ -57,7 +52,7 @@ constructor( /** Check whether to use scene framework */ fun isSceneContainerEnabled() = - sceneContainerFlags.isEnabled() && MediaInSceneContainerFlag.isEnabled + SceneContainerFlag.isEnabled && MediaInSceneContainerFlag.isEnabled /** Check whether to use media refactor code */ fun isMediaControlsRefactorEnabled() = MediaControlsRefactorFlag.isEnabled diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt index 54d175c6a110..06267e243456 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt @@ -38,7 +38,9 @@ constructor( // Dismiss the previous dialog, if any. mediaOutputBroadcastDialog?.dismiss() - val controller = mediaOutputControllerFactory.create(packageName) + // TODO: b/321969740 - Populate the userHandle parameter. The user handle is necessary to + // disambiguate the same package running on different users. + val controller = mediaOutputControllerFactory.create(packageName, /* userHandle= */ null) val dialog = MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller) mediaOutputBroadcastDialog = dialog diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 4db89d18ef7d..d6ca32079b09 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -124,6 +124,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private static final String ALLOWLIST_REASON = "mediaoutput:remote_transfer"; private final String mPackageName; + private final UserHandle mUserHandle; private final Context mContext; private final MediaSessionManager mMediaSessionManager; private final LocalBluetoothManager mLocalBluetoothManager; @@ -177,6 +178,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, public MediaOutputController( Context context, @Assisted String packageName, + @Assisted @Nullable UserHandle userHandle, MediaSessionManager mediaSessionManager, @Nullable LocalBluetoothManager lbm, ActivityStarter starter, @@ -190,6 +192,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, UserTracker userTracker) { mContext = context; mPackageName = packageName; + mUserHandle = userHandle; mMediaSessionManager = mediaSessionManager; mLocalBluetoothManager = lbm; mActivityStarter = starter; @@ -199,7 +202,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mKeyGuardManager = keyGuardManager; mFeatureFlags = featureFlags; mUserTracker = userTracker; - InfoMediaManager imm = InfoMediaManager.createInstance(mContext, packageName, lbm); + InfoMediaManager imm = + InfoMediaManager.createInstance(mContext, packageName, userHandle, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mDialogTransitionAnimator = dialogTransitionAnimator; @@ -231,7 +235,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @AssistedFactory public interface Factory { /** Construct a MediaOutputController */ - MediaOutputController create(String packageName); + MediaOutputController create(String packageName, UserHandle userHandle); } protected void start(@NonNull Callback cb) { @@ -946,11 +950,22 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } void launchMediaOutputBroadcastDialog(View mediaOutputDialog, BroadcastSender broadcastSender) { - MediaOutputController controller = new MediaOutputController(mContext, mPackageName, - mMediaSessionManager, mLocalBluetoothManager, mActivityStarter, - mNotifCollection, mDialogTransitionAnimator, mNearbyMediaDevicesManager, - mAudioManager, mPowerExemptionManager, mKeyGuardManager, mFeatureFlags, - mUserTracker); + MediaOutputController controller = + new MediaOutputController( + mContext, + mPackageName, + mUserHandle, + mMediaSessionManager, + mLocalBluetoothManager, + mActivityStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyGuardManager, + mFeatureFlags, + mUserTracker); MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true, broadcastSender, controller); dialog.show(); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt index e7816a40bb5e..04d1492ff656 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt @@ -17,6 +17,7 @@ package com.android.systemui.media.dialog import android.content.Context +import android.os.UserHandle import android.view.View import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.UiEventLogger @@ -41,7 +42,15 @@ constructor( } /** Creates a [MediaOutputDialog] for the given package. */ - open fun createAndShow(packageName: String, aboveStatusBar: Boolean, view: View? = null) { + // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the + // package name. The user handle is necessary to disambiguate the same package running on + // different users. + open fun createAndShow( + packageName: String, + aboveStatusBar: Boolean, + view: View? = null, + userHandle: UserHandle? = null + ) { createAndShowWithController( packageName, aboveStatusBar, @@ -55,20 +64,26 @@ constructor( ) ) }, + userHandle = userHandle, ) } /** Creates a [MediaOutputDialog] for the given package. */ + // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the + // package name. The user handle is necessary to disambiguate the same package running on + // different users. open fun createAndShowWithController( packageName: String, aboveStatusBar: Boolean, controller: DialogTransitionAnimator.Controller?, + userHandle: UserHandle? = null, ) { createAndShow( packageName, aboveStatusBar, dialogTransitionAnimatorController = controller, - includePlaybackAndAppMetadata = true + includePlaybackAndAppMetadata = true, + userHandle = userHandle, ) } @@ -79,20 +94,25 @@ constructor( packageName = null, aboveStatusBar = false, dialogTransitionAnimatorController = null, - includePlaybackAndAppMetadata = false + includePlaybackAndAppMetadata = false, + userHandle = null, ) } + // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the + // package name. The user handle is necessary to disambiguate the same package running on + // different users. private fun createAndShow( packageName: String?, aboveStatusBar: Boolean, dialogTransitionAnimatorController: DialogTransitionAnimator.Controller?, - includePlaybackAndAppMetadata: Boolean = true + includePlaybackAndAppMetadata: Boolean = true, + userHandle: UserHandle? = null, ) { // Dismiss the previous dialog, if any. mediaOutputDialog?.dismiss() - val controller = mediaOutputControllerFactory.create(packageName) + val controller = mediaOutputControllerFactory.create(packageName, userHandle) val mediaOutputDialog = MediaOutputDialog( diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java index 6e7e0f241dd8..9cc288899d45 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java @@ -18,6 +18,7 @@ package com.android.systemui.media.dialog; import android.annotation.MainThread; import android.content.Context; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -52,9 +53,10 @@ public class MediaOutputSwitcherDialogUI implements CoreStartable, CommandQueue. @Override @MainThread - public void showMediaOutputSwitcher(String packageName) { + public void showMediaOutputSwitcher(String packageName, UserHandle userHandle) { if (!TextUtils.isEmpty(packageName)) { - mMediaOutputDialogManager.createAndShow(packageName, false, null); + mMediaOutputDialogManager.createAndShow( + packageName, /* aboveStatusBar= */ false, /* view= */ null, userHandle); } else { Log.e(TAG, "Unable to launch media output dialog. Package name is empty."); } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt index 3e9b546d58c9..2dbe2aa4ef2d 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt @@ -18,7 +18,9 @@ package com.android.systemui.mediaprojection.appselector.data import android.annotation.ColorInt import android.annotation.UserIdInt +import android.app.ActivityManager.RecentTaskInfo import android.content.ComponentName +import com.android.wm.shell.util.SplitBounds data class RecentTask( val taskId: Int, @@ -29,7 +31,25 @@ data class RecentTask( @ColorInt val colorBackground: Int?, val isForegroundTask: Boolean, val userType: UserType, + val splitBounds: SplitBounds?, ) { + constructor( + taskInfo: RecentTaskInfo, + isForegroundTask: Boolean, + userType: UserType, + splitBounds: SplitBounds? = null + ) : this( + taskInfo.taskId, + taskInfo.displayId, + taskInfo.userId, + taskInfo.topActivity, + taskInfo.baseIntent?.component, + taskInfo.taskDescription?.backgroundColor, + isForegroundTask, + userType, + splitBounds + ) + enum class UserType { STANDARD, WORK, diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt index a6049c8b556d..596c18f04134 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt @@ -58,20 +58,27 @@ constructor( val foregroundTaskId1 = foregroundGroup?.taskInfo1?.taskId val foregroundTaskId2 = foregroundGroup?.taskInfo2?.taskId val foregroundTaskIds = listOfNotNull(foregroundTaskId1, foregroundTaskId2) - groupedTasks - .flatMap { listOfNotNull(it.taskInfo1, it.taskInfo2) } - .map { + groupedTasks.flatMap { + val task1 = RecentTask( - it.taskId, - it.displayId, - it.userId, - it.topActivity, - it.baseIntent?.component, - it.taskDescription?.backgroundColor, - isForegroundTask = it.taskId in foregroundTaskIds && it.isVisible, - userType = userManager.getUserInfo(it.userId).toUserType(), + it.taskInfo1, + it.taskInfo1.taskId in foregroundTaskIds && it.taskInfo1.isVisible, + userManager.getUserInfo(it.taskInfo1.userId).toUserType(), + it.splitBounds ) - } + + val task2 = + if (it.taskInfo2 != null) { + RecentTask( + it.taskInfo2!!, + it.taskInfo2!!.taskId in foregroundTaskIds && it.taskInfo2!!.isVisible, + userManager.getUserInfo(it.taskInfo2!!.userId).toUserType(), + it.splitBounds + ) + } else null + + listOfNotNull(task1, task2) + } } private suspend fun RecentTasks.getTasks(): List<GroupedRecentTaskInfo> = diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt index 7c7efd0be8ed..9549ab1cab3e 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt @@ -24,9 +24,12 @@ import android.graphics.Rect import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.window.RemoteTransition import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.android.systemui.Flags.pssAppSelectorAbruptExitFix +import com.android.systemui.Flags.pssAppSelectorRecentsSplitScreen +import com.android.systemui.display.naturalBounds import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope import com.android.systemui.mediaprojection.appselector.data.RecentTask @@ -34,6 +37,11 @@ import com.android.systemui.mediaprojection.appselector.view.RecentTasksAdapter. import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener import com.android.systemui.res.R import com.android.systemui.util.recycler.HorizontalSpacerItemDecoration +import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT +import com.android.wm.shell.splitscreen.SplitScreen +import com.android.wm.shell.util.SplitBounds +import java.util.Optional import javax.inject.Inject /** @@ -48,6 +56,7 @@ constructor( private val taskViewSizeProvider: TaskPreviewSizeProvider, private val activityTaskManager: IActivityTaskManager, private val resultHandler: MediaProjectionAppSelectorResultHandler, + private val splitScreen: Optional<SplitScreen>, ) : RecentTaskClickListener, TaskPreviewSizeListener { private var views: Views? = null @@ -63,11 +72,11 @@ constructor( fun createView(parent: ViewGroup): ViewGroup = views?.root ?: createRecentViews(parent) - .also { - views = it - lastBoundData?.let { recents -> bind(recents) } - } - .root + .also { + views = it + lastBoundData?.let { recents -> bind(recents) } + } + .root fun bind(recentTasks: List<RecentTask>) { views?.apply { @@ -93,8 +102,10 @@ constructor( private fun createRecentViews(parent: ViewGroup): Views { val recentsRoot = LayoutInflater.from(parent.context) - .inflate(R.layout.media_projection_recent_tasks, parent, /* attachToRoot= */ false) - as ViewGroup + .inflate(R.layout.media_projection_recent_tasks, + parent, /* attachToRoot= */ + false) + as ViewGroup val container = recentsRoot.requireViewById<View>(R.id.media_projection_recent_tasks_container) @@ -121,18 +132,34 @@ constructor( return Views(recentsRoot, container, progress, recycler) } + private fun RecentTask.isLaunchingInSplitScreen(): Boolean { + return splitScreen.isPresent && splitBounds != null + } + override fun onRecentAppClicked(task: RecentTask, view: View) { val launchCookie = LaunchCookie() val activityOptions = createAnimation(task, view) activityOptions.pendingIntentBackgroundActivityStartMode = MODE_BACKGROUND_ACTIVITY_START_ALLOWED - activityOptions.setLaunchCookie(launchCookie) activityOptions.launchDisplayId = task.displayId + activityOptions.setLaunchCookie(launchCookie) + + val handleResult: () -> Unit = { resultHandler.returnSelectedApp(launchCookie)} + + val taskId = task.taskId + val splitBounds = task.splitBounds - activityTaskManager.startActivityFromRecents(task.taskId, activityOptions.toBundle()) - resultHandler.returnSelectedApp(launchCookie) + if (pssAppSelectorRecentsSplitScreen() && + task.isLaunchingInSplitScreen() && + !task.isForegroundTask) { + startSplitScreenTask(view, taskId, splitBounds!!, handleResult, activityOptions) + } else { + activityTaskManager.startActivityFromRecents(taskId, activityOptions.toBundle()) + handleResult() + } } + private fun createAnimation(task: RecentTask, view: View): ActivityOptions = if (pssAppSelectorAbruptExitFix() && task.isForegroundTask) { // When the selected task is in the foreground, the scale up animation doesn't work. @@ -145,7 +172,14 @@ constructor( /* startedListener = */ null, /* finishedListener = */ null ) + } else if (task.isLaunchingInSplitScreen()) { + // When the selected task isn't in the foreground, but is launching in split screen, + // then we don't need to specify an animation, since we'll already be passing a + // manually built remote animation to SplitScreenController + ActivityOptions.makeBasic() } else { + // The default case is a selected task not in the foreground and launching fullscreen, + // so for this we can use the default ActivityOptions animation ActivityOptions.makeScaleUpAnimation( view, /* startX= */ 0, @@ -155,6 +189,29 @@ constructor( ) } + private fun startSplitScreenTask( + view: View, + taskId: Int, + splitBounds: SplitBounds, + handleResult: () -> Unit, + activityOptions: ActivityOptions, + ) { + val isLeftTopTask = taskId == splitBounds.leftTopTaskId + val task2Id = + if (isLeftTopTask) splitBounds.rightBottomTaskId else splitBounds.leftTopTaskId + val splitPosition = + if (isLeftTopTask) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT + + val animationRunner = RemoteRecentSplitTaskTransitionRunner(taskId, task2Id, + view.locationOnScreen, view.context.display.naturalBounds, handleResult) + val remoteTransition = RemoteTransition(animationRunner, + view.context.iApplicationThread, "startSplitScreenTask") + + splitScreen.get().startTasks(taskId, activityOptions.toBundle(), task2Id, null, + splitPosition, splitBounds.snapPosition, remoteTransition, null) + } + + override fun onTaskSizeChanged(size: Rect) { views?.recentsContainer?.setTaskHeightSize() } @@ -163,12 +220,12 @@ constructor( val thumbnailHeight = taskViewSizeProvider.size.height() val itemHeight = thumbnailHeight + - context.resources.getDimensionPixelSize( - R.dimen.media_projection_app_selector_task_icon_size - ) + - context.resources.getDimensionPixelSize( - R.dimen.media_projection_app_selector_task_icon_margin - ) * 2 + context.resources.getDimensionPixelSize( + R.dimen.media_projection_app_selector_task_icon_size + ) + + context.resources.getDimensionPixelSize( + R.dimen.media_projection_app_selector_task_icon_margin + ) * 2 layoutParams = layoutParams.apply { height = itemHeight } } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RemoteRecentSplitTaskTransitionRunner.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RemoteRecentSplitTaskTransitionRunner.kt new file mode 100644 index 000000000000..b7942f7888fa --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RemoteRecentSplitTaskTransitionRunner.kt @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.mediaprojection.appselector.view + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import android.animation.ValueAnimator +import android.annotation.UiThread +import android.graphics.Rect +import android.os.IBinder +import android.os.RemoteException +import android.util.Log +import android.view.SurfaceControl +import android.view.animation.DecelerateInterpolator +import android.window.IRemoteTransitionFinishedCallback +import android.window.RemoteTransitionStub +import android.window.TransitionInfo +import android.window.WindowContainerToken +import com.android.app.viewcapture.ViewCapture +import com.android.internal.policy.TransitionAnimation +import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity.Companion.TAG + +class RemoteRecentSplitTaskTransitionRunner( + private val firstTaskId: Int, + private val secondTaskId: Int, + private val viewPosition: IntArray, + private val screenBounds: Rect, + private val handleResult: () -> Unit, +) : RemoteTransitionStub() { + override fun startAnimation( + transition: IBinder?, + info: TransitionInfo?, + t: SurfaceControl.Transaction?, + finishedCallback: IRemoteTransitionFinishedCallback + ) { + val launchAnimation = AnimatorSet() + var rootCandidate = + info!!.changes.firstOrNull { + it.taskInfo?.taskId == firstTaskId || it.taskInfo?.taskId == secondTaskId + } + + // If we could not find a proper root candidate, something went wrong. + check(rootCandidate != null) { "Could not find a split root candidate" } + + // Recurse up the tree until parent is null, then we've found our root. + var parentToken: WindowContainerToken? = rootCandidate.parent + while (parentToken != null) { + rootCandidate = info.getChange(parentToken) ?: break + parentToken = rootCandidate.parent + } + + // Make sure nothing weird happened, like getChange() returning null. + check(rootCandidate != null) { "Failed to find a root leash" } + + // Ending position is the full device screen. + val startingScale = 0.25f + + val startX = viewPosition[0] + val startY = viewPosition[1] + val endX = screenBounds.left + val endY = screenBounds.top + + ViewCapture.MAIN_EXECUTOR.execute { + val progressUpdater = ValueAnimator.ofFloat(0f, 1f) + with(progressUpdater) { + interpolator = DecelerateInterpolator(1.5f) + setDuration(TransitionAnimation.DEFAULT_APP_TRANSITION_DURATION.toLong()) + + addUpdateListener { valueAnimator -> + val progress = valueAnimator.animatedFraction + + val x = startX + ((endX - startX) * progress) + val y = startY + ((endY - startY) * progress) + val scale = startingScale + ((1 - startingScale) * progress) + + t!! + .setPosition(rootCandidate.leash, x, y) + .setScale(rootCandidate.leash, scale, scale) + .setAlpha(rootCandidate.leash, progress) + .apply() + } + + addListener( + object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + try { + onTransitionFinished() + finishedCallback.onTransitionFinished(null, null) + } catch (e: RemoteException) { + Log.e(TAG, "Failed to call transition finished callback", e) + } + } + } + ) + } + + launchAnimation.play(progressUpdater) + launchAnimation.start() + } + } + + @Throws(RemoteException::class) + override fun onTransitionConsumed(transition: IBinder, aborted: Boolean) { + Log.w(TAG, "unexpected consumption of app selector transition: aborted=$aborted") + } + + @UiThread + private fun onTransitionFinished() { + // After finished transition, then invoke callback to close the app selector, so that + // finish animation of app selector does not override the launch animation of the split + // tasks + handleResult() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java index da9e00ddb6c2..e861ddf69aa6 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java @@ -16,8 +16,11 @@ package com.android.systemui.mediaprojection.permission; +import static android.Manifest.permission.LOG_COMPAT_CHANGE; +import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; import static android.media.projection.IMediaProjectionManager.EXTRA_PACKAGE_REUSING_GRANTED_CONSENT; import static android.media.projection.IMediaProjectionManager.EXTRA_USER_REVIEW_GRANTED_CONSENT; +import static android.media.projection.MediaProjectionManager.OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION; import static android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL; import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; @@ -26,11 +29,13 @@ import static com.android.systemui.mediaprojection.permission.ScreenShareOptionK import static com.android.systemui.mediaprojection.permission.ScreenShareOptionKt.SINGLE_APP; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions.LaunchCookie; import android.app.AlertDialog; import android.app.StatusBarManager; +import android.app.compat.CompatChanges; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -108,6 +113,7 @@ public class MediaProjectionPermissionActivity extends Activity } @Override + @RequiresPermission(allOf = {READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE}) public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -235,6 +241,10 @@ public class MediaProjectionPermissionActivity extends Activity // the correct screen width when in split screen. Context dialogContext = getApplicationContext(); if (isPartialScreenSharingEnabled()) { + final boolean overrideDisableSingleAppOption = + CompatChanges.isChangeEnabled( + OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION, + mPackageName, getHostUserHandle()); MediaProjectionPermissionDialogDelegate delegate = new MediaProjectionPermissionDialogDelegate( dialogContext, @@ -246,6 +256,7 @@ public class MediaProjectionPermissionActivity extends Activity }, () -> finish(RECORD_CANCEL, /* projection= */ null), appName, + overrideDisableSingleAppOption, mUid, mMediaProjectionMetricsLogger); mDialog = diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt index 0f54e934f3cf..8858041ae529 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt @@ -30,11 +30,12 @@ class MediaProjectionPermissionDialogDelegate( private val onStartRecordingClicked: Consumer<MediaProjectionPermissionDialogDelegate>, private val onCancelClicked: Runnable, private val appName: String?, + private val forceShowPartialScreenshare: Boolean, hostUid: Int, mediaProjectionMetricsLogger: MediaProjectionMetricsLogger, ) : BaseMediaProjectionPermissionDialogDelegate<AlertDialog>( - createOptionList(context, appName, mediaProjectionConfig), + createOptionList(context, appName, mediaProjectionConfig, forceShowPartialScreenshare), appName, hostUid, mediaProjectionMetricsLogger @@ -65,7 +66,8 @@ class MediaProjectionPermissionDialogDelegate( private fun createOptionList( context: Context, appName: String?, - mediaProjectionConfig: MediaProjectionConfig? + mediaProjectionConfig: MediaProjectionConfig?, + overrideDisableSingleAppOption: Boolean = false, ): List<ScreenShareOption> { val singleAppWarningText = if (appName == null) { @@ -80,8 +82,13 @@ class MediaProjectionPermissionDialogDelegate( R.string.media_projection_entry_app_permission_dialog_warning_entire_screen } + // The single app option should only be disabled if there is an app name provided, + // the client has setup a MediaProjection with + // MediaProjectionConfig#createConfigForDefaultDisplay, AND it hasn't been overridden by + // the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override. val singleAppOptionDisabled = appName != null && + !overrideDisableSingleAppOption && mediaProjectionConfig?.regionToCapture == MediaProjectionConfig.CAPTURE_REGION_FIXED_DISPLAY diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java index 63989ef64c8e..a6b6d61b464b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java @@ -35,6 +35,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE import android.content.ContentResolver; import android.content.Context; +import android.content.res.Configuration; import android.database.ContentObserver; import android.inputmethodservice.InputMethodService; import android.net.Uri; @@ -74,6 +75,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import dagger.Lazy; @@ -101,7 +103,7 @@ public final class NavBarHelper implements AccessibilityButtonModeObserver.ModeChangedListener, AccessibilityButtonTargetsObserver.TargetsChangedListener, OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, - Dumpable, CommandQueue.Callbacks { + Dumpable, CommandQueue.Callbacks, ConfigurationController.ConfigurationListener { private static final String TAG = NavBarHelper.class.getSimpleName(); private final Handler mHandler = new Handler(Looper.getMainLooper()); @@ -189,6 +191,7 @@ public final class NavBarHelper implements UserTracker userTracker, DisplayTracker displayTracker, NotificationShadeWindowController notificationShadeWindowController, + ConfigurationController configurationController, DumpManager dumpManager, CommandQueue commandQueue, @Main Executor mainExecutor) { @@ -215,6 +218,7 @@ public final class NavBarHelper implements mNavBarMode = navigationModeController.addListener(this); mCommandQueue.addCallback(this); + configurationController.addCallback(this); overviewProxyService.addCallback(this); dumpManager.registerDumpable(this); } @@ -359,6 +363,11 @@ public final class NavBarHelper implements updateA11yState(); } + @Override + public void onConfigChanged(Configuration newConfig) { + mEdgeBackGestureHandler.onConfigurationChanged(newConfig); + } + /** * Updates the current accessibility button state. The accessibility button state is only * used for {@link Secure#ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR} and diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index ade56c435421..b6098645f7bc 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -902,11 +902,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements refreshLayout(ld); } repositionNavigationBar(rotation); - // NOTE(b/260220098): In some cases, the recreated nav bar will already have the right - // configuration, which means that NavBarView will not receive a configuration change to - // propagate to EdgeBackGestureHandler (which is injected into this and NBV). As such, we - // should also force-update the gesture handler to ensure it updates to the right bounds - mEdgeBackGestureHandler.onConfigurationChanged(newConfig); if (canShowSecondaryHandle()) { if (rotation != mCurrentRotation) { mCurrentRotation = rotation; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java index 9f7d1b34151a..12f27038e179 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java @@ -162,14 +162,11 @@ public class NavigationBarControllerImpl implements mIsLargeScreen = isLargeScreen(mContext); boolean willApplyConfig = mConfigChanges.applyNewConfig(mContext.getResources()); boolean largeScreenChanged = mIsLargeScreen != isOldConfigLargeScreen; - // TODO(b/243765256): Disable this logging once b/243765256 is fixed. + // TODO(b/332635834): Disable this logging once b/332635834 is fixed. Log.i(DEBUG_MISSING_GESTURE_TAG, "NavbarController: newConfig=" + newConfig + " mTaskbarDelegate initialized=" + mTaskbarDelegate.isInitialized() + " willApplyConfigToNavbars=" + willApplyConfig + " navBarCount=" + mNavigationBars.size()); - if (mTaskbarDelegate.isInitialized()) { - mTaskbarDelegate.onConfigurationChanged(newConfig); - } // If we folded/unfolded while in 3 button, show navbar in folded state, hide in unfolded if (largeScreenChanged && updateNavbarForTaskbar()) { return; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 1927f4932ee0..3c69ed994440 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -1031,7 +1031,6 @@ public class NavigationBarView extends FrameLayout { updateIcons(mTmpLastConfiguration); updateRecentsIcon(); updateCurrentRotation(); - mEdgeBackGestureHandler.onConfigurationChanged(mConfiguration); if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi || mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) { // If car mode or density changes, we need to reset the icons. diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 5dd1bd80140b..f67973bcd70e 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -39,7 +39,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode import android.app.StatusBarManager; import android.app.StatusBarManager.WindowVisibleState; import android.content.Context; -import android.content.res.Configuration; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; @@ -72,7 +71,6 @@ import com.android.systemui.shared.system.TaskStackChangeListeners; import com.android.systemui.statusbar.AutoHideUiElement; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoHideController; -import com.android.systemui.statusbar.phone.BarTransitions; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LightBarTransitionsController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -250,8 +248,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mLightBarController.setNavigationBar(mLightBarTransitionsController); mPipOptional.ifPresent(this::addPipExclusionBoundsChangeListener); mEdgeBackGestureHandler.setBackAnimation(mBackAnimation); - mEdgeBackGestureHandler.onConfigurationChanged( - mContext.getResources().getConfiguration()); mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener); mInitialized = true; } finally { @@ -495,10 +491,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; } - public void onConfigurationChanged(Configuration configuration) { - mEdgeBackGestureHandler.onConfigurationChanged(configuration); - } - @Override public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) { mOverviewProxyService.onNavigationBarLumaSamplingEnabled(displayId, enable); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt index b3d848c2d23b..30f33a3a2f6f 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt @@ -34,7 +34,6 @@ import androidx.annotation.VisibleForTesting import androidx.core.os.postDelayed import androidx.core.view.isVisible import androidx.dynamicanimation.animation.DynamicAnimation -import com.android.internal.jank.Cuj.CUJ_BACK_PANEL_ARROW import com.android.internal.jank.InteractionJankMonitor import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.qualifiers.Main @@ -1039,7 +1038,7 @@ internal constructor( override fun dump(pw: PrintWriter) { pw.println("$TAG:") pw.println(" currentState=$currentState") - pw.println(" isLeftPanel=$mView.isLeftPanel") + pw.println(" isLeftPanel=${mView.isLeftPanel}") } init { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 9d0ea5ebd925..db4a7fad579c 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -1187,7 +1187,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack updateDisabledForQuickstep(newConfig); } - // TODO(b/243765256): Disable this logging once b/243765256 is fixed. + // TODO(b/332635834): Disable this logging once b/332635834 is fixed. Log.i(DEBUG_MISSING_GESTURE_TAG, "Config changed: newConfig=" + newConfig + " lastReportedConfig=" + mLastReportedConfig); mLastReportedConfig.updateFrom(newConfig); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java index ffbc56098e26..7ccdf0ac301a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java @@ -24,7 +24,7 @@ import android.view.View; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.dagger.QSScope; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.ViewController; @@ -66,15 +66,14 @@ public class QSContainerImplController extends ViewController<QSContainerImpl> { QSPanelController qsPanelController, QuickStatusBarHeaderController quickStatusBarHeaderController, ConfigurationController configurationController, - FalsingManager falsingManager, - SceneContainerFlags sceneContainerFlags) { + FalsingManager falsingManager) { super(view); mQsPanelController = qsPanelController; mQuickStatusBarHeaderController = quickStatusBarHeaderController; mConfigurationController = configurationController; mFalsingManager = falsingManager; mQSPanelContainer = mView.getQSPanelContainer(); - mSceneContainerEnabled = sceneContainerFlags.isEnabled(); + mSceneContainerEnabled = SceneContainerFlag.isEnabled(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java index a0607e9f859a..1f4838e85e79 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java @@ -60,7 +60,7 @@ import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder; import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.settings.brightness.MirrorController; import com.android.systemui.shade.transition.LargeScreenShadeInterpolator; import com.android.systemui.statusbar.CommandQueue; @@ -174,8 +174,6 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl @Nullable private View mFooterActionsView; - private final SceneContainerFlags mSceneContainerFlags; - @Inject public QSImpl(RemoteInputQuickSettingsDisabler remoteInputQsDisabler, SysuiStatusBarStateController statusBarStateController, CommandQueue commandQueue, @@ -188,8 +186,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl FooterActionsViewModel.Factory footerActionsViewModelFactory, FooterActionsViewBinder footerActionsViewBinder, LargeScreenShadeInterpolator largeScreenShadeInterpolator, - FeatureFlags featureFlags, - SceneContainerFlags sceneContainerFlags) { + FeatureFlags featureFlags) { mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler; mQsMediaHost = qsMediaHost; mQqsMediaHost = qqsMediaHost; @@ -205,8 +202,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mFooterActionsViewModelFactory = footerActionsViewModelFactory; mFooterActionsViewBinder = footerActionsViewBinder; mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner(); - mSceneContainerFlags = sceneContainerFlags; - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { mStatusBarState = StatusBarState.SHADE; } } @@ -224,7 +220,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mQSPanelController.init(); mQuickQSPanelController.init(); - if (!mSceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled()) { mQSFooterActionsViewModel = mFooterActionsViewModelFactory .create(mListeningAndVisibilityLifecycleOwner); bindFooterActionsView(mRootView); @@ -249,7 +245,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mScrollListener.onQsPanelScrollChanged(scrollY); } }); - mQSPanelScrollView.setScrollingEnabled(!mSceneContainerFlags.isEnabled()); + mQSPanelScrollView.setScrollingEnabled(!SceneContainerFlag.isEnabled()); mHeader = mRootView.findViewById(R.id.header); mFooter = qsComponent.getQSFooter(); @@ -509,7 +505,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl @VisibleForTesting boolean isKeyguardState() { - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { return false; } else { // We want the freshest state here since otherwise we'll have some weirdness if earlier @@ -573,7 +569,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl } private void setKeyguardShowing(boolean keyguardShowing) { - if (!mSceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled()) { if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing); mLastQSExpansion = -1; @@ -651,7 +647,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl @Override public int getHeightDiff() { - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { return mQSPanelController.getViewBottom() - mHeader.getBottom() + mHeader.getPaddingBottom(); } else { @@ -720,7 +716,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); - if (!mSceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled()) { float qsScrollViewTranslation = onKeyguard && !mShowCollapsedOnKeyguard ? panelTranslationY : 0; mQSPanelScrollView.setTranslationY(qsScrollViewTranslation); @@ -824,7 +820,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mQsBounds.set(-sideMargin, 0, mQSPanelScrollView.getWidth() + sideMargin, mQSPanelScrollView.getHeight()); } - if (!mSceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled()) { mQSPanelScrollView.setClipBounds(mQsBounds); mQSPanelScrollView.getLocationOnScreen(mLocationTemp); @@ -907,7 +903,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl // The customize state changed, so our height changed. mContainer.updateExpansion(); boolean customizing = isCustomizing(); - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { mQSPanelController.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); } else { mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); @@ -984,7 +980,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl @Override public void onStateChanged(int newState) { - if (mSceneContainerFlags.isEnabled() || newState == mStatusBarState) { + if (SceneContainerFlag.isEnabled() || newState == mStatusBarState) { return; } mStatusBarState = newState; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 55dc4859cf90..e24caf19a14b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -29,6 +29,7 @@ import androidx.annotation.Nullable; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.systemui.dump.DumpManager; +import com.android.systemui.haptics.qs.QSLongPressEffect; import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager; import com.android.systemui.media.controls.ui.view.MediaHost; import com.android.systemui.media.controls.ui.view.MediaHostState; @@ -36,18 +37,18 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.logging.QSLogger; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.settings.brightness.BrightnessController; import com.android.systemui.settings.brightness.BrightnessMirrorHandler; import com.android.systemui.settings.brightness.BrightnessSliderController; import com.android.systemui.settings.brightness.MirrorController; -import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.tuner.TunerService; import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Provider; /** * Controller for {@link QSPanel}. @@ -93,11 +94,10 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { FalsingManager falsingManager, StatusBarKeyguardViewManager statusBarKeyguardViewManager, SplitShadeStateController splitShadeStateController, - SceneContainerFlags sceneContainerFlags, - VibratorHelper vibratorHelper) { + Provider<QSLongPressEffect> longPRessEffectProvider) { super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager, splitShadeStateController, - vibratorHelper); + longPRessEffectProvider); mTunerService = tunerService; mQsCustomizerController = qsCustomizerController; mQsTileRevealControllerFactory = qsTileRevealControllerFactory; @@ -112,7 +112,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mLastDensity = view.getResources().getConfiguration().densityDpi; - mSceneContainerEnabled = sceneContainerFlags.isEnabled(); + mSceneContainerEnabled = SceneContainerFlag.isEnabled(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java index d8e81875bbbf..583cfb9ab47e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java @@ -17,6 +17,7 @@ package com.android.systemui.qs; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import static com.android.systemui.Flags.quickSettingsVisualHapticsLongpress; import android.annotation.NonNull; import android.annotation.Nullable; @@ -32,6 +33,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dumpable; import com.android.systemui.dump.DumpManager; +import com.android.systemui.haptics.qs.QSLongPressEffect; import com.android.systemui.media.controls.ui.view.MediaHost; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTileView; @@ -39,7 +41,6 @@ import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileViewImpl; -import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.util.ViewController; import com.android.systemui.util.animation.DisappearParameters; @@ -55,6 +56,8 @@ import java.util.Objects; import java.util.function.Consumer; import java.util.stream.Collectors; +import javax.inject.Provider; + /** * Controller for QSPanel views. * @@ -88,7 +91,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr private SplitShadeStateController mSplitShadeStateController; - private final VibratorHelper mVibratorHelper; + private final Provider<QSLongPressEffect> mLongPressEffectProvider; @VisibleForTesting protected final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener = @@ -148,7 +151,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr QSLogger qsLogger, DumpManager dumpManager, SplitShadeStateController splitShadeStateController, - VibratorHelper vibratorHelper + Provider<QSLongPressEffect> longPressEffectProvider ) { super(view); mHost = host; @@ -162,7 +165,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr mSplitShadeStateController = splitShadeStateController; mShouldUseSplitNotificationShade = mSplitShadeStateController.shouldUseSplitNotificationShade(getResources()); - mVibratorHelper = vibratorHelper; + mLongPressEffectProvider = longPressEffectProvider; } @Override @@ -305,8 +308,14 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr } private void addTile(final QSTile tile, boolean collapsedView) { + QSLongPressEffect longPressEffect; + if (quickSettingsVisualHapticsLongpress()) { + longPressEffect = mLongPressEffectProvider.get(); + } else { + longPressEffect = null; + } final QSTileViewImpl tileView = new QSTileViewImpl( - getContext(), collapsedView, mVibratorHelper); + getContext(), collapsedView, longPressEffect); final TileRecord r = new TileRecord(tile, tileView); // TODO(b/250618218): Remove the QSLogger in QSTileViewImpl once we know the root cause of // b/250618218. diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index 05bb08813cc5..6cda740dd1a8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -25,6 +25,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.systemui.dump.DumpManager; +import com.android.systemui.haptics.qs.QSLongPressEffect; import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager; import com.android.systemui.media.controls.ui.view.MediaHost; import com.android.systemui.plugins.qs.QSTile; @@ -32,7 +33,6 @@ import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.res.R; -import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.util.leak.RotationUtils; @@ -58,10 +58,11 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> Provider<Boolean> usingCollapsedLandscapeMediaProvider, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, SplitShadeStateController splitShadeStateController, - VibratorHelper vibratorHelper + Provider<QSLongPressEffect> longPressEffectProvider ) { super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, - uiEventLogger, qsLogger, dumpManager, splitShadeStateController, vibratorHelper); + uiEventLogger, qsLogger, dumpManager, splitShadeStateController, + longPressEffectProvider); mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index 1d92d782be69..bb40d3e69dc1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -17,7 +17,7 @@ package com.android.systemui.qs; import com.android.systemui.qs.dagger.QSScope; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.util.ViewController; import javax.inject.Inject; @@ -34,12 +34,11 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Inject QuickStatusBarHeaderController(QuickStatusBarHeader view, - QuickQSPanelController quickQSPanelController, - SceneContainerFlags sceneContainerFlags + QuickQSPanelController quickQSPanelController ) { super(view); mQuickQSPanelController = quickQSPanelController; - mSceneContainerEnabled = sceneContainerFlags.isEnabled(); + mSceneContainerEnabled = SceneContainerFlag.isEnabled(); } @Override protected void onViewAttached() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java index a01d65896592..10c8e530553a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,124 +16,21 @@ package com.android.systemui.qs; -import android.content.Context; -import android.database.ContentObserver; -import android.hardware.display.ColorDisplayManager; -import android.net.Uri; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.provider.Settings; - -import androidx.annotation.NonNull; - -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Background; -import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.policy.CallbackController; -import com.android.systemui.util.settings.SecureSettings; - -import java.util.ArrayList; -import javax.inject.Inject; - -/** - * @hide - */ -@SysUISingleton -public class ReduceBrightColorsController implements +public interface ReduceBrightColorsController extends CallbackController<ReduceBrightColorsController.Listener> { - private final ColorDisplayManager mManager; - private final UserTracker mUserTracker; - private UserTracker.Callback mCurrentUserTrackerCallback; - private final Handler mHandler; - private final ContentObserver mContentObserver; - private final SecureSettings mSecureSettings; - private final ArrayList<ReduceBrightColorsController.Listener> mListeners = new ArrayList<>(); - - @Inject - public ReduceBrightColorsController(UserTracker userTracker, - @Background Handler handler, - ColorDisplayManager colorDisplayManager, - SecureSettings secureSettings) { - mManager = colorDisplayManager; - mUserTracker = userTracker; - mHandler = handler; - mSecureSettings = secureSettings; - mContentObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - final String setting = uri == null ? null : uri.getLastPathSegment(); - synchronized (mListeners) { - if (setting != null && mListeners.size() != 0) { - if (setting.equals(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED)) { - dispatchOnActivated(mManager.isReduceBrightColorsActivated()); - } - } - } - } - }; - - mCurrentUserTrackerCallback = new UserTracker.Callback() { - @Override - public void onUserChanged(int newUser, Context userContext) { - synchronized (mListeners) { - if (mListeners.size() > 0) { - mSecureSettings.unregisterContentObserver(mContentObserver); - mSecureSettings.registerContentObserverForUser( - Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, - false, mContentObserver, newUser); - } - } - } - }; - mUserTracker.addCallback(mCurrentUserTrackerCallback, new HandlerExecutor(handler)); - } - - @Override - public void addCallback(@NonNull Listener listener) { - synchronized (mListeners) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - if (mListeners.size() == 1) { - mSecureSettings.registerContentObserverForUser( - Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, - false, mContentObserver, mUserTracker.getUserId()); - } - } - } - } - - @Override - public void removeCallback(@androidx.annotation.NonNull Listener listener) { - synchronized (mListeners) { - if (mListeners.remove(listener) && mListeners.size() == 0) { - mSecureSettings.unregisterContentObserver(mContentObserver); - } - } - } /** Returns {@code true} if Reduce Bright Colors is activated */ - public boolean isReduceBrightColorsActivated() { - return mManager.isReduceBrightColorsActivated(); - } + boolean isReduceBrightColorsActivated(); /** Sets the activation state of Reduce Bright Colors */ - public void setReduceBrightColorsActivated(boolean activated) { - mManager.setReduceBrightColorsActivated(activated); - } - - private void dispatchOnActivated(boolean activated) { - ArrayList<Listener> copy = new ArrayList<>(mListeners); - for (Listener l : copy) { - l.onActivated(activated); - } - } + void setReduceBrightColorsActivated(boolean activated); /** * Listener invoked whenever the Reduce Bright Colors settings are changed. */ - public interface Listener { + interface Listener { /** * Listener invoked when the activated state changes. * @@ -142,4 +39,4 @@ public class ReduceBrightColorsController implements default void onActivated(boolean activated) { } } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsControllerImpl.java new file mode 100644 index 000000000000..4fc660948926 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsControllerImpl.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @hide + */ +package com.android.systemui.qs; + +import android.content.Context; +import android.database.ContentObserver; +import android.hardware.display.ColorDisplayManager; +import android.net.Uri; +import android.os.Handler; +import android.os.HandlerExecutor; +import android.provider.Settings; + +import androidx.annotation.NonNull; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.util.settings.SecureSettings; + +import java.util.ArrayList; + +import javax.inject.Inject; + +@SysUISingleton +public class ReduceBrightColorsControllerImpl implements + ReduceBrightColorsController { + private final ColorDisplayManager mManager; + private final UserTracker mUserTracker; + private UserTracker.Callback mCurrentUserTrackerCallback; + private final Handler mHandler; + private final ContentObserver mContentObserver; + private final SecureSettings mSecureSettings; + private final ArrayList<ReduceBrightColorsController.Listener> mListeners = new ArrayList<>(); + + @Inject + public ReduceBrightColorsControllerImpl(UserTracker userTracker, + @Background Handler handler, + ColorDisplayManager colorDisplayManager, + SecureSettings secureSettings) { + mManager = colorDisplayManager; + mUserTracker = userTracker; + mHandler = handler; + mSecureSettings = secureSettings; + mContentObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + final String setting = uri == null ? null : uri.getLastPathSegment(); + synchronized (mListeners) { + if (setting != null && mListeners.size() != 0) { + if (setting.equals(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED)) { + dispatchOnActivated(mManager.isReduceBrightColorsActivated()); + } + } + } + } + }; + + mCurrentUserTrackerCallback = new UserTracker.Callback() { + @Override + public void onUserChanged(int newUser, Context userContext) { + synchronized (mListeners) { + if (mListeners.size() > 0) { + mSecureSettings.unregisterContentObserver(mContentObserver); + mSecureSettings.registerContentObserverForUser( + Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, + false, mContentObserver, newUser); + } + } + } + }; + mUserTracker.addCallback(mCurrentUserTrackerCallback, new HandlerExecutor(handler)); + } + + @Override + public void addCallback(@NonNull Listener listener) { + synchronized (mListeners) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + if (mListeners.size() == 1) { + mSecureSettings.registerContentObserverForUser( + Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, + false, mContentObserver, mUserTracker.getUserId()); + } + } + } + } + + @Override + public void removeCallback(@androidx.annotation.NonNull Listener listener) { + synchronized (mListeners) { + if (mListeners.remove(listener) && mListeners.size() == 0) { + mSecureSettings.unregisterContentObserver(mContentObserver); + } + } + } + + @Override + public boolean isReduceBrightColorsActivated() { + return mManager.isReduceBrightColorsActivated(); + } + + @Override + public void setReduceBrightColorsActivated(boolean activated) { + mManager.setReduceBrightColorsActivated(activated); + } + + private void dispatchOnActivated(boolean activated) { + ArrayList<Listener> copy = new ArrayList<>(mListeners); + for (Listener l : copy) { + l.onActivated(activated); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java index 34b1b2d0657a..a222b3cbd08c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java @@ -42,7 +42,7 @@ import com.android.systemui.qs.QSEditEvent; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; @@ -107,8 +107,7 @@ public class QSCustomizerController extends ViewController<QSCustomizer> { protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper, QSHost qsHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle, KeyguardStateController keyguardStateController, LightBarController lightBarController, - ConfigurationController configurationController, UiEventLogger uiEventLogger, - SceneContainerFlags sceneContainerFlags) { + ConfigurationController configurationController, UiEventLogger uiEventLogger) { super(view); mTileQueryHelper = tileQueryHelper; mQsHost = qsHost; @@ -118,7 +117,7 @@ public class QSCustomizerController extends ViewController<QSCustomizer> { mLightBarController = lightBarController; mConfigurationController = configurationController; mUiEventLogger = uiEventLogger; - view.setSceneContainerEnabled(sceneContainerFlags.isEnabled()); + view.setSceneContainerEnabled(SceneContainerFlag.isEnabled()); mToolbar = mView.findViewById(com.android.internal.R.id.action_bar); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java index 8d3500a4f9f0..b705a0389300 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java @@ -28,6 +28,7 @@ import com.android.systemui.media.dagger.MediaModule; import com.android.systemui.qs.AutoAddTracker; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.ReduceBrightColorsController; +import com.android.systemui.qs.ReduceBrightColorsControllerImpl; import com.android.systemui.qs.external.QSExternalModule; import com.android.systemui.qs.panels.dagger.PanelsModule; import com.android.systemui.qs.pipeline.dagger.QSPipelineModule; @@ -118,4 +119,11 @@ public interface QSModule { @Binds QSSceneAdapter bindsQsSceneInteractor(QSSceneAdapterImpl impl); + + /** + * Dims the screen + */ + @Binds + ReduceBrightColorsController bindReduceBrightColorsController( + ReduceBrightColorsControllerImpl impl); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt index 267e2b7d0609..9c1b85799648 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt @@ -16,6 +16,7 @@ package com.android.systemui.qs.pipeline.domain.autoaddable +import android.view.accessibility.Flags import com.android.systemui.dagger.SysUISingleton import com.android.systemui.qs.ReduceBrightColorsController import com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE @@ -58,7 +59,9 @@ constructor( override val autoAddTracking get() = - if (available) { + if (Flags.a11yQsShortcut()) { + AutoAddTracking.Disabled + } else if (available) { super.autoAddTracking } else { AutoAddTracking.Disabled diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 30044856a7d4..ca71870845e0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -62,15 +62,15 @@ import com.android.systemui.plugins.qs.QSTileView import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH import com.android.systemui.res.R -import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.children +import kotlinx.coroutines.DisposableHandle import java.util.Objects private const val TAG = "QSTileViewImpl" open class QSTileViewImpl @JvmOverloads constructor( context: Context, private val collapsed: Boolean = false, - private val vibratorHelper: VibratorHelper? = null, + private val longPressEffect: QSLongPressEffect? = null, ) : QSTileView(context), HeightOverrideable, LaunchableView { companion object { @@ -180,15 +180,13 @@ open class QSTileViewImpl @JvmOverloads constructor( private val locInScreen = IntArray(2) /** Visuo-haptic long-press effects */ - private var longPressEffect: QSLongPressEffect? = null - private val longPressEffectViewBinder = QSLongPressEffectViewBinder() private var initialLongPressProperties: QSLongPressProperties? = null private var finalLongPressProperties: QSLongPressProperties? = null private val colorEvaluator = ArgbEvaluator.getInstance() - val hasLongPressEffect: Boolean - get() = longPressEffect != null - @VisibleForTesting val isLongPressEffectBound: Boolean - get() = longPressEffectViewBinder.isBound + val isLongPressEffectInitialized: Boolean + get() = longPressEffect?.hasInitialized == true + @VisibleForTesting + var longPressEffectHandle: DisposableHandle? = null init { val typedValue = TypedValue() @@ -325,6 +323,13 @@ open class QSTileViewImpl @JvmOverloads constructor( } private fun updateHeight() { + // TODO(b/332900989): Find a more robust way of resetting the tile if not reset by the + // launch animation. + if (scaleX != 1f || scaleY != 1f) { + // The launch animation of a long-press effect did not reset the long-press effect so + // we must do it here + resetLongPressEffectProperties() + } val actualHeight = if (heightOverride != HeightOverrideable.NO_OVERRIDE) { heightOverride } else { @@ -614,25 +619,26 @@ open class QSTileViewImpl @JvmOverloads constructor( lastIconTint = icon.getColor(state) // Long-press effects - if (quickSettingsVisualHapticsLongpress()){ - if (state.handlesLongClick && maybeCreateAndInitializeLongPressEffect()) { - // set the valid long-press effect as the touch listener - showRippleEffect = false + if (state.handlesLongClick && + longPressEffect?.initializeEffect(longPressEffectDuration) == true) { + // set the valid long-press effect as the touch listener + if (longPressEffectHandle == null) { + longPressEffectHandle = + QSLongPressEffectViewBinder.bind(this, longPressEffect, state.spec) setOnTouchListener(longPressEffect) - if (!longPressEffectViewBinder.isBound) { - longPressEffectViewBinder.bind(this, state.spec, longPressEffect) - } - } else { - // Long-press effects might have been enabled before but the new state does not - // handle a long-press. In this case, we go back to the behaviour of a regular tile - // and clean-up the resources - longPressEffectViewBinder.dispose() - showRippleEffect = isClickable - setOnTouchListener(null) - longPressEffect = null - initialLongPressProperties = null - finalLongPressProperties = null } + showRippleEffect = false + initializeLongPressProperties() + } else { + // Long-press effects might have been enabled before but the new state does not + // handle a long-press. In this case, we go back to the behaviour of a regular tile + // and clean-up the resources + setOnTouchListener(null) + longPressEffectHandle?.dispose() + longPressEffectHandle = null + showRippleEffect = isClickable + initialLongPressProperties = null + finalLongPressProperties = null } } @@ -824,7 +830,7 @@ open class QSTileViewImpl @JvmOverloads constructor( private fun interpolateFloat(fraction: Float, start: Float, end: Float): Float = start + fraction * (end - start) - private fun resetLongPressEffectProperties() { + fun resetLongPressEffectProperties() { scaleY = 1f scaleX = 1f for (child in children) { @@ -842,27 +848,6 @@ open class QSTileViewImpl @JvmOverloads constructor( icon.setTint(icon.mIcon as ImageView, lastIconTint) } - private fun maybeCreateAndInitializeLongPressEffect(): Boolean { - // Don't setup the effect if the long-press duration is invalid - val effectDuration = longPressEffectDuration - if (effectDuration <= 0) { - longPressEffect = null - return false - } - - initializeLongPressProperties() - if (longPressEffect == null) { - longPressEffect = - QSLongPressEffect( - vibratorHelper, - effectDuration, - ) - } else { - longPressEffect?.resetWithDuration(effectDuration) - } - return true - } - private fun initializeLongPressProperties() { initialLongPressProperties = QSLongPressProperties( diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt index 6c9a8a4f3a3e..5122e1feabfc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt @@ -28,6 +28,7 @@ import com.android.systemui.qs.tiles.impl.custom.domain.entity.CustomTileDataMod import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel import com.android.systemui.qs.tiles.viewmodel.QSTileViewModelAdapter +import com.android.systemui.qs.tiles.viewmodel.StubQSTileViewModel import javax.inject.Inject import javax.inject.Provider @@ -57,7 +58,9 @@ constructor( val viewModel: QSTileViewModel = when (val spec = TileSpec.create(tileSpec)) { is TileSpec.CustomTileSpec -> createCustomTileViewModel(spec) - is TileSpec.PlatformTileSpec -> tileMap[tileSpec]?.get() + // when using the stub, we default to old tile rather than adding the stub + is TileSpec.PlatformTileSpec -> + tileMap[tileSpec]?.get()?.takeIf { it !is StubQSTileViewModel } is TileSpec.Invalid -> null } ?: return null diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractor.kt new file mode 100644 index 000000000000..98fd561b27d6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractor.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor + +import android.os.UserHandle +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.qs.ReduceBrightColorsController +import com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE +import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger +import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.android.systemui.util.kotlin.isEnabled +import javax.inject.Inject +import javax.inject.Named +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map + +/** Observes reduce bright colors state changes providing the [ReduceBrightColorsTileModel]. */ +class ReduceBrightColorsTileDataInteractor +@Inject +constructor( + @Background private val bgCoroutineContext: CoroutineContext, + @Named(RBC_AVAILABLE) private val isAvailable: Boolean, + private val reduceBrightColorsController: ReduceBrightColorsController, +) : QSTileDataInteractor<ReduceBrightColorsTileModel> { + + override fun tileData( + user: UserHandle, + triggers: Flow<DataUpdateTrigger> + ): Flow<ReduceBrightColorsTileModel> { + return reduceBrightColorsController + .isEnabled() + .distinctUntilChanged() + .map { ReduceBrightColorsTileModel(it) } + .flowOn(bgCoroutineContext) + } + override fun availability(user: UserHandle): Flow<Boolean> = flowOf(isAvailable) +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt new file mode 100644 index 000000000000..762f8635c562 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor + +import android.content.Intent +import android.provider.Settings +import com.android.systemui.qs.ReduceBrightColorsController +import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler +import com.android.systemui.qs.tiles.base.interactor.QSTileInput +import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction +import javax.inject.Inject + +/** Handles reduce bright colors tile clicks. */ +class ReduceBrightColorsTileUserActionInteractor +@Inject +constructor( + private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler, + private val reduceBrightColorsController: ReduceBrightColorsController, +) : QSTileUserActionInteractor<ReduceBrightColorsTileModel> { + + override suspend fun handleInput(input: QSTileInput<ReduceBrightColorsTileModel>): Unit = + with(input) { + when (action) { + is QSTileUserAction.Click -> { + reduceBrightColorsController.setReduceBrightColorsActivated( + !input.data.isEnabled + ) + } + is QSTileUserAction.LongClick -> { + qsTileIntentUserActionHandler.handle( + action.view, + Intent(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS) + ) + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/model/ReduceBrightColorsTileModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/model/ReduceBrightColorsTileModel.kt new file mode 100644 index 000000000000..05e0f5d202da --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/model/ReduceBrightColorsTileModel.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.domain.model + +/** + * Reduce bright colors tile model. + * + * @param isEnabled is true when the reduce bright colors is enabled; + */ +@JvmInline value class ReduceBrightColorsTileModel(val isEnabled: Boolean) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt new file mode 100644 index 000000000000..fca93dfe47da --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness.ui + +import android.content.res.Resources +import android.service.quicksettings.Tile +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper +import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel +import com.android.systemui.qs.tiles.viewmodel.QSTileConfig +import com.android.systemui.qs.tiles.viewmodel.QSTileState +import com.android.systemui.res.R +import javax.inject.Inject + +/** Maps [ReduceBrightColorsTileModel] to [QSTileState]. */ +class ReduceBrightColorsTileMapper +@Inject +constructor( + @Main private val resources: Resources, + private val theme: Resources.Theme, +) : QSTileDataToStateMapper<ReduceBrightColorsTileModel> { + + override fun map(config: QSTileConfig, data: ReduceBrightColorsTileModel): QSTileState = + QSTileState.build(resources, theme, config.uiConfig) { + if (data.isEnabled) { + activationState = QSTileState.ActivationState.ACTIVE + icon = { + Icon.Loaded( + drawable = resources.getDrawable(R.drawable.qs_extra_dim_icon_on, theme), + contentDescription = null + ) + } + + secondaryLabel = + resources + .getStringArray(R.array.tile_states_reduce_brightness)[Tile.STATE_ACTIVE] + } else { + activationState = QSTileState.ActivationState.INACTIVE + icon = { + Icon.Loaded( + drawable = resources.getDrawable(R.drawable.qs_extra_dim_icon_off, theme), + contentDescription = null + ) + } + secondaryLabel = + resources + .getStringArray(R.array.tile_states_reduce_brightness)[Tile.STATE_INACTIVE] + } + label = + resources.getString(com.android.internal.R.string.reduce_bright_colors_feature_name) + contentDescription = label + supportedActions = + setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/StubQSTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/StubQSTileViewModel.kt new file mode 100644 index 000000000000..64f1fd3d6416 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/StubQSTileViewModel.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.viewmodel + +import android.os.UserHandle +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow + +object StubQSTileViewModel : QSTileViewModel { + + override val state: SharedFlow<QSTileState> + get() = error("Don't call stubs") + + override val config: QSTileConfig + get() = error("Don't call stubs") + + override val isAvailable: StateFlow<Boolean> + get() = error("Don't call stubs") + + override fun onUserChanged(user: UserHandle) = error("Don't call stubs") + + override fun forceUpdate() = error("Don't call stubs") + + override fun onActionPerformed(userAction: QSTileUserAction) = error("Don't call stubs") + + override fun destroy() = error("Don't call stubs") +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt index 4e0b5762b6cf..ab0b0b7b7c6c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt @@ -52,8 +52,6 @@ constructor( val destinationScenes = qsSceneAdapter.isCustomizing.flatMapLatest { customizing -> if (customizing) { - // TODO(b/332749288) Empty map so there are no back handlers and back can close - // customizer flowOf(emptyMap()) // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade // while customizing diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 4ece7b6c8990..1ddc0946905c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -98,7 +98,7 @@ import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.navigationbar.buttons.KeyButtonView; import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; import com.android.systemui.scene.domain.interactor.SceneInteractor; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.scene.shared.model.Scenes; import com.android.systemui.settings.DisplayTracker; import com.android.systemui.settings.UserTracker; @@ -146,7 +146,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000; private final Context mContext; - private final SceneContainerFlags mSceneContainerFlags; private final Executor mMainExecutor; private final ShellInterface mShellInterface; private final Lazy<ShadeViewController> mShadeViewControllerLazy; @@ -208,7 +207,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis @Override public void onStatusBarTouchEvent(MotionEvent event) { verifyCallerAndClearCallingIdentity("onStatusBarTouchEvent", () -> { - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { //TODO(b/329863123) implement latency tracking for shade scene Log.i(TAG_OPS, "Scene container enabled. Latency tracking not started."); } else if (event.getActionMasked() == ACTION_DOWN) { @@ -223,7 +222,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis // If scene framework is enabled, set the scene container window to // visible and let the touch "slip" into that window. - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { mSceneInteractor.get().onRemoteUserInteractionStarted("launcher swipe"); } else { mShadeViewControllerLazy.get().startInputFocusTransfer(); @@ -232,7 +231,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis if (action == ACTION_UP || action == ACTION_CANCEL) { mInputFocusTransferStarted = false; - if (!mSceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled()) { float velocity = (event.getY() - mInputFocusTransferStartY) / (event.getEventTime() - mInputFocusTransferStartMillis); if (action == ACTION_CANCEL) { @@ -612,7 +611,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis KeyguardUnlockAnimationController sysuiUnlockAnimationController, InWindowLauncherUnlockAnimationManager inWindowLauncherUnlockAnimationManager, AssistUtils assistUtils, - SceneContainerFlags sceneContainerFlags, DumpManager dumpManager, Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder, BroadcastDispatcher broadcastDispatcher @@ -624,7 +622,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } mContext = context; - mSceneContainerFlags = sceneContainerFlags; mMainExecutor = mainExecutor; mShellInterface = shellInterface; mShadeViewControllerLazy = shadeViewControllerLazy; diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt index afd0746f4696..8277c73025d8 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt @@ -16,7 +16,6 @@ package com.android.systemui.scene -import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.Scenes import dagger.Module @@ -29,7 +28,6 @@ import dagger.Provides EmptySceneModule::class, GoneSceneModule::class, QuickSettingsSceneModule::class, - SceneContainerFlagsModule::class, ShadeSceneModule::class, ], ) diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt index 62b0914fab79..69f9443b334b 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt @@ -20,7 +20,6 @@ import com.android.systemui.CoreStartable import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlagsModule import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor import com.android.systemui.scene.domain.startable.SceneContainerStartable -import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.Scenes import dagger.Binds @@ -40,7 +39,6 @@ import dagger.multibindings.IntoMap GoneSceneModule::class, LockscreenSceneModule::class, QuickSettingsSceneModule::class, - SceneContainerFlagsModule::class, ShadeSceneModule::class, ], ) diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt index 0665c9e1b802..d202c24ae152 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt @@ -16,7 +16,6 @@ package com.android.systemui.scene -import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.Scenes import dagger.Module @@ -30,7 +29,6 @@ import dagger.Provides EmptySceneModule::class, GoneSceneModule::class, LockscreenSceneModule::class, - SceneContainerFlagsModule::class, ], ) object ShadelessSceneContainerFrameworkModule { diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt index c736707ecd2d..1cf1c18749cb 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt @@ -24,7 +24,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.statusbar.NotificationPresenter import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor @@ -53,7 +53,6 @@ constructor( private val headsUpManager: HeadsUpManager, private val powerInteractor: PowerInteractor, private val activeNotificationsInteractor: ActiveNotificationsInteractor, - sceneContainerFlags: SceneContainerFlags, sceneInteractorProvider: Provider<SceneInteractor>, ) : CoreStartable { @@ -68,7 +67,7 @@ constructor( * false if the bouncer is visible. */ val isLockscreenOrShadeVisible: StateFlow<Boolean> = - if (!sceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled) { windowRootViewVisibilityRepository.isLockscreenOrShadeVisible } else { sceneInteractorProvider diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index 32d72e0bac22..4774eb32a445 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -44,9 +44,10 @@ import com.android.systemui.plugins.FalsingManager.FalsingBeliefListener import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.logger.SceneLogger import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor import com.android.systemui.statusbar.phone.CentralSurfaces @@ -61,6 +62,7 @@ import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged @@ -68,10 +70,12 @@ import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** @@ -88,7 +92,6 @@ constructor( private val deviceUnlockedInteractor: DeviceUnlockedInteractor, private val bouncerInteractor: BouncerInteractor, private val keyguardInteractor: KeyguardInteractor, - private val flags: SceneContainerFlags, private val sysUiState: SysUiState, @DisplayId private val displayId: Int, private val sceneLogger: SceneLogger, @@ -103,10 +106,11 @@ constructor( private val headsUpInteractor: HeadsUpNotificationInteractor, private val occlusionInteractor: SceneContainerOcclusionInteractor, private val faceUnlockInteractor: DeviceEntryFaceAuthInteractor, + private val shadeInteractor: ShadeInteractor, ) : CoreStartable { override fun start() { - if (flags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { sceneLogger.logFrameworkEnabled(isEnabled = true) hydrateVisibility() automaticallySwitchScenes() @@ -119,16 +123,18 @@ constructor( } else { sceneLogger.logFrameworkEnabled( isEnabled = false, - reason = flags.requirementDescription(), + reason = SceneContainerFlag.requirementDescription(), ) } } override fun dump(pw: PrintWriter, args: Array<out String>) = pw.asIndenting().run { - printSection("SceneContainerFlags") { - println("isEnabled", flags.isEnabled()) - printSection("requirementDescription") { println(flags.requirementDescription()) } + printSection("SceneContainerFlag") { + println("isEnabled", SceneContainerFlag.isEnabled) + printSection("requirementDescription") { + println(SceneContainerFlag.requirementDescription()) + } } } @@ -185,6 +191,14 @@ constructor( /** Switches between scenes based on ever-changing application state. */ private fun automaticallySwitchScenes() { + handleBouncerImeVisibility() + handleSimUnlock() + handleDeviceUnlockStatus() + handlePowerState() + handleShadeTouchability() + } + + private fun handleBouncerImeVisibility() { applicationScope.launch { // TODO (b/308001302): Move this to a bouncer specific interactor. bouncerInteractor.onImeHiddenByUser.collectLatest { @@ -196,6 +210,9 @@ constructor( } } } + } + + private fun handleSimUnlock() { applicationScope.launch { simBouncerInteractor .get() @@ -229,7 +246,16 @@ constructor( } } } + } + + private fun handleDeviceUnlockStatus() { applicationScope.launch { + // Track the previous scene (sans Bouncer), so that we know where to go when the device + // is unlocked whilst on the bouncer. + val previousScene = + sceneInteractor.previousScene + .filterNot { it == Scenes.Bouncer } + .stateIn(this, SharingStarted.Eagerly, initialValue = null) deviceUnlockedInteractor.deviceUnlockStatus .mapNotNull { deviceUnlockStatus -> val renderedScenes = @@ -257,8 +283,16 @@ constructor( when { isOnBouncer -> - // When the device becomes unlocked in Bouncer, go to Gone. - Scenes.Gone to "device was unlocked in Bouncer scene" + // When the device becomes unlocked in Bouncer, go to previous scene, + // or Gone. + if (previousScene.value == Scenes.Lockscreen) { + Scenes.Gone to "device was unlocked in Bouncer scene" + } else { + val prevScene = previousScene.value + (prevScene + ?: Scenes.Gone) to + "device was unlocked in Bouncer scene, from sceneKey=$prevScene" + } isOnLockscreen -> // The lockscreen should be dismissed automatically in 2 scenarios: // 1. When face auth bypass is enabled and authentication happens while @@ -288,7 +322,9 @@ constructor( ) } } + } + private fun handlePowerState() { applicationScope.launch { powerInteractor.isAsleep.collect { isAsleep -> if (isAsleep) { @@ -317,7 +353,7 @@ constructor( ) { switchToScene( targetSceneKey = Scenes.Bouncer, - loggingReason = "device is starting to wake up with a locked sim" + loggingReason = "device is starting to wake up with a locked sim", ) } } @@ -325,6 +361,20 @@ constructor( } } + private fun handleShadeTouchability() { + applicationScope.launch { + shadeInteractor.isShadeTouchable + .distinctUntilChanged() + .filter { !it } + .collect { + switchToScene( + targetSceneKey = Scenes.Lockscreen, + loggingReason = "device became non-interactive", + ) + } + } + } + /** Keeps [SysUiState] up-to-date */ private fun hydrateSystemUiState() { applicationScope.launch { diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt index c9291966bc15..234eda8c0988 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt @@ -20,18 +20,17 @@ package com.android.systemui.scene.shared.flag import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.Flags.sceneContainer -import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.KeyguardWmStateRefactor import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.shared.ComposeLockscreen +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent import com.android.systemui.media.controls.util.MediaInSceneContainerFlag import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag -import dagger.Module -import dagger.Provides /** Helper for reading or using the scene container flag state. */ object SceneContainerFlag { @@ -48,7 +47,9 @@ object SceneContainerFlag { MediaInSceneContainerFlag.isEnabled && MigrateClocksToBlueprint.isEnabled && NotificationsHeadsUpRefactor.isEnabled && - PredictiveBackSysUiFlag.isEnabled + PredictiveBackSysUiFlag.isEnabled && + DeviceEntryUdfpsRefactor.isEnabled && + RefactorKeyguardDismissIntent.isEnabled // NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer /** The main aconfig flag. */ @@ -64,6 +65,8 @@ object SceneContainerFlag { MigrateClocksToBlueprint.token, NotificationsHeadsUpRefactor.token, PredictiveBackSysUiFlag.token, + DeviceEntryUdfpsRefactor.token, + RefactorKeyguardDismissIntent.token, // NOTE: Changes should also be made in isEnabled and @EnableSceneContainer ) @@ -93,30 +96,12 @@ object SceneContainerFlag { */ @JvmStatic inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, DESCRIPTION) -} - -/** - * Defines interface for classes that can check whether the scene container framework feature is - * enabled. - */ -interface SceneContainerFlags { - - /** Returns `true` if the Scene Container Framework is enabled; `false` otherwise. */ - fun isEnabled(): Boolean /** Returns a developer-readable string that describes the current requirement list. */ - fun requirementDescription(): String -} - -class SceneContainerFlagsImpl : SceneContainerFlags { - - override fun isEnabled(): Boolean { - return SceneContainerFlag.isEnabled - } - - override fun requirementDescription(): String { + @JvmStatic + fun requirementDescription(): String { return buildString { - SceneContainerFlag.getAllRequirements().forEach { requirement -> + getAllRequirements().forEach { requirement -> append('\n') append(if (requirement.isEnabled) " [MET]" else "[NOT MET]") append(" ${requirement.name}") @@ -124,9 +109,3 @@ class SceneContainerFlagsImpl : SceneContainerFlags { } } } - -@Module -object SceneContainerFlagsModule { - - @Provides @SysUISingleton fun impl(): SceneContainerFlags = SceneContainerFlagsImpl() -} diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt index 67dc0cc6e03b..259a8bfef175 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt @@ -4,7 +4,6 @@ import android.content.Context import android.util.AttributeSet import android.view.View import android.view.WindowInsets -import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.Scene import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneDataSourceDelegator @@ -31,7 +30,6 @@ class SceneWindowRootView( viewModel: SceneContainerViewModel, containerConfig: SceneContainerConfig, sharedNotificationContainer: SharedNotificationContainer, - flags: SceneContainerFlags, scenes: Set<Scene>, layoutInsetController: LayoutInsetsController, sceneDataSourceDelegator: SceneDataSourceDelegator, @@ -44,7 +42,6 @@ class SceneWindowRootView( windowInsets = windowInsets, containerConfig = containerConfig, sharedNotificationContainer = sharedNotificationContainer, - flags = flags, scenes = scenes, onVisibilityChangedInternal = { isVisible -> super.setVisibility(if (isVisible) View.VISIBLE else View.INVISIBLE) diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt index 809ac2ea9f82..2ef9b731502f 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt @@ -39,7 +39,7 @@ import com.android.systemui.common.ui.compose.windowinsets.DisplayCutout import com.android.systemui.common.ui.compose.windowinsets.ScreenDecorProvider import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scene import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneDataSourceDelegator @@ -63,7 +63,6 @@ object SceneWindowRootViewBinder { windowInsets: StateFlow<WindowInsets?>, containerConfig: SceneContainerConfig, sharedNotificationContainer: SharedNotificationContainer, - flags: SceneContainerFlags, scenes: Set<Scene>, onVisibilityChangedInternal: (isVisible: Boolean) -> Unit, dataSourceDelegator: SceneDataSourceDelegator, @@ -115,7 +114,7 @@ object SceneWindowRootViewBinder { // the SceneContainerView. This SharedNotificationContainer should contain NSSL // due to the NotificationStackScrollLayoutSection (legacy) or // NotificationSection (scene container) moving it there. - if (flags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { (sharedNotificationContainer.parent as? ViewGroup)?.removeView( sharedNotificationContainer ) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java b/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java index ab8fc652c938..12bff499217e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java @@ -15,6 +15,7 @@ */ package com.android.systemui.screenshot; +import android.annotation.Nullable; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; import android.app.IAssistDataReceiver; @@ -55,7 +56,7 @@ public class AssistContentRequester { * Called when the {@link android.app.assist.AssistContent} of the requested task is * available. **/ - void onAssistContentAvailable(AssistContent assistContent); + void onAssistContentAvailable(@Nullable AssistContent assistContent); } private final IActivityTaskManager mActivityTaskManager; @@ -117,15 +118,9 @@ public class AssistContentRequester { @Override public void onHandleAssistData(Bundle data) { - if (data == null) { - return; - } - - final AssistContent content = data.getParcelable(ASSIST_KEY_CONTENT); - if (content == null) { - Log.e(TAG, "Received AssistData, but no AssistContent found"); - return; - } + final AssistContent content = (data == null) ? null + : data.getParcelable( + ASSIST_KEY_CONTENT, AssistContent.class); AssistContentRequester requester = mParentRef.get(); if (requester != null) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java index 6224e1bf2414..afb0280a3917 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java @@ -16,6 +16,7 @@ package com.android.systemui.screenshot; +import dagger.Binds; import dagger.Module; import dagger.Provides; @@ -29,4 +30,9 @@ public interface ReferenceScreenshotModule { static ScreenshotNotificationSmartActionsProvider providesScrnshtNotifSmartActionsProvider() { return new ScreenshotNotificationSmartActionsProvider(); } + + /** */ + @Binds + ScreenshotActionsProvider.Factory bindScreenshotActionsProviderFactory( + DefaultScreenshotActionsProvider.Factory defaultScreenshotActionsProviderFactory); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt index 0ccb19cd9d31..07e143a34319 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt @@ -28,7 +28,6 @@ import com.android.systemui.screenshot.ActionIntentCreator.createShareWithSubjec import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_EDIT_TAPPED import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SHARE_TAPPED -import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED import com.android.systemui.screenshot.ui.viewmodel.ActionButtonAppearance import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel import dagger.assisted.Assisted @@ -43,7 +42,11 @@ interface ScreenshotActionsProvider { fun onScrollChipReady(onClick: Runnable) fun setCompletedScreenshot(result: ScreenshotSavedResult) - fun onAssistContentAvailable(assistContent: AssistContent) {} + /** + * Provide the AssistContent for the focused task if available, null if the focused task isn't + * known or didn't return data. + */ + fun onAssistContent(assistContent: AssistContent?) {} interface Factory { fun create( @@ -59,7 +62,6 @@ class DefaultScreenshotActionsProvider constructor( private val context: Context, private val viewModel: ScreenshotViewModel, - private val smartActionsProvider: SmartActionsProvider, private val uiEventLogger: UiEventLogger, @Assisted val request: ScreenshotData, @Assisted val requestId: String, @@ -115,37 +117,6 @@ constructor( ) } } - - smartActionsProvider.requestQuickShare(request, requestId) { quickShare -> - if (!quickShare.actionIntent.isImmutable) { - viewModel.addAction( - ActionButtonAppearance( - quickShare.getIcon().loadDrawable(context), - quickShare.title, - quickShare.title - ) - ) { - debugLog(LogConfig.DEBUG_ACTIONS) { "Quickshare tapped" } - onDeferrableActionTapped { result -> - uiEventLogger.log( - SCREENSHOT_SMART_ACTION_TAPPED, - 0, - request.packageNameString - ) - val pendingIntentWithUri = - smartActionsProvider.wrapIntent( - quickShare, - result.uri, - result.subject, - requestId - ) - actionExecutor.sendPendingIntent(pendingIntentWithUri) - } - } - } else { - Log.w(TAG, "Received immutable quick share pending intent; ignoring") - } - } } override fun onScrollChipReady(onClick: Runnable) { @@ -167,21 +138,6 @@ constructor( } this.result = result pendingAction?.invoke(result) - smartActionsProvider.requestSmartActions(request, requestId, result) { smartActions -> - smartActions.forEach { - smartActions.forEach { action -> - viewModel.addAction( - ActionButtonAppearance( - action.getIcon().loadDrawable(context), - action.title, - action.title, - ) - ) { - actionExecutor.sendPendingIntent(action.actionIntent) - } - } - } - } } private fun onDeferrableActionTapped(onResult: (ScreenshotSavedResult) -> Unit) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 13dd229d8f62..6871084aa938 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -176,11 +176,12 @@ public class ScreenshotController { // These strings are used for communicating the action invoked to // ScreenshotNotificationSmartActionsProvider. - static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type"; - static final String EXTRA_ID = "android:screenshot_id"; - static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled"; - static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent"; - static final String EXTRA_ACTION_INTENT_FILLIN = "android:screenshot_action_intent_fillin"; + public static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type"; + public static final String EXTRA_ID = "android:screenshot_id"; + public static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled"; + public static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent"; + public static final String EXTRA_ACTION_INTENT_FILLIN = + "android:screenshot_action_intent_fillin"; // From WizardManagerHelper.java @@ -411,9 +412,9 @@ public class ScreenshotController { if (screenshot.getTaskId() >= 0) { mAssistContentRequester.requestAssistContent(screenshot.getTaskId(), - assistContent -> { - mActionsProvider.onAssistContentAvailable(assistContent); - }); + assistContent -> mActionsProvider.onAssistContent(assistContent)); + } else { + mActionsProvider.onAssistContent(null); } } else { saveScreenshotInWorkerThread(screenshot.getUserHandle(), finisher, diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java index 3eafbfbf37d7..23f05e0d8337 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java @@ -44,7 +44,7 @@ public class ScreenshotNotificationSmartActionsProvider { public static final String DEFAULT_ACTION_TYPE = "Smart Action"; /* Define phases of screenshot execution. */ - protected enum ScreenshotOp { + public enum ScreenshotOp { OP_UNKNOWN, RETRIEVE_SMART_ACTIONS, REQUEST_SMART_ACTIONS, @@ -52,7 +52,7 @@ public class ScreenshotNotificationSmartActionsProvider { } /* Enum to report success or failure for screenshot execution phases. */ - protected enum ScreenshotOpStatus { + public enum ScreenshotOpStatus { OP_STATUS_UNKNOWN, SUCCESS, ERROR, diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt index 6b9332b39816..254c13367ce2 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt @@ -28,6 +28,7 @@ import android.view.ScrollCaptureResponse import android.view.View import android.view.ViewTreeObserver import android.view.WindowInsets +import android.view.WindowManager import android.window.OnBackInvokedCallback import android.window.OnBackInvokedDispatcher import com.android.internal.logging.UiEventLogger @@ -53,6 +54,7 @@ class ScreenshotShelfViewProxy constructor( private val logger: UiEventLogger, private val viewModel: ScreenshotViewModel, + private val windowManager: WindowManager, @Assisted private val context: Context, @Assisted private val displayId: Int ) : ScreenshotViewProxy { @@ -79,6 +81,16 @@ constructor( addPredictiveBackListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) } setOnKeyListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) } debugLog(DEBUG_WINDOW) { "adding OnComputeInternalInsetsListener" } + view.viewTreeObserver.addOnComputeInternalInsetsListener { info -> + val touchableRegion = + view.getTouchRegion( + windowManager.currentWindowMetrics.windowInsets.getInsets( + WindowInsets.Type.systemGestures() + ) + ) + info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION) + info.touchableRegion.set(touchableRegion) + } screenshotPreview = view.screenshotPreview } @@ -194,6 +206,7 @@ constructor( } ) } + private fun setOnKeyListener(onDismissRequested: (ScreenshotEvent) -> Unit) { view.setOnKeyListener( object : View.OnKeyListener { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt deleted file mode 100644 index a895b300b900..000000000000 --- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.screenshot - -import android.app.Notification -import android.app.PendingIntent -import android.content.ClipData -import android.content.ClipDescription -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.graphics.Bitmap -import android.net.Uri -import android.os.Bundle -import android.os.Process -import android.os.SystemClock -import android.os.UserHandle -import android.provider.DeviceConfig -import android.util.Log -import com.android.internal.config.sysui.SystemUiDeviceConfigFlags -import com.android.systemui.log.DebugLogger.debugLog -import com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS -import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.QUICK_SHARE_ACTION -import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.REGULAR_SMART_ACTIONS -import java.util.concurrent.CompletableFuture -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException -import javax.inject.Inject -import kotlin.random.Random - -/** - * Handle requesting smart/quickshare actions from the provider and executing an action when the - * action futures complete. - */ -class SmartActionsProvider -@Inject -constructor( - private val context: Context, - private val smartActions: ScreenshotNotificationSmartActionsProvider, -) { - /** - * Requests quick share action for a given screenshot. - * - * @param data the ScreenshotData request - * @param id the request id for the screenshot - * @param onAction callback to run when quick share action is returned - */ - fun requestQuickShare( - data: ScreenshotData, - id: String, - onAction: (Notification.Action) -> Unit - ) { - val bitmap = data.bitmap ?: return - val component = data.topComponent ?: ComponentName("", "") - requestQuickShareAction(id, bitmap, component, data.getUserOrDefault()) { quickShare -> - onAction(quickShare) - } - } - - /** - * Requests smart actions for a given screenshot. - * - * @param data the ScreenshotData request - * @param id the request id for the screenshot - * @param result the data for the saved image - * @param onActions callback to run when actions are returned - */ - fun requestSmartActions( - data: ScreenshotData, - id: String, - result: ScreenshotSavedResult, - onActions: (List<Notification.Action>) -> Unit - ) { - val bitmap = data.bitmap ?: return - val component = data.topComponent ?: ComponentName("", "") - requestSmartActions( - id, - bitmap, - component, - data.getUserOrDefault(), - result.uri, - REGULAR_SMART_ACTIONS - ) { actions -> - onActions(actions) - } - } - - /** - * Wraps the given quick share action in a broadcast intent. - * - * @param quickShare the quick share action to wrap - * @param uri the URI of the saved screenshot - * @param subject the subject/title for the screenshot - * @param id the request ID of the screenshot - * @return the pending intent with correct URI - */ - fun wrapIntent( - quickShare: Notification.Action, - uri: Uri, - subject: String, - id: String - ): PendingIntent { - val wrappedIntent: Intent = - Intent(context, SmartActionsReceiver::class.java) - .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, quickShare.actionIntent) - .putExtra( - ScreenshotController.EXTRA_ACTION_INTENT_FILLIN, - createFillInIntent(uri, subject) - ) - .addFlags(Intent.FLAG_RECEIVER_FOREGROUND) - val extras: Bundle = quickShare.extras - val actionType = - extras.getString( - ScreenshotNotificationSmartActionsProvider.ACTION_TYPE, - ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE - ) - // We only query for quick share actions when smart actions are enabled, so we can assert - // that it's true here. - wrappedIntent - .putExtra(ScreenshotController.EXTRA_ACTION_TYPE, actionType) - .putExtra(ScreenshotController.EXTRA_ID, id) - .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, true) - return PendingIntent.getBroadcast( - context, - Random.nextInt(), - wrappedIntent, - PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE - ) - } - - private fun createFillInIntent(uri: Uri, subject: String): Intent { - val fillIn = Intent() - fillIn.setType("image/png") - fillIn.putExtra(Intent.EXTRA_STREAM, uri) - fillIn.putExtra(Intent.EXTRA_SUBJECT, subject) - // Include URI in ClipData also, so that grantPermission picks it up. - // We don't use setData here because some apps interpret this as "to:". - val clipData = - ClipData(ClipDescription("content", arrayOf("image/png")), ClipData.Item(uri)) - fillIn.clipData = clipData - fillIn.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - return fillIn - } - - private fun requestQuickShareAction( - id: String, - image: Bitmap, - component: ComponentName, - user: UserHandle, - timeoutMs: Long = 500, - onAction: (Notification.Action) -> Unit - ) { - requestSmartActions(id, image, component, user, null, QUICK_SHARE_ACTION, timeoutMs) { - it.firstOrNull()?.let { action -> onAction(action) } - } - } - - private fun requestSmartActions( - id: String, - image: Bitmap, - component: ComponentName, - user: UserHandle, - uri: Uri?, - actionType: ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType, - timeoutMs: Long = 500, - onActions: (List<Notification.Action>) -> Unit - ) { - val enabled = isSmartActionsEnabled(user) - debugLog(DEBUG_ACTIONS) { - ("getSmartActionsFuture id=$id, uri=$uri, provider=$smartActions, " + - "actionType=$actionType, smartActionsEnabled=$enabled, userHandle=$user") - } - if (!enabled) { - debugLog(DEBUG_ACTIONS) { "Screenshot Intelligence not enabled, returning empty list" } - onActions(listOf()) - return - } - if (image.config != Bitmap.Config.HARDWARE) { - debugLog(DEBUG_ACTIONS) { - "Bitmap expected: Hardware, Bitmap found: ${image.config}. Returning empty list." - } - onActions(listOf()) - return - } - val smartActionsFuture: CompletableFuture<List<Notification.Action>> - val startTimeMs = SystemClock.uptimeMillis() - try { - smartActionsFuture = - smartActions.getActions(id, uri, image, component, actionType, user) - } catch (e: Throwable) { - val waitTimeMs = SystemClock.uptimeMillis() - startTimeMs - debugLog(DEBUG_ACTIONS, error = e) { - "Failed to get future for screenshot notification smart actions." - } - notifyScreenshotOp( - id, - ScreenshotNotificationSmartActionsProvider.ScreenshotOp.REQUEST_SMART_ACTIONS, - ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR, - waitTimeMs - ) - onActions(listOf()) - return - } - try { - val actions = smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS) - val waitTimeMs = SystemClock.uptimeMillis() - startTimeMs - debugLog(DEBUG_ACTIONS) { - ("Got ${actions.size} smart actions. Wait time: $waitTimeMs ms, " + - "actionType=$actionType") - } - notifyScreenshotOp( - id, - ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS, - ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS, - waitTimeMs - ) - onActions(actions) - } catch (e: Throwable) { - val waitTimeMs = SystemClock.uptimeMillis() - startTimeMs - debugLog(DEBUG_ACTIONS, error = e) { - "Error getting smart actions. Wait time: $waitTimeMs ms, actionType=$actionType" - } - val status = - if (e is TimeoutException) { - ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT - } else { - ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR - } - notifyScreenshotOp( - id, - ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS, - status, - waitTimeMs - ) - onActions(listOf()) - } - } - - private fun notifyScreenshotOp( - screenshotId: String, - op: ScreenshotNotificationSmartActionsProvider.ScreenshotOp, - status: ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus, - durationMs: Long - ) { - debugLog(DEBUG_ACTIONS) { - "$smartActions notifyOp: $op id=$screenshotId, status=$status, durationMs=$durationMs" - } - try { - smartActions.notifyOp(screenshotId, op, status, durationMs) - } catch (e: Throwable) { - Log.e(TAG, "Error in notifyScreenshotOp: ", e) - } - } - - private fun isSmartActionsEnabled(user: UserHandle): Boolean { - // Smart actions don't yet work for cross-user saves. - val savingToOtherUser = user !== Process.myUserHandle() - val actionsEnabled = - DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, - true - ) - return !savingToOtherUser && actionsEnabled - } - - companion object { - private const val TAG = "SmartActionsProvider" - private const val SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java index 6ff0fdaeab0f..ab23e5fdb7d9 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java @@ -22,11 +22,9 @@ import android.app.Service; import android.view.accessibility.AccessibilityManager; import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.screenshot.DefaultScreenshotActionsProvider; import com.android.systemui.screenshot.ImageCapture; import com.android.systemui.screenshot.ImageCaptureImpl; import com.android.systemui.screenshot.LegacyScreenshotViewProxy; -import com.android.systemui.screenshot.ScreenshotActionsProvider; import com.android.systemui.screenshot.ScreenshotPolicy; import com.android.systemui.screenshot.ScreenshotPolicyImpl; import com.android.systemui.screenshot.ScreenshotShelfViewProxy; @@ -90,10 +88,6 @@ public abstract class ScreenshotModule { abstract ScreenshotSoundController bindScreenshotSoundController( ScreenshotSoundControllerImpl screenshotSoundProviderImpl); - @Binds - abstract ScreenshotActionsProvider.Factory bindScreenshotActionsProviderFactory( - DefaultScreenshotActionsProvider.Factory defaultScreenshotActionsProviderFactory); - @Provides @SysUISingleton static ScreenshotViewModel providesScreenshotViewModel( diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt index 4a88180d8f73..0fb536636f1c 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt @@ -22,7 +22,28 @@ import com.android.systemui.screenshot.data.model.DisplayContentModel fun interface CapturePolicy { /** * Test the policy against the current display task state. If the policy applies, Returns a - * non-null [CaptureParameters] describing how the screenshot request should be augmented. + * [PolicyResult.Matched] containing [CaptureParameters] used to alter the request. */ - suspend fun apply(content: DisplayContentModel): CaptureParameters? + suspend fun check(content: DisplayContentModel): PolicyResult + + /** The result of a screen capture policy check. */ + sealed interface PolicyResult { + /** The policy rules matched the given display content and will be applied. */ + data class Matched( + /** The name of the policy rule which matched. */ + val policy: String, + /** Why the policy matched. */ + val reason: String, + /** Details on how to modify the screen capture request. */ + val parameters: CaptureParameters, + ) : PolicyResult + + /** The policy rules do not match the given display content and do not apply. */ + data class NotMatched( + /** The name of the policy rule which matched. */ + val policy: String, + /** Why the policy did not match. */ + val reason: String + ) : PolicyResult + } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt index 6ca2e9d6d5e0..0ef5207cad37 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt @@ -21,10 +21,10 @@ import android.graphics.Rect /** What to capture */ sealed interface CaptureType { /** Capture the entire screen contents. */ - class FullScreen(val displayId: Int) : CaptureType + data class FullScreen(val displayId: Int) : CaptureType /** Capture the contents of the task only. */ - class IsolatedTask( + data class IsolatedTask( val taskId: Int, val taskBounds: Rect?, ) : CaptureType diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt index 2c0a0dbf8ea9..80aa0efb0a19 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt @@ -16,9 +16,12 @@ package com.android.systemui.screenshot.policy +import android.app.ActivityTaskManager.RootTaskInfo +import android.app.WindowConfiguration import android.content.ComponentName import android.graphics.Bitmap import android.graphics.Rect +import android.os.Process.myUserHandle import android.os.UserHandle import android.util.Log import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN @@ -27,7 +30,10 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.screenshot.ImageCapture import com.android.systemui.screenshot.ScreenshotData import com.android.systemui.screenshot.ScreenshotRequestProcessor +import com.android.systemui.screenshot.data.model.DisplayContentModel import com.android.systemui.screenshot.data.repository.DisplayContentRepository +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched import com.android.systemui.screenshot.policy.CaptureType.FullScreen import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask import kotlinx.coroutines.CoroutineDispatcher @@ -39,8 +45,14 @@ private const val TAG = "PolicyRequestProcessor" class PolicyRequestProcessor( @Background private val background: CoroutineDispatcher, private val capture: ImageCapture, + /** Provides information about the tasks on a given display */ private val displayTasks: DisplayContentRepository, + /** The list of policies to apply, in order of priority */ private val policies: List<CapturePolicy>, + /** The owner to assign for screenshot when a focused task isn't visible */ + private val defaultOwner: UserHandle = myUserHandle(), + /** The assigned component when no application has focus, or not visible */ + private val defaultComponent: ComponentName, ) : ScreenshotRequestProcessor { override suspend fun process(original: ScreenshotData): ScreenshotData { if (original.type == TAKE_SCREENSHOT_PROVIDED_IMAGE) { @@ -48,29 +60,26 @@ class PolicyRequestProcessor( Log.i(TAG, "Screenshot bitmap provided. No modifications applied.") return original } - - val tasks = displayTasks.getDisplayContent(original.displayId) + val displayContent = displayTasks.getDisplayContent(original.displayId) // If policies yield explicit modifications, apply them and return the result Log.i(TAG, "Applying policy checks....") - policies - .firstNotNullOfOrNull { policy -> policy.apply(tasks) } - ?.let { - Log.i(TAG, "Modifying screenshot: $it") - return apply(it, original) + policies.map { policy -> + when (val result = policy.check(displayContent)) { + is Matched -> { + Log.i(TAG, "$result") + return modify(original, result.parameters) + } + is NotMatched -> Log.i(TAG, "$result") } + } // Otherwise capture normally, filling in additional information as needed. - return replaceWithScreenshot( - original = original, - componentName = original.topComponent ?: tasks.rootTasks.firstOrNull()?.topActivity, - owner = original.userHandle, - displayId = original.displayId - ) + return captureScreenshot(original, displayContent) } /** Produce a new [ScreenshotData] using [CaptureParameters] */ - suspend fun apply(updates: CaptureParameters, original: ScreenshotData): ScreenshotData { + suspend fun modify(original: ScreenshotData, updates: CaptureParameters): ScreenshotData { // Update and apply bitmap capture depending on the parameters. val updated = when (val type = updates.type) { @@ -93,6 +102,26 @@ class PolicyRequestProcessor( return updated } + private suspend fun captureScreenshot( + original: ScreenshotData, + displayContent: DisplayContentModel, + ): ScreenshotData { + // The first root task on the display, excluding Picture-in-Picture + val topMainRootTask = + if (!displayContent.systemUiState.shadeExpanded) { + displayContent.rootTasks.firstOrNull(::nonPipVisibleTask) + } else { + null // Otherwise attributed to SystemUI / current user + } + + return replaceWithScreenshot( + original = original, + componentName = topMainRootTask?.topActivity ?: defaultComponent, + owner = topMainRootTask?.userId?.let { UserHandle.of(it) } ?: defaultOwner, + displayId = original.displayId + ) + } + suspend fun replaceWithTaskSnapshot( original: ScreenshotData, componentName: ComponentName?, @@ -100,6 +129,7 @@ class PolicyRequestProcessor( taskId: Int, taskBounds: Rect?, ): ScreenshotData { + Log.i(TAG, "Capturing task snapshot: $componentName / $owner") val taskSnapshot = capture.captureTask(taskId) return original.copy( type = TAKE_SCREENSHOT_PROVIDED_IMAGE, @@ -117,6 +147,7 @@ class PolicyRequestProcessor( owner: UserHandle?, displayId: Int, ): ScreenshotData { + Log.i(TAG, "Capturing screenshot: $componentName / $owner") val screenshot = captureDisplay(displayId) return original.copy( type = TAKE_SCREENSHOT_FULLSCREEN, @@ -127,6 +158,16 @@ class PolicyRequestProcessor( ) } + /** Filter for the task used to attribute a full screen capture to an owner */ + private fun nonPipVisibleTask(info: RootTaskInfo): Boolean { + return info.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED && + info.isVisible && + info.isRunning && + info.numActivities > 0 && + info.topActivity != null && + info.childTaskIds.isNotEmpty() + } + /** TODO: Move to ImageCapture (existing function is non-suspending) */ private suspend fun captureDisplay(displayId: Int): Bitmap? { return withContext(background) { capture.captureDisplay(displayId) } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt index 221e64782894..d62ab8574799 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt @@ -20,10 +20,11 @@ import android.os.UserHandle import com.android.systemui.screenshot.data.model.DisplayContentModel import com.android.systemui.screenshot.data.model.ProfileType import com.android.systemui.screenshot.data.repository.ProfileTypeRepository +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched import com.android.systemui.screenshot.policy.CaptureType.FullScreen import javax.inject.Inject -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.firstOrNull /** * Condition: When any visible task belongs to a private user. @@ -35,7 +36,12 @@ class PrivateProfilePolicy constructor( private val profileTypes: ProfileTypeRepository, ) : CapturePolicy { - override suspend fun apply(content: DisplayContentModel): CaptureParameters? { + override suspend fun check(content: DisplayContentModel): PolicyResult { + // The systemUI notification shade isn't a private profile app, skip. + if (content.systemUiState.shadeExpanded) { + return NotMatched(policy = NAME, reason = "Notification shade is expanded") + } + // Find the first visible rootTaskInfo with a child task owned by a private user val (rootTask, childTask) = content.rootTasks @@ -48,13 +54,20 @@ constructor( } ?.let { root to it } } - ?: return null + ?: return NotMatched(policy = NAME, reason = "No private profile tasks are visible") // If matched, return parameters needed to modify the request. - return CaptureParameters( - type = FullScreen(content.displayId), - component = childTask.componentName ?: rootTask.topActivity, - owner = UserHandle.of(childTask.userId), + return Matched( + policy = NAME, + reason = "At least one private profile task is visible", + CaptureParameters( + type = FullScreen(content.displayId), + component = childTask.componentName ?: rootTask.topActivity, + owner = UserHandle.of(childTask.userId), + ) ) } + companion object { + const val NAME = "PrivateProfile" + } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt index d2f4d9e039f6..3789371d7c33 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt @@ -18,12 +18,10 @@ package com.android.systemui.screenshot.policy import android.app.ActivityTaskManager.RootTaskInfo import com.android.systemui.screenshot.data.model.ChildTaskModel -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.map -internal fun RootTaskInfo.childTasksTopDown(): Flow<ChildTaskModel> { - return ((numActivities - 1) downTo 0).asFlow().map { index -> +/** The child tasks of A RootTaskInfo as [ChildTaskModel] in top-down (z-index ascending) order. */ +internal fun RootTaskInfo.childTasksTopDown(): Sequence<ChildTaskModel> { + return ((childTaskIds.size - 1) downTo 0).asSequence().map { index -> ChildTaskModel( childTaskIds[index], childTaskNames[index], @@ -32,16 +30,3 @@ internal fun RootTaskInfo.childTasksTopDown(): Flow<ChildTaskModel> { ) } } - -internal suspend fun RootTaskInfo.firstChildTaskOrNull( - filter: suspend (Int) -> Boolean -): Pair<RootTaskInfo, Int>? { - // Child tasks are provided in bottom-up order - // Filtering is done top-down, so iterate backwards here. - for (index in numActivities - 1 downTo 0) { - if (filter(index)) { - return (this to index) - } - } - return null -} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt index 63d15087d12c..44f767aa321e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt @@ -16,8 +16,13 @@ package com.android.systemui.screenshot.policy -import com.android.systemui.Flags.screenshotPrivateProfile +import android.content.ComponentName +import android.content.Context +import android.os.Process +import com.android.systemui.Flags.screenshotPrivateProfileBehaviorFix +import com.android.systemui.SystemUIService import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.screenshot.ImageCapture import com.android.systemui.screenshot.RequestProcessor @@ -60,18 +65,22 @@ interface ScreenshotPolicyModule { @Provides @SysUISingleton fun bindScreenshotRequestProcessor( + @Application context: Context, @Background background: CoroutineDispatcher, imageCapture: ImageCapture, policyProvider: Provider<ScreenshotPolicy>, displayContentRepoProvider: Provider<DisplayContentRepository>, policyListProvider: Provider<List<CapturePolicy>>, ): ScreenshotRequestProcessor { - return if (screenshotPrivateProfile()) { + return if (screenshotPrivateProfileBehaviorFix()) { PolicyRequestProcessor( - background, - imageCapture, - displayContentRepoProvider.get(), - policyListProvider.get() + background = background, + capture = imageCapture, + displayTasks = displayContentRepoProvider.get(), + policies = policyListProvider.get(), + defaultOwner = Process.myUserHandle(), + defaultComponent = + ComponentName(context.packageName, SystemUIService::class.java.toString()) ) } else { RequestProcessor(imageCapture, policyProvider.get()) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt index d6b5d6dfda25..b781ae99a4de 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt @@ -21,6 +21,8 @@ import android.os.UserHandle import com.android.systemui.screenshot.data.model.DisplayContentModel import com.android.systemui.screenshot.data.model.ProfileType import com.android.systemui.screenshot.data.repository.ProfileTypeRepository +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult +import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask import javax.inject.Inject import kotlinx.coroutines.flow.first @@ -35,7 +37,13 @@ class WorkProfilePolicy constructor( private val profileTypes: ProfileTypeRepository, ) : CapturePolicy { - override suspend fun apply(content: DisplayContentModel): CaptureParameters? { + + override suspend fun check(content: DisplayContentModel): PolicyResult { + // The systemUI notification shade isn't a work app, skip. + if (content.systemUiState.shadeExpanded) { + return NotMatched(policy = NAME, reason = "Notification shade is expanded") + } + // Find the first non PiP rootTask with a top child task owned by a work user val (rootTask, childTask) = content.rootTasks @@ -44,13 +52,24 @@ constructor( .firstOrNull { (_, child) -> profileTypes.getProfileType(child.userId) == ProfileType.WORK } - ?: return null + ?: return NotMatched( + policy = NAME, + reason = "The top-most non-PINNED task does not belong to a work profile user" + ) // If matched, return parameters needed to modify the request. - return CaptureParameters( - type = IsolatedTask(taskId = childTask.id, taskBounds = childTask.bounds), - component = childTask.componentName ?: rootTask.topActivity, - owner = UserHandle.of(childTask.userId), + return PolicyResult.Matched( + policy = NAME, + reason = "The top-most non-PINNED task ($childTask) belongs to a work profile user", + CaptureParameters( + type = IsolatedTask(taskId = childTask.id, taskBounds = childTask.bounds), + component = childTask.componentName ?: rootTask.topActivity, + owner = UserHandle.of(childTask.userId), + ) ) } + + companion object { + val NAME = "WorkProfile" + } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java index 706ac9c46be1..b43a1d23da24 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java @@ -23,6 +23,7 @@ import android.content.ContentProvider; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.HardwareRenderer; +import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.RecordingCanvas; import android.graphics.Rect; @@ -38,9 +39,11 @@ import android.util.Log; import android.view.Display; import android.view.ScrollCaptureResponse; import android.view.View; +import android.view.WindowInsets; import android.widget.ImageView; import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.view.WindowCompat; import com.android.internal.app.ChooserActivity; import com.android.internal.logging.UiEventLogger; @@ -127,6 +130,10 @@ public class LongScreenshotActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + // Enable edge-to-edge explicitly. + WindowCompat.setDecorFitsSystemWindows(getWindow(), false); + setContentView(R.layout.long_screenshot); mPreview = requireViewById(R.id.preview); @@ -149,6 +156,13 @@ public class LongScreenshotActivity extends Activity { (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> updateImageDimensions()); + requireViewById(R.id.root).setOnApplyWindowInsetsListener( + (view, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars()); + view.setPadding(insets.left, insets.top, insets.right, insets.bottom); + return WindowInsets.CONSUMED; + }); + Intent intent = getIntent(); mScrollCaptureResponse = intent.getParcelableExtra(EXTRA_CAPTURE_RESPONSE); mScreenshotUserHandle = intent.getParcelableExtra(EXTRA_SCREENSHOT_USER_HANDLE, diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt index 747ad4f9e48c..b7a03ef42245 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt @@ -17,17 +17,70 @@ package com.android.systemui.screenshot.ui import android.content.Context +import android.graphics.Insets +import android.graphics.Rect +import android.graphics.Region import android.util.AttributeSet +import android.view.View import android.widget.ImageView import androidx.constraintlayout.widget.ConstraintLayout import com.android.systemui.res.R +import com.android.systemui.screenshot.FloatingWindowUtil class ScreenshotShelfView(context: Context, attrs: AttributeSet? = null) : ConstraintLayout(context, attrs) { lateinit var screenshotPreview: ImageView + private val displayMetrics = context.resources.displayMetrics + private val tmpRect = Rect() + private lateinit var actionsContainerBackground: View + private lateinit var dismissButton: View + override fun onFinishInflate() { super.onFinishInflate() screenshotPreview = requireViewById(R.id.screenshot_preview) + actionsContainerBackground = requireViewById(R.id.actions_container_background) + dismissButton = requireViewById(R.id.screenshot_dismiss_button) + } + + fun getTouchRegion(gestureInsets: Insets): Region { + val region = getSwipeRegion() + + // Receive touches in gesture insets so they don't cause TOUCH_OUTSIDE + // left edge gesture region + val insetRect = Rect(0, 0, gestureInsets.left, displayMetrics.heightPixels) + region.op(insetRect, Region.Op.UNION) + // right edge gesture region + insetRect.set( + displayMetrics.widthPixels - gestureInsets.right, + 0, + displayMetrics.widthPixels, + displayMetrics.heightPixels + ) + region.op(insetRect, Region.Op.UNION) + + return region + } + + private fun getSwipeRegion(): Region { + val swipeRegion = Region() + val padding = FloatingWindowUtil.dpToPx(displayMetrics, -1 * TOUCH_PADDING_DP).toInt() + swipeRegion.addInsetView(screenshotPreview, padding) + swipeRegion.addInsetView(actionsContainerBackground, padding) + swipeRegion.addInsetView(dismissButton, padding) + findViewById<View>(R.id.screenshot_message_container)?.let { + swipeRegion.addInsetView(it, padding) + } + return swipeRegion + } + + private fun Region.addInsetView(view: View, padding: Int = 0) { + view.getBoundsOnScreen(tmpRect) + tmpRect.inset(padding, padding) + this.op(tmpRect, Region.Op.UNION) + } + + companion object { + private const val TOUCH_PADDING_DP = 12f } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt index 32e9296107a3..5f835b3697a1 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt @@ -65,7 +65,9 @@ object ScreenshotShelfViewBinder { } launch { viewModel.actions.collect { actions -> - if (actions.isNotEmpty()) { + val visibleActions = actions.filter { it.visible } + + if (visibleActions.isNotEmpty()) { view .requireViewById<View>(R.id.actions_container_background) .visibility = View.VISIBLE @@ -75,7 +77,7 @@ object ScreenshotShelfViewBinder { // any new actions and update any that are already there. // This assumes that actions can never change order and that each action // ID is unique. - val newIds = actions.map { it.id } + val newIds = visibleActions.map { it.id } for (view in actionsContainer.children.toList()) { if (view.tag !in newIds) { @@ -83,7 +85,7 @@ object ScreenshotShelfViewBinder { } } - for ((index, action) in actions.withIndex()) { + for ((index, action) in visibleActions.withIndex()) { val currentView: View? = actionsContainer.getChildAt(index) if (action.id == currentView?.tag) { // Same ID, update the display @@ -93,7 +95,7 @@ object ScreenshotShelfViewBinder { // mean that the new action must be inserted here. val actionButton = layoutInflater.inflate( - R.layout.overlay_action_chip, + R.layout.shelf_action_chip, actionsContainer, false ) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt index 64b0105a98a0..c5fa8db953fa 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt @@ -19,6 +19,7 @@ package com.android.systemui.screenshot.ui.viewmodel data class ActionButtonViewModel( val appearance: ActionButtonAppearance, val id: Int, + val visible: Boolean, val onClicked: (() -> Unit)?, ) { companion object { @@ -29,6 +30,6 @@ data class ActionButtonViewModel( fun withNextId( appearance: ActionButtonAppearance, onClicked: (() -> Unit)? - ): ActionButtonViewModel = ActionButtonViewModel(appearance, getId(), onClicked) + ): ActionButtonViewModel = ActionButtonViewModel(appearance, getId(), true, onClicked) } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt index fa3480343ea0..f67ad402a738 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt @@ -48,12 +48,34 @@ class ScreenshotViewModel(private val accessibilityManager: AccessibilityManager return action.id } + fun setActionVisibility(actionId: Int, visible: Boolean) { + val actionList = _actions.value.toMutableList() + val index = actionList.indexOfFirst { it.id == actionId } + if (index >= 0) { + actionList[index] = + ActionButtonViewModel( + actionList[index].appearance, + actionId, + visible, + actionList[index].onClicked + ) + _actions.value = actionList + } else { + Log.w(TAG, "Attempted to update unknown action id $actionId") + } + } + fun updateActionAppearance(actionId: Int, appearance: ActionButtonAppearance) { val actionList = _actions.value.toMutableList() val index = actionList.indexOfFirst { it.id == actionId } if (index >= 0) { actionList[index] = - ActionButtonViewModel(appearance, actionId, actionList[index].onClicked) + ActionButtonViewModel( + appearance, + actionId, + actionList[index].visible, + actionList[index].onClicked + ) _actions.value = actionList } else { Log.w(TAG, "Attempted to update unknown action id $actionId") diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt index f6b1bcc0ceea..f418e7e0278f 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt @@ -23,7 +23,13 @@ import android.view.GestureDetector import android.view.MotionEvent import android.view.View import android.view.ViewGroup +import androidx.activity.OnBackPressedDispatcher +import androidx.activity.OnBackPressedDispatcherOwner +import androidx.activity.setViewTreeOnBackPressedDispatcherOwner import androidx.compose.ui.platform.ComposeView +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import com.android.compose.theme.PlatformTheme import com.android.internal.annotations.VisibleForTesting import com.android.systemui.communal.dagger.Communal @@ -33,6 +39,7 @@ import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import com.android.systemui.scene.shared.model.SceneDataSourceDelegator import com.android.systemui.shade.domain.interactor.ShadeInteractor @@ -40,6 +47,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialogFactory import com.android.systemui.util.kotlin.collectFlow import javax.inject.Inject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch /** * Controller that's responsible for the glanceable hub container view and its touch handling. @@ -139,13 +147,33 @@ constructor( ): View { return initView( ComposeView(context).apply { - setContent { - PlatformTheme { - CommunalContainer( - viewModel = communalViewModel, - dataSourceDelegator = dataSourceDelegator, - dialogFactory = dialogFactory, - ) + repeatWhenAttached { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.CREATED) { + setViewTreeOnBackPressedDispatcherOwner( + object : OnBackPressedDispatcherOwner { + override val onBackPressedDispatcher = + OnBackPressedDispatcher().apply { + setOnBackInvokedDispatcher( + viewRootImpl.onBackInvokedDispatcher + ) + } + + override val lifecycle: Lifecycle = + this@repeatWhenAttached.lifecycle + } + ) + + setContent { + PlatformTheme { + CommunalContainer( + viewModel = communalViewModel, + dataSourceDelegator = dataSourceDelegator, + dialogFactory = dialogFactory, + ) + } + } + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 4660831b77af..b8512f2de0a6 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -30,6 +30,11 @@ import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK; import static com.android.systemui.classifier.Classifier.GENERIC; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import static com.android.systemui.classifier.Classifier.UNLOCK; +import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING; +import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING_LOCKSCREEN_HOSTED; +import static com.android.systemui.keyguard.shared.model.KeyguardState.GONE; +import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN; +import static com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED; import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll; import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe; import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED; @@ -1119,7 +1124,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump controller.setup(mNotificationContainerParent)); // Dreaming->Lockscreen - collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(), + collectFlow(mView, mKeyguardTransitionInteractor.transition(DREAMING, LOCKSCREEN), mDreamingToLockscreenTransition, mMainDispatcher); collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(), setDreamLockscreenTransitionAlpha(mNotificationStackScrollLayoutController), @@ -1130,7 +1135,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump // Gone -> Dreaming hosted in lockscreen collectFlow(mView, mKeyguardTransitionInteractor - .getGoneToDreamingLockscreenHostedTransition(), + .transition(GONE, DREAMING_LOCKSCREEN_HOSTED), mGoneToDreamingLockscreenHostedTransition, mMainDispatcher); collectFlow(mView, mGoneToDreamingLockscreenHostedTransitionViewModel.getLockscreenAlpha(), setTransitionAlpha(mNotificationStackScrollLayoutController), @@ -1138,16 +1143,16 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump // Lockscreen -> Dreaming hosted in lockscreen collectFlow(mView, mKeyguardTransitionInteractor - .getLockscreenToDreamingLockscreenHostedTransition(), + .transition(LOCKSCREEN, DREAMING_LOCKSCREEN_HOSTED), mLockscreenToDreamingLockscreenHostedTransition, mMainDispatcher); // Dreaming hosted in lockscreen -> Lockscreen collectFlow(mView, mKeyguardTransitionInteractor - .getDreamingLockscreenHostedToLockscreenTransition(), + .transition(DREAMING_LOCKSCREEN_HOSTED, LOCKSCREEN), mDreamingLockscreenHostedToLockscreenTransition, mMainDispatcher); // Occluded->Lockscreen - collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(), + collectFlow(mView, mKeyguardTransitionInteractor.transition(OCCLUDED, LOCKSCREEN), mOccludedToLockscreenTransition, mMainDispatcher); if (!MigrateClocksToBlueprint.isEnabled()) { collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(), @@ -1158,7 +1163,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump } // Lockscreen->Dreaming - collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(), + collectFlow(mView, mKeyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING), mLockscreenToDreamingTransition, mMainDispatcher); if (!MigrateClocksToBlueprint.isEnabled()) { collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(), @@ -1170,7 +1175,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher); // Gone->Dreaming - collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(), + collectFlow(mView, mKeyguardTransitionInteractor.transition(GONE, DREAMING), mGoneToDreamingTransition, mMainDispatcher); if (!MigrateClocksToBlueprint.isEnabled()) { collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(), @@ -1181,7 +1186,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher); // Lockscreen->Occluded - collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(), + collectFlow(mView, mKeyguardTransitionInteractor.transition(LOCKSCREEN, OCCLUDED), mLockscreenToOccludedTransition, mMainDispatcher); if (!MigrateClocksToBlueprint.isEnabled()) { collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(), @@ -1201,6 +1206,16 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump "mPrimaryBouncerToGoneTransitionViewModel.getNotificationAlpha()"); }, mMainDispatcher); } + + // Ensures that flags are updated when an activity launches + collectFlow(mView, + mShadeAnimationInteractor.isLaunchingActivity(), + isLaunchingActivity -> { + if (isLaunchingActivity) { + updateSystemUiStateFlags(); + } + }, + mMainDispatcher); } @VisibleForTesting @@ -3632,7 +3647,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump + isFullyExpanded() + " inQs=" + mQsController.getExpanded()); } mSysUiState - .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE, isPanelExpanded()) + .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE, + isPanelExpanded() && !isCollapsing()) .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED, isFullyExpanded() && !mQsController.getExpanded()) .setFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED, diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java index fb32b9fce909..adcb14a67983 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java @@ -59,7 +59,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.scene.ui.view.WindowRootViewComponent; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.domain.interactor.ShadeInteractor; @@ -117,7 +117,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private final AuthController mAuthController; private final Lazy<SelectedUserInteractor> mUserInteractor; private final Lazy<ShadeInteractor> mShadeInteractorLazy; - private final SceneContainerFlags mSceneContainerFlags; private final Lazy<CommunalInteractor> mCommunalInteractor; private ViewGroup mWindowRootView; private LayoutParams mLp; @@ -166,7 +165,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW ShadeWindowLogger logger, Lazy<SelectedUserInteractor> userInteractor, UserTracker userTracker, - SceneContainerFlags sceneContainerFlags, Lazy<CommunalInteractor> communalInteractor) { mContext = context; mWindowRootViewComponentFactory = windowRootViewComponentFactory; @@ -186,7 +184,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this); mAuthController = authController; mUserInteractor = userInteractor; - mSceneContainerFlags = sceneContainerFlags; mCommunalInteractor = communalInteractor; mLastKeyguardRotationAllowed = mKeyguardStateController.isKeyguardScreenRotationAllowed(); mLockScreenDisplayTimeout = context.getResources() @@ -289,7 +286,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; mLp.privateFlags |= PRIVATE_FLAG_OPTIMIZE_MEASURE; - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { // This prevents the appearance and disappearance of the software keyboard (also known // as the "IME") from scrolling/panning the window to make room for the keyboard. // diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 6ac81d226eee..00bc752c1b83 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -18,6 +18,8 @@ package com.android.systemui.shade; import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; import static com.android.systemui.flags.Flags.TRACKPAD_GESTURE_COMMON; +import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING; +import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; @@ -221,7 +223,7 @@ public class NotificationShadeWindowViewController implements Dumpable { mDisableSubpixelTextTransitionListener = new DisableSubpixelTextTransitionListener(mView); bouncerViewBinder.bind(mView.findViewById(R.id.keyguard_bouncer_container)); - collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(), + collectFlow(mView, keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING), mLockscreenToDreamingTransition); collectFlow( mView, @@ -382,12 +384,15 @@ public class NotificationShadeWindowViewController implements Dumpable { float x = ev.getRawX(); float y = ev.getRawY(); if (mStatusBarViewController.touchIsWithinView(x, y)) { - if (mStatusBarWindowStateController.windowIsShowing()) { - mIsTrackingBarGesture = true; - return logDownDispatch(ev, "sending touch to status bar", - mStatusBarViewController.sendTouchToView(ev)); - } else { - return logDownDispatch(ev, "hidden or hiding", true); + if (!(MigrateClocksToBlueprint.isEnabled() + && mPrimaryBouncerInteractor.isBouncerShowing())) { + if (mStatusBarWindowStateController.windowIsShowing()) { + mIsTrackingBarGesture = true; + return logDownDispatch(ev, "sending touch to status bar", + mStatusBarViewController.sendTouchToView(ev)); + } else { + return logDownDispatch(ev, "hidden or hiding", true); + } } } } else if (mIsTrackingBarGesture) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt index ebebbe65d54b..8c15817898a8 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt @@ -124,7 +124,6 @@ constructor( // release focus immediately to kick off focus change transition notificationShadeWindowController.setNotificationShadeFocusable(false) notificationStackScrollLayout.cancelExpandHelper() - sceneInteractor.changeScene(Scenes.Shade, "ShadeController.animateExpandShade") if (delayed) { scope.launch { delay(125) diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt index 648d4b55370e..a0c939107fdb 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt @@ -19,7 +19,7 @@ package com.android.systemui.shade import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.qs.QSContainerController import com.android.systemui.qs.ui.adapter.QSSceneAdapterImpl -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.data.repository.PrivacyChipRepository import com.android.systemui.shade.data.repository.PrivacyChipRepositoryImpl import com.android.systemui.shade.data.repository.ShadeRepository @@ -50,11 +50,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun provideBaseShadeInteractor( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<ShadeInteractorSceneContainerImpl>, sceneContainerOff: Provider<ShadeInteractorLegacyImpl> ): BaseShadeInteractor { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() @@ -64,11 +63,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun provideShadeController( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<ShadeControllerSceneImpl>, sceneContainerOff: Provider<ShadeControllerImpl> ): ShadeController { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() @@ -78,11 +76,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun provideShadeAnimationInteractor( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<ShadeAnimationInteractorSceneContainerImpl>, sceneContainerOff: Provider<ShadeAnimationInteractorLegacyImpl> ): ShadeAnimationInteractor { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() @@ -92,11 +89,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun provideShadeBackActionInteractor( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<ShadeBackActionInteractorImpl>, sceneContainerOff: Provider<NotificationPanelViewController> ): ShadeBackActionInteractor { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() @@ -106,11 +102,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun provideShadeLockscreenInteractor( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<ShadeLockscreenInteractorImpl>, sceneContainerOff: Provider<NotificationPanelViewController> ): ShadeLockscreenInteractor { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() @@ -120,11 +115,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun providePanelExpansionInteractor( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<PanelExpansionInteractorImpl>, sceneContainerOff: Provider<NotificationPanelViewController> ): PanelExpansionInteractor { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() @@ -134,11 +128,10 @@ abstract class ShadeModule { @Provides @SysUISingleton fun provideQuickSettingsController( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<QuickSettingsControllerSceneImpl>, sceneContainerOff: Provider<QuickSettingsControllerImpl>, ): QuickSettingsController { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt index f5dd5e465505..bc2377895101 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt @@ -33,7 +33,7 @@ import com.android.systemui.flags.FeatureFlags import com.android.systemui.keyguard.ui.view.KeyguardRootView import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.res.R -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scene import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneDataSourceDelegator @@ -78,15 +78,13 @@ abstract class ShadeViewProviderModule { @SysUISingleton fun providesWindowRootView( layoutInflater: LayoutInflater, - sceneContainerFlags: SceneContainerFlags, viewModelProvider: Provider<SceneContainerViewModel>, containerConfigProvider: Provider<SceneContainerConfig>, - flagsProvider: Provider<SceneContainerFlags>, scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>, layoutInsetController: NotificationInsetsController, sceneDataSourceDelegator: Provider<SceneDataSourceDelegator>, ): WindowRootView { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { checkNoSceneDuplicates(scenesProvider.get()) val sceneWindowRootView = layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView @@ -95,7 +93,6 @@ abstract class ShadeViewProviderModule { containerConfig = containerConfigProvider.get(), sharedNotificationContainer = sceneWindowRootView.requireViewById(R.id.shared_notification_container), - flags = flagsProvider.get(), scenes = scenesProvider.get(), layoutInsetController = layoutInsetController, sceneDataSourceDelegator = sceneDataSourceDelegator.get(), @@ -115,9 +112,8 @@ abstract class ShadeViewProviderModule { @SysUISingleton fun providesNotificationShadeWindowView( root: WindowRootView, - sceneContainerFlags: SceneContainerFlags, ): NotificationShadeWindowView { - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { return root.requireViewById(R.id.legacy_window_root) } return root as NotificationShadeWindowView? diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt index d68e28c930f4..0b45c0834245 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt @@ -82,7 +82,7 @@ constructor( override val isShadeTouchable: Flow<Boolean> = combine( powerInteractor.isAsleep, - keyguardTransitionInteractor.isInTransitionToStateWhere { it == KeyguardState.AOD }, + keyguardTransitionInteractor.isInTransitionToState(KeyguardState.AOD), keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING }, ) { isAsleep, goingToSleep, isPulsing -> when { diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt index 72a9c8d01554..6c7606170d9f 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt @@ -22,9 +22,11 @@ import android.content.IntentFilter import android.icu.text.DateFormat import android.icu.text.DisplayContext import android.os.UserHandle +import android.provider.Settings import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.plugins.ActivityStarter import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyItem import com.android.systemui.res.R @@ -54,6 +56,7 @@ class ShadeHeaderViewModel constructor( @Application private val applicationScope: CoroutineScope, context: Context, + private val activityStarter: ActivityStarter, shadeInteractor: ShadeInteractor, mobileIconsInteractor: MobileIconsInteractor, val mobileIconsViewModel: MobileIconsViewModel, @@ -136,6 +139,14 @@ constructor( clockInteractor.launchClockActivity() } + /** Notifies that the shadeCarrierGroup was clicked. */ + fun onShadeCarrierGroupClicked() { + activityStarter.postStartActivityDismissingKeyguard( + Intent(Settings.ACTION_WIRELESS_SETTINGS), + 0 + ) + } + private fun updateDateTexts(invalidateFormats: Boolean) { if (invalidateFormats) { longerDateFormat.value = getFormatFromPattern(longerPattern) diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt index 980f665ae61f..6800c6115080 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt @@ -37,6 +37,7 @@ import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorVie import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel +import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -64,6 +65,7 @@ constructor( private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, private val footerActionsController: FooterActionsController, private val sceneInteractor: SceneInteractor, + unfoldTransitionInteractor: UnfoldTransitionInteractor, ) { val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> = combine( @@ -106,6 +108,16 @@ constructor( val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode + /** + * The unfold transition progress. When fully-unfolded, this is `1` and fully folded, it's `0`. + */ + val unfoldTransitionProgress: StateFlow<Float> = + unfoldTransitionInteractor.unfoldProgress.stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = 1f + ) + /** Notifies that some content in the shade was clicked. */ fun onContentClicked() { if (!isClickable.value) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index e7b159a2d057..d955349ffede 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -50,6 +50,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Pair; import android.util.SparseArray; import android.view.KeyEvent; @@ -516,7 +517,7 @@ public class CommandQueue extends IStatusBar.Stub implements /** * @see IStatusBar#showMediaOutputSwitcher */ - default void showMediaOutputSwitcher(String packageName) {} + default void showMediaOutputSwitcher(String packageName, UserHandle userHandle) {} /** * @see IStatusBar#confirmImmersivePrompt @@ -1361,7 +1362,7 @@ public class CommandQueue extends IStatusBar.Stub implements } } @Override - public void showMediaOutputSwitcher(String packageName) { + public void showMediaOutputSwitcher(String packageName, UserHandle userHandle) { int callingUid = Binder.getCallingUid(); if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { throw new SecurityException("Call only allowed from system server."); @@ -1369,6 +1370,7 @@ public class CommandQueue extends IStatusBar.Stub implements synchronized (mLock) { SomeArgs args = SomeArgs.obtain(); args.arg1 = packageName; + args.arg2 = userHandle; mHandler.obtainMessage(MSG_SHOW_MEDIA_OUTPUT_SWITCHER, args).sendToTarget(); } } @@ -1939,8 +1941,10 @@ public class CommandQueue extends IStatusBar.Stub implements case MSG_SHOW_MEDIA_OUTPUT_SWITCHER: args = (SomeArgs) msg.obj; String clientPackageName = (String) args.arg1; + UserHandle clientUserHandle = (UserHandle) args.arg2; for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).showMediaOutputSwitcher(clientPackageName); + mCallbacks.get(i).showMediaOutputSwitcher(clientPackageName, + clientUserHandle); } break; case MSG_CONFIRM_IMMERSIVE_PROMPT: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 815236e0820c..09985f842185 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -195,20 +195,20 @@ public class KeyguardIndicationController { private boolean mOrganizationOwnedDevice; // these all assume the device is plugged in (wired/wireless/docked) AND chargingOrFull: - private boolean mPowerPluggedIn; - private boolean mPowerPluggedInWired; - private boolean mPowerPluggedInWireless; - private boolean mPowerPluggedInDock; + protected boolean mPowerPluggedIn; + protected boolean mPowerPluggedInWired; + protected boolean mPowerPluggedInWireless; + protected boolean mPowerPluggedInDock; private boolean mPowerCharged; private boolean mBatteryDefender; private boolean mEnableBatteryDefender; private boolean mIncompatibleCharger; - private int mChargingSpeed; + protected int mChargingSpeed; private int mChargingWattage; private int mBatteryLevel; private boolean mBatteryPresent = true; - private long mChargingTimeRemaining; + protected long mChargingTimeRemaining; private Pair<String, BiometricSourceType> mBiometricErrorMessageToShowOnScreenOn; private final Set<Integer> mCoExFaceAcquisitionMsgIdsToShow; private final FaceHelpMessageDeferral mFaceAcquiredMessageDeferral; @@ -1053,20 +1053,24 @@ public class KeyguardIndicationController { * Assumption: device is charging */ protected String computePowerIndication() { - int chargingId; if (mBatteryDefender) { - chargingId = R.string.keyguard_plugged_in_charging_limited; String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f); - return mContext.getResources().getString(chargingId, percentage); + return mContext.getResources().getString( + R.string.keyguard_plugged_in_charging_limited, percentage); } else if (mPowerPluggedIn && mIncompatibleCharger) { - chargingId = R.string.keyguard_plugged_in_incompatible_charger; String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f); - return mContext.getResources().getString(chargingId, percentage); + return mContext.getResources().getString( + R.string.keyguard_plugged_in_incompatible_charger, percentage); } else if (mPowerCharged) { return mContext.getResources().getString(R.string.keyguard_charged); } + return computePowerChargingStringIndication(); + } + + protected String computePowerChargingStringIndication() { final boolean hasChargingTime = mChargingTimeRemaining > 0; + int chargingId; if (mPowerPluggedInWired) { switch (mChargingSpeed) { case BatteryStatus.CHARGING_FAST: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index bb6ee24b0ffe..f8193a4a1b93 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -57,6 +57,7 @@ import com.android.app.animation.Interpolators; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.util.ContrastColorUtil; +import com.android.systemui.Flags; import com.android.systemui.res.R; import com.android.systemui.statusbar.notification.NotificationContentDescription; import com.android.systemui.statusbar.notification.NotificationDozeHelper; @@ -208,6 +209,10 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi initializeDecorColor(); reloadDimens(); maybeUpdateIconScaleDimens(); + + if (Flags.statusBarMonochromeIconsFix()) { + setCropToPadding(true); + } } /** Should always be preceded by {@link #reloadDimens()} */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java index e5b64970c5b0..594c1913fd33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java @@ -35,7 +35,7 @@ import com.android.systemui.dump.DumpHandler; import com.android.systemui.dump.DumpManager; import com.android.systemui.media.controls.domain.pipeline.MediaDataManager; import com.android.systemui.power.domain.interactor.PowerInteractor; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.settings.DisplayTracker; import com.android.systemui.shade.NotificationPanelViewController; import com.android.systemui.shade.ShadeSurface; @@ -61,8 +61,6 @@ import com.android.systemui.statusbar.phone.StatusBarIconList; import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback; import com.android.systemui.statusbar.policy.KeyguardStateController; -import javax.inject.Provider; - import dagger.Binds; import dagger.Lazy; import dagger.Module; @@ -70,6 +68,8 @@ import dagger.Provides; import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; +import javax.inject.Provider; + /** * This module provides instances needed to construct {@link CentralSurfacesImpl}. These are moved to * this separate from {@link CentralSurfacesModule} module so that components that wish to build @@ -185,10 +185,9 @@ public interface CentralSurfacesDependenciesModule { @Provides @SysUISingleton static ShadeSurface provideShadeSurface( - SceneContainerFlags sceneContainerFlags, Provider<ShadeSurfaceImpl> sceneContainerOn, Provider<NotificationPanelViewController> sceneContainerOff) { - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { return sceneContainerOn.get(); } else { return sceneContainerOff.get(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 9ce38db1aebe..8b673c951b94 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -49,7 +49,6 @@ import android.os.SystemClock; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; -import android.util.ArraySet; import android.view.ContentInfo; import androidx.annotation.NonNull; @@ -150,10 +149,8 @@ public final class NotificationEntry extends ListEntry { private int mCachedContrastColor = COLOR_INVALID; private int mCachedContrastColorIsFor = COLOR_INVALID; private InflationTask mRunningTask = null; - private Throwable mDebugThrowable; public CharSequence remoteInputTextWhenReset; public long lastRemoteInputSent = NOT_LAUNCHED_YET; - public final ArraySet<Integer> mActiveAppOps = new ArraySet<>(3); private final MutableStateFlow<CharSequence> mHeadsUpStatusBarText = StateFlowKt.MutableStateFlow(null); @@ -190,11 +187,6 @@ public final class NotificationEntry extends ListEntry { private boolean mBlockable; /** - * The {@link SystemClock#elapsedRealtime()} when this notification entry was created. - */ - public long mCreationElapsedRealTime; - - /** * Whether this notification has ever been a non-sticky HUN. */ private boolean mIsDemoted = false; @@ -264,13 +256,8 @@ public final class NotificationEntry extends ListEntry { mKey = sbn.getKey(); setSbn(sbn); setRanking(ranking); - mCreationElapsedRealTime = SystemClock.elapsedRealtime(); } - @VisibleForTesting - public void setCreationElapsedRealTime(long time) { - mCreationElapsedRealTime = time; - } @Override public NotificationEntry getRepresentativeEntry() { return this; @@ -581,19 +568,6 @@ public final class NotificationEntry extends ListEntry { return mRunningTask; } - /** - * Set a throwable that is used for debugging - * - * @param debugThrowable the throwable to save - */ - public void setDebugThrowable(Throwable debugThrowable) { - mDebugThrowable = debugThrowable; - } - - public Throwable getDebugThrowable() { - return mDebugThrowable; - } - public void onRemoteInputInserted() { lastRemoteInputSent = NOT_LAUNCHED_YET; remoteInputTextWhenReset = null; @@ -749,12 +723,6 @@ public final class NotificationEntry extends ListEntry { return row != null && row.areChildrenExpanded(); } - - //TODO: probably less confusing to say "is group fully visible" - public boolean isGroupNotFullyVisible() { - return row == null || row.isGroupNotFullyVisible(); - } - public NotificationGuts getGuts() { if (row != null) return row.getGuts(); return null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt index ed8c05688a66..77660eb7d864 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt @@ -29,9 +29,9 @@ interface HeadsUpRepository { /** * True if we are exiting the headsUp pinned mode, and some notifications might still be - * animating out. This is used to keep the touchable regions in a reasonable state. + * animating out. This is used to keep their view container visible. */ - val headsUpAnimatingAway: Flow<Boolean> + val isHeadsUpAnimatingAway: Flow<Boolean> /** The heads up row that should be displayed on top. */ val topHeadsUpRow: Flow<HeadsUpRowRepository?> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt index d1dd7b55c11f..7f94da3c8c6a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt @@ -60,7 +60,7 @@ class HeadsUpNotificationInteractor @Inject constructor(repository: HeadsUpRepos } val isHeadsUpOrAnimatingAway: Flow<Boolean> = - combine(hasPinnedRows, repository.headsUpAnimatingAway) { hasPinnedRows, animatingAway -> + combine(hasPinnedRows, repository.isHeadsUpAnimatingAway) { hasPinnedRows, animatingAway -> hasPinnedRows || animatingAway } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt index c4d9ab7a47c2..9619acaed441 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt @@ -27,6 +27,7 @@ import android.database.ContentObserver import android.hardware.display.AmbientDisplayConfiguration import android.os.Handler import android.os.PowerManager +import android.provider.Settings import android.provider.Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED import android.provider.Settings.Global.HEADS_UP_OFF import com.android.systemui.dagger.qualifiers.Main @@ -42,6 +43,7 @@ import com.android.systemui.statusbar.notification.interruption.VisualInterrupti import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.util.settings.GlobalSettings +import com.android.systemui.util.settings.SystemSettings import com.android.systemui.util.time.SystemClock class PeekDisabledSuppressor( @@ -231,6 +233,7 @@ class AlertKeyguardVisibilitySuppressor( class AvalancheSuppressor( private val avalancheProvider: AvalancheProvider, private val systemClock: SystemClock, + private val systemSettings: SystemSettings, ) : VisualInterruptionFilter( types = setOf(PEEK, PULSE), @@ -253,12 +256,23 @@ class AvalancheSuppressor( } override fun shouldSuppress(entry: NotificationEntry): Boolean { - val timeSinceAvalanche = systemClock.currentTimeMillis() - avalancheProvider.startTime - val isActive = timeSinceAvalanche < avalancheProvider.timeoutMs + if (!isCooldownEnabled()) { + reason = "FALSE avalanche cooldown setting DISABLED" + return false + } + val timeSinceAvalancheMs = systemClock.currentTimeMillis() - avalancheProvider.startTime + val timedOut = timeSinceAvalancheMs >= avalancheProvider.timeoutMs + if (timedOut) { + reason = "FALSE avalanche event TIMED OUT. " + + "${timeSinceAvalancheMs/1000} seconds since last avalanche" + return false + } val state = calculateState(entry) - val suppress = isActive && state == State.SUPPRESS - reason = "avalanche suppress=$suppress isActive=$isActive state=$state" - return suppress + if (state != State.SUPPRESS) { + reason = "FALSE avalanche IN ALLOWLIST: $state" + return false + } + return true } private fun calculateState(entry: NotificationEntry): State { @@ -294,4 +308,11 @@ class AvalancheSuppressor( } return State.SUPPRESS } + + private fun isCooldownEnabled(): Boolean { + return systemSettings.getInt( + Settings.System.NOTIFICATION_COOLDOWN_ENABLED, + /* def */ 1 + ) == 1 + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt index 375b6e5cb6a3..e6d97c211dc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt @@ -40,6 +40,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.EventLog import com.android.systemui.util.settings.GlobalSettings +import com.android.systemui.util.settings.SystemSettings import com.android.systemui.util.time.SystemClock import javax.inject.Inject @@ -61,7 +62,8 @@ constructor( private val systemClock: SystemClock, private val uiEventLogger: UiEventLogger, private val userTracker: UserTracker, - private val avalancheProvider: AvalancheProvider + private val avalancheProvider: AvalancheProvider, + private val systemSettings: SystemSettings ) : VisualInterruptionDecisionProvider { init { @@ -170,7 +172,7 @@ constructor( addFilter(AlertKeyguardVisibilitySuppressor(keyguardNotificationVisibilityProvider)) if (NotificationAvalancheSuppression.isEnabled) { - addFilter(AvalancheSuppressor(avalancheProvider, systemClock)) + addFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) avalancheProvider.register() } started = true diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt index d6118a0b3865..d3c874ce04d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.row +import android.app.Flags import android.app.Notification import android.app.Notification.MessagingStyle import android.app.Person @@ -131,7 +132,7 @@ internal object SingleLineViewInflater { val senderName = systemUiContext.resources.getString( R.string.conversation_single_line_name_display, - name + if (Flags.cleanUpSpansAndNewLines()) name?.toString() else name ) // We need to find back-up values for those texts if they are needed and empty diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 5eaccd924344..e980794d23dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -594,7 +594,11 @@ public class StackScrollAlgorithm { ); if (view instanceof FooterView) { if (FooterViewRefactor.isEnabled()) { - if (((FooterView) view).shouldBeHidden()) { + // TODO(b/333445519): shouldBeHidden should reflect whether the shade is closed + // already, so we shouldn't need to use ambientState here. However, currently it + // doesn't get updated quickly enough and can cause the footer to flash when + // closing the shade. As such, we temporarily also check the ambientState directly. + if (((FooterView) view).shouldBeHidden() || !ambientState.isShadeExpanded()) { viewState.hidden = true; } else { final float footerEnd = algorithmState.mCurrentExpandedYPosition diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt index 741102bcd574..cf5366b92cda 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt @@ -29,7 +29,6 @@ import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.scene.shared.flag.SceneContainerFlag -import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator @@ -49,7 +48,6 @@ import kotlinx.coroutines.launch class SharedNotificationContainerBinder @Inject constructor( - private val sceneContainerFlags: SceneContainerFlags, private val controller: NotificationStackScrollLayoutController, private val notificationStackSizeCalculator: NotificationStackSizeCalculator, private val notificationScrollViewBinder: NotificationScrollViewBinder, @@ -130,7 +128,7 @@ constructor( .collect { controller.setMaxDisplayedNotifications(it) } } - if (!sceneContainerFlags.isEnabled()) { + if (!SceneContainerFlag.isEnabled) { launch { viewModel.bounds.collect { val animate = @@ -166,7 +164,7 @@ constructor( } } - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { disposables += notificationScrollViewBinder.bindWhileAttached() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt index b284179d42b7..ca19da58a135 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt @@ -22,7 +22,7 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds @@ -43,7 +43,6 @@ constructor( dumpManager: DumpManager, private val interactor: NotificationStackAppearanceInteractor, shadeInteractor: ShadeInteractor, - flags: SceneContainerFlags, featureFlags: FeatureFlagsClassic, private val keyguardInteractor: KeyguardInteractor, ) : FlowDumperImpl(dumpManager) { @@ -51,7 +50,7 @@ constructor( val isVisualDebuggingEnabled: Boolean = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES) /** DEBUG: whether the debug logging should be output. */ - val isDebugLoggingEnabled: Boolean = flags.isEnabled() + val isDebugLoggingEnabled: Boolean = SceneContainerFlag.isEnabled /** Notifies that the bounds of the notification scrim have changed. */ fun onScrimBoundsChanged(bounds: ShadeScrimBounds?) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index 0486ef5bca51..50996821a156 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -57,6 +57,7 @@ import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGoneTransitionView import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenToPrimaryBouncerTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludedToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.OccludedToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel @@ -121,6 +122,7 @@ constructor( LockscreenToPrimaryBouncerTransitionViewModel, private val lockscreenToOccludedTransitionViewModel: LockscreenToOccludedTransitionViewModel, private val occludedToAodTransitionViewModel: OccludedToAodTransitionViewModel, + private val occludedToGoneTransitionViewModel: OccludedToGoneTransitionViewModel, private val occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel, private val primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel, private val primaryBouncerToLockscreenTransitionViewModel: @@ -207,9 +209,7 @@ constructor( keyguardTransitionInteractor.finishedKeyguardState.map { statesForConstrainedNotifications.contains(it) }, - keyguardTransitionInteractor - .isInTransitionWhere { from, to -> from == LOCKSCREEN || to == LOCKSCREEN } - .onStart { emit(false) } + keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f }, ) { constrainedNotificationState, transitioningToOrFromLockscreen -> constrainedNotificationState || transitioningToOrFromLockscreen } @@ -241,11 +241,10 @@ constructor( keyguardTransitionInteractor.finishedKeyguardState.map { state -> state == GLANCEABLE_HUB }, - keyguardTransitionInteractor - .isInTransitionWhere { from, to -> - from == GLANCEABLE_HUB || to == GLANCEABLE_HUB - } - .onStart { emit(false) } + or( + keyguardTransitionInteractor.isInTransitionToState(GLANCEABLE_HUB), + keyguardTransitionInteractor.isInTransitionFromState(GLANCEABLE_HUB), + ), ) { isOnGlanceableHub, transitioningToOrFromHub -> isOnGlanceableHub || transitioningToOrFromHub } @@ -290,12 +289,10 @@ constructor( var aodTransitionIsComplete = true return combine( isOnLockscreenWithoutShade, - keyguardTransitionInteractor - .isInTransitionWhere( - fromStatePredicate = { it == LOCKSCREEN }, - toStatePredicate = { it == AOD } - ) - .onStart { emit(false) }, + keyguardTransitionInteractor.isInTransition( + from = LOCKSCREEN, + to = AOD, + ), ::Pair ) .transformWhile { (isOnLockscreenWithoutShade, aodTransitionIsRunning) -> @@ -350,7 +347,8 @@ constructor( * * When the shade is expanding, the position is controlled by... the shade. */ - val bounds: StateFlow<NotificationContainerBounds> = + val bounds: StateFlow<NotificationContainerBounds> by lazy { + SceneContainerFlag.assertInLegacyMode() combine( isOnLockscreenWithoutShade, keyguardInteractor.notificationContainerBounds, @@ -380,6 +378,7 @@ constructor( initialValue = NotificationContainerBounds(), ) .dumpValue("bounds") + } /** * Ensure view is visible when the shade/qs are expanded. Also, as QS is expanding, fade out @@ -475,6 +474,7 @@ constructor( lockscreenToOccludedTransitionViewModel.lockscreenAlpha, lockscreenToPrimaryBouncerTransitionViewModel.lockscreenAlpha, occludedToAodTransitionViewModel.lockscreenAlpha, + occludedToGoneTransitionViewModel.notificationAlpha(viewState), occludedToLockscreenTransitionViewModel.lockscreenAlpha, primaryBouncerToGoneTransitionViewModel.notificationAlpha, primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt index 37646aea86e2..9268d1658b80 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt @@ -14,51 +14,20 @@ package com.android.systemui.statusbar.phone -import android.app.ActivityManager -import android.app.ActivityOptions -import android.app.ActivityTaskManager import android.app.PendingIntent -import android.app.TaskStackBuilder -import android.content.Context import android.content.Intent import android.os.Bundle -import android.os.RemoteException import android.os.UserHandle -import android.provider.Settings -import android.util.Log -import android.view.RemoteAnimationAdapter import android.view.View -import android.view.WindowManager -import com.android.keyguard.KeyguardUpdateMonitor -import com.android.systemui.ActivityIntentHelper import com.android.systemui.animation.ActivityTransitionAnimator -import com.android.systemui.animation.ActivityTransitionAnimator.PendingIntentStarter -import com.android.systemui.animation.DelegateTransitionAnimatorController -import com.android.systemui.assist.AssistManager -import com.android.systemui.camera.CameraIntents.Companion.isInsecureCameraIntent import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.DisplayId import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.keyguard.KeyguardViewMediator -import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter.OnDismissAction -import com.android.systemui.res.R -import com.android.systemui.settings.UserTracker -import com.android.systemui.shade.ShadeController -import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor -import com.android.systemui.statusbar.CommandQueue -import com.android.systemui.statusbar.NotificationLockscreenUserManager -import com.android.systemui.statusbar.NotificationShadeWindowController +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.statusbar.SysuiStatusBarStateController -import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow -import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.KeyguardStateController -import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.kotlin.getOrNull import dagger.Lazy -import java.util.Optional import javax.inject.Inject /** Handles start activity logic in SystemUI. */ @@ -66,38 +35,18 @@ import javax.inject.Inject class ActivityStarterImpl @Inject constructor( - private val centralSurfacesOptLazy: Lazy<Optional<CentralSurfaces>>, - private val assistManagerLazy: Lazy<AssistManager>, - private val dozeServiceHostLazy: Lazy<DozeServiceHost>, - private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>, - private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>, - private val shadeControllerLazy: Lazy<ShadeController>, - private val commandQueue: CommandQueue, - private val shadeAnimationInteractor: ShadeAnimationInteractor, - private val statusBarKeyguardViewManagerLazy: Lazy<StatusBarKeyguardViewManager>, - private val notifShadeWindowControllerLazy: Lazy<NotificationShadeWindowController>, - private val activityTransitionAnimator: ActivityTransitionAnimator, - private val context: Context, - @DisplayId private val displayId: Int, - private val lockScreenUserManager: NotificationLockscreenUserManager, - private val statusBarWindowController: StatusBarWindowController, - private val wakefulnessLifecycle: WakefulnessLifecycle, - private val keyguardStateController: KeyguardStateController, private val statusBarStateController: SysuiStatusBarStateController, - private val keyguardUpdateMonitor: KeyguardUpdateMonitor, - private val deviceProvisionedController: DeviceProvisionedController, - private val userTracker: UserTracker, - private val activityIntentHelper: ActivityIntentHelper, @Main private val mainExecutor: DelayableExecutor, + legacyActivityStarter: Lazy<LegacyActivityStarterInternalImpl>, + activityStarterInternal: Lazy<ActivityStarterInternalImpl>, ) : ActivityStarter { - companion object { - const val TAG = "ActivityStarterImpl" - } - - private val centralSurfaces: CentralSurfaces? - get() = centralSurfacesOptLazy.get().getOrNull() - private val activityStarterInternal = ActivityStarterInternal() + private val activityStarterInternal: ActivityStarterInternal = + if (SceneContainerFlag.isEnabled) { + activityStarterInternal.get() + } else { + legacyActivityStarter.get() + } override fun startPendingIntentDismissingKeyguard(intent: PendingIntent) { activityStarterInternal.startPendingIntentDismissingKeyguard(intent = intent) @@ -401,575 +350,11 @@ constructor( } } - private fun postOnUiThread(delay: Int = 0, runnable: Runnable) { - mainExecutor.executeDelayed(runnable, delay.toLong()) - } - - /** - * Whether we should animate an activity launch. - * - * Note: This method must be called *before* dismissing the keyguard. - */ - private fun shouldAnimateLaunch( - isActivityIntent: Boolean, - showOverLockscreen: Boolean, - ): Boolean { - // TODO(b/294418322): Support launch animations when occluded. - if (keyguardStateController.isOccluded) { - return false - } - - // Always animate if we are not showing the keyguard or if we animate over the lockscreen - // (without unlocking it). - if (showOverLockscreen || !keyguardStateController.isShowing) { - return true - } - - // We don't animate non-activity launches as they can break the animation. - // TODO(b/184121838): Support non activity launches on the lockscreen. - return isActivityIntent - } - override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean { - return shouldAnimateLaunch(isActivityIntent, false) + return activityStarterInternal.shouldAnimateLaunch(isActivityIntent) } - /** - * Encapsulates the activity logic for activity starter. - * - * Logic is duplicated in {@link CentralSurfacesImpl} - */ - private inner class ActivityStarterInternal { - /** Starts an activity after dismissing keyguard. */ - fun startActivityDismissingKeyguard( - intent: Intent, - onlyProvisioned: Boolean = false, - dismissShade: Boolean = false, - disallowEnterPictureInPictureWhileLaunching: Boolean = false, - callback: ActivityStarter.Callback? = null, - flags: Int = 0, - animationController: ActivityTransitionAnimator.Controller? = null, - userHandle: UserHandle? = null, - customMessage: String? = null, - ) { - val userHandle: UserHandle = userHandle ?: getActivityUserHandle(intent) - - if (onlyProvisioned && !deviceProvisionedController.isDeviceProvisioned) return - - val willLaunchResolverActivity: Boolean = - activityIntentHelper.wouldLaunchResolverActivity( - intent, - lockScreenUserManager.currentUserId - ) - - val animate = - animationController != null && - !willLaunchResolverActivity && - shouldAnimateLaunch(isActivityIntent = true) - val animController = - wrapAnimationControllerForShadeOrStatusBar( - animationController = animationController, - dismissShade = dismissShade, - isLaunchForActivity = true, - ) - - // If we animate, we will dismiss the shade only once the animation is done. This is - // taken care of by the StatusBarLaunchAnimationController. - val dismissShadeDirectly = dismissShade && animController == null - - val runnable = Runnable { - assistManagerLazy.get().hideAssist() - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - intent.addFlags(flags) - val result = intArrayOf(ActivityManager.START_CANCELED) - activityTransitionAnimator.startIntentWithAnimation( - animController, - animate, - intent.getPackage() - ) { adapter: RemoteAnimationAdapter? -> - val options = - ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter)) - - // We know that the intent of the caller is to dismiss the keyguard and - // this runnable is called right after the keyguard is solved, so we tell - // WM that we should dismiss it to avoid flickers when opening an activity - // that can also be shown over the keyguard. - options.setDismissKeyguardIfInsecure() - options.setDisallowEnterPictureInPictureWhileLaunching( - disallowEnterPictureInPictureWhileLaunching - ) - if (isInsecureCameraIntent(intent)) { - // Normally an activity will set it's requested rotation - // animation on its window. However when launching an activity - // causes the orientation to change this is too late. In these cases - // the default animation is used. This doesn't look good for - // the camera (as it rotates the camera contents out of sync - // with physical reality). So, we ask the WindowManager to - // force the cross fade animation if an orientation change - // happens to occur during the launch. - options.rotationAnimationHint = - WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS - } - if (Settings.Panel.ACTION_VOLUME == intent.action) { - // Settings Panel is implemented as activity(not a dialog), so - // underlying app is paused and may enter picture-in-picture mode - // as a result. - // So we need to disable picture-in-picture mode here - // if it is volume panel. - options.setDisallowEnterPictureInPictureWhileLaunching(true) - } - try { - result[0] = - ActivityTaskManager.getService() - .startActivityAsUser( - null, - context.basePackageName, - context.attributionTag, - intent, - intent.resolveTypeIfNeeded(context.contentResolver), - null, - null, - 0, - Intent.FLAG_ACTIVITY_NEW_TASK, - null, - options.toBundle(), - userHandle.identifier, - ) - } catch (e: RemoteException) { - Log.w(TAG, "Unable to start activity", e) - } - result[0] - } - callback?.onActivityStarted(result[0]) - } - val cancelRunnable = Runnable { - callback?.onActivityStarted(ActivityManager.START_CANCELED) - } - // Do not deferKeyguard when occluded because, when keyguard is occluded, - // we do not launch the activity until keyguard is done. - val occluded = (keyguardStateController.isShowing && keyguardStateController.isOccluded) - val deferred = !occluded - executeRunnableDismissingKeyguard( - runnable, - cancelRunnable, - dismissShadeDirectly, - willLaunchResolverActivity, - deferred, - animate, - customMessage, - ) - } - - /** - * Starts a pending intent after dismissing keyguard. - * - * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in - * the main thread). - */ - fun startPendingIntentDismissingKeyguard( - intent: PendingIntent, - intentSentUiThreadCallback: Runnable? = null, - associatedView: View? = null, - animationController: ActivityTransitionAnimator.Controller? = null, - showOverLockscreen: Boolean = false, - fillInIntent: Intent? = null, - extraOptions: Bundle? = null, - ) { - val animationController = - if (associatedView is ExpandableNotificationRow) { - centralSurfaces?.getAnimatorControllerFromNotification(associatedView) - } else animationController - - val willLaunchResolverActivity = - (intent.isActivity && - activityIntentHelper.wouldPendingLaunchResolverActivity( - intent, - lockScreenUserManager.currentUserId, - )) - - val actuallyShowOverLockscreen = - showOverLockscreen && - intent.isActivity && - activityIntentHelper.wouldPendingShowOverLockscreen( - intent, - lockScreenUserManager.currentUserId - ) - - val animate = - !willLaunchResolverActivity && - animationController != null && - shouldAnimateLaunch(intent.isActivity, actuallyShowOverLockscreen) - - // We wrap animationCallback with a StatusBarLaunchAnimatorController so - // that the shade is collapsed after the animation (or when it is cancelled, - // aborted, etc). - val statusBarController = - wrapAnimationControllerForShadeOrStatusBar( - animationController = animationController, - dismissShade = true, - isLaunchForActivity = intent.isActivity, - ) - val controller = - if (actuallyShowOverLockscreen) { - wrapAnimationControllerForLockscreen(statusBarController) - } else { - statusBarController - } - - // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we - // run the animation on the keyguard). The animation will take care of (instantly) - // collapsing the shade and hiding the keyguard once it is done. - val collapse = !animate - val runnable = Runnable { - try { - activityTransitionAnimator.startPendingIntentWithAnimation( - controller, - animate, - intent.creatorPackage, - actuallyShowOverLockscreen, - object : PendingIntentStarter { - override fun startPendingIntent( - animationAdapter: RemoteAnimationAdapter? - ): Int { - val options = - ActivityOptions( - CentralSurfaces.getActivityOptions( - displayId, - animationAdapter - ) - .apply { extraOptions?.let { putAll(it) } } - ) - // TODO b/221255671: restrict this to only be set for - // notifications - options.isEligibleForLegacyPermissionPrompt = true - options.setPendingIntentBackgroundActivityStartMode( - ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED - ) - return intent.sendAndReturnResult( - context, - 0, - fillInIntent, - null, - null, - null, - options.toBundle() - ) - } - }, - ) - } catch (e: PendingIntent.CanceledException) { - // the stack trace isn't very helpful here. - // Just log the exception message. - Log.w(TAG, "Sending intent failed: $e") - if (!collapse) { - // executeRunnableDismissingKeyguard did not collapse for us already. - shadeControllerLazy.get().collapseOnMainThread() - } - // TODO: Dismiss Keyguard. - } - if (intent.isActivity) { - assistManagerLazy.get().hideAssist() - // This activity could have started while the device is dreaming, in which case - // the dream would occlude the activity. In order to show the newly started - // activity, we wake from the dream. - keyguardUpdateMonitor.awakenFromDream() - } - intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) } - } - - if (!actuallyShowOverLockscreen) { - postOnUiThread(delay = 0) { - executeRunnableDismissingKeyguard( - runnable = runnable, - afterKeyguardGone = willLaunchResolverActivity, - dismissShade = collapse, - willAnimateOnKeyguard = animate, - ) - } - } else { - postOnUiThread(delay = 0, runnable) - } - } - - /** Starts an Activity. */ - fun startActivity( - intent: Intent, - dismissShade: Boolean = false, - animationController: ActivityTransitionAnimator.Controller? = null, - showOverLockscreenWhenLocked: Boolean = false, - userHandle: UserHandle? = null, - ) { - val userHandle = userHandle ?: getActivityUserHandle(intent) - // Make sure that we dismiss the keyguard if it is directly dismissible or when we don't - // want to show the activity above it. - if (keyguardStateController.isUnlocked || !showOverLockscreenWhenLocked) { - startActivityDismissingKeyguard( - intent = intent, - onlyProvisioned = false, - dismissShade = dismissShade, - disallowEnterPictureInPictureWhileLaunching = false, - callback = null, - flags = 0, - animationController = animationController, - userHandle = userHandle, - ) - return - } - - val animate = - animationController != null && - shouldAnimateLaunch( - /* isActivityIntent= */ true, - showOverLockscreenWhenLocked - ) == true - - var controller: ActivityTransitionAnimator.Controller? = null - if (animate) { - // Wrap the animation controller to dismiss the shade and set - // mIsLaunchingActivityOverLockscreen during the animation. - val delegate = - wrapAnimationControllerForShadeOrStatusBar( - animationController = animationController, - dismissShade = dismissShade, - isLaunchForActivity = true, - ) - controller = wrapAnimationControllerForLockscreen(delegate) - } else if (dismissShade) { - // The animation will take care of dismissing the shade at the end of the animation. - // If we don't animate, collapse it directly. - shadeControllerLazy.get().cancelExpansionAndCollapseShade() - } - - // We should exit the dream to prevent the activity from starting below the - // dream. - if (keyguardUpdateMonitor.isDreaming) { - centralSurfaces?.awakenDreams() - } - - activityTransitionAnimator.startIntentWithAnimation( - controller, - animate, - intent.getPackage(), - showOverLockscreenWhenLocked - ) { adapter: RemoteAnimationAdapter? -> - TaskStackBuilder.create(context) - .addNextIntent(intent) - .startActivities( - CentralSurfaces.getActivityOptions(displayId, adapter), - userHandle - ) - } - } - - /** Executes an action after dismissing keyguard. */ - fun dismissKeyguardThenExecute( - action: OnDismissAction, - cancel: Runnable? = null, - afterKeyguardGone: Boolean = false, - customMessage: String? = null, - ) { - if ( - !action.willRunAnimationOnKeyguard() && - wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP && - keyguardStateController.canDismissLockScreen() && - !statusBarStateController.leaveOpenOnKeyguardHide() && - dozeServiceHostLazy.get().isPulsing - ) { - // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a - // pulse. - // TODO: Factor this transition out of BiometricUnlockController. - biometricUnlockControllerLazy - .get() - .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) - } - if (keyguardStateController.isShowing) { - statusBarKeyguardViewManagerLazy - .get() - .dismissWithAction(action, cancel, afterKeyguardGone, customMessage) - } else { - // If the keyguard isn't showing but the device is dreaming, we should exit the - // dream. - if (keyguardUpdateMonitor.isDreaming) { - centralSurfaces?.awakenDreams() - } - action.onDismiss() - } - } - - /** Executes an action after dismissing keyguard. */ - fun executeRunnableDismissingKeyguard( - runnable: Runnable? = null, - cancelAction: Runnable? = null, - dismissShade: Boolean = false, - afterKeyguardGone: Boolean = false, - deferred: Boolean = false, - willAnimateOnKeyguard: Boolean = false, - customMessage: String? = null, - ) { - val onDismissAction: OnDismissAction = - object : OnDismissAction { - override fun onDismiss(): Boolean { - if (runnable != null) { - if ( - keyguardStateController.isShowing && - keyguardStateController.isOccluded - ) { - statusBarKeyguardViewManagerLazy - .get() - .addAfterKeyguardGoneRunnable(runnable) - } else { - mainExecutor.execute(runnable) - } - } - if (dismissShade) { - shadeControllerLazy.get().collapseShadeForActivityStart() - } - return deferred - } - - override fun willRunAnimationOnKeyguard(): Boolean { - return willAnimateOnKeyguard - } - } - dismissKeyguardThenExecute( - onDismissAction, - cancelAction, - afterKeyguardGone, - customMessage, - ) - } - - /** - * Return a [ActivityTransitionAnimator.Controller] wrapping `animationController` so that: - * - if it launches in the notification shade window and `dismissShade` is true, then the - * shade will be instantly dismissed at the end of the animation. - * - if it launches in status bar window, it will make the status bar window match the - * device size during the animation (that way, the animation won't be clipped by the - * status bar size). - * - * @param animationController the controller that is wrapped and will drive the main - * animation. - * @param dismissShade whether the notification shade will be dismissed at the end of the - * animation. This is ignored if `animationController` is not animating in the shade - * window. - * @param isLaunchForActivity whether the launch is for an activity. - */ - private fun wrapAnimationControllerForShadeOrStatusBar( - animationController: ActivityTransitionAnimator.Controller?, - dismissShade: Boolean, - isLaunchForActivity: Boolean, - ): ActivityTransitionAnimator.Controller? { - if (animationController == null) { - return null - } - val rootView = animationController.transitionContainer.rootView - val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> = - statusBarWindowController.wrapAnimationControllerIfInStatusBar( - rootView, - animationController - ) - if (controllerFromStatusBar.isPresent) { - return controllerFromStatusBar.get() - } - - centralSurfaces?.let { - // If the view is not in the status bar, then we are animating a view in the shade. - // We have to make sure that we collapse it when the animation ends or is cancelled. - if (dismissShade) { - return StatusBarTransitionAnimatorController( - animationController, - shadeAnimationInteractor, - shadeControllerLazy.get(), - notifShadeWindowControllerLazy.get(), - commandQueue, - displayId, - isLaunchForActivity - ) - } - } - - return animationController - } - - /** - * Wraps an animation controller so that if an activity would be launched on top of the - * lockscreen, the correct flags are set for it to be occluded. - */ - private fun wrapAnimationControllerForLockscreen( - animationController: ActivityTransitionAnimator.Controller? - ): ActivityTransitionAnimator.Controller? { - return animationController?.let { - object : DelegateTransitionAnimatorController(it) { - override fun onIntentStarted(willAnimate: Boolean) { - delegate.onIntentStarted(willAnimate) - if (willAnimate) { - centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) - } - } - - override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { - super.onTransitionAnimationStart(isExpandingFullyAbove) - - // Double check that the keyguard is still showing and not going - // away, but if so set the keyguard occluded. Typically, WM will let - // KeyguardViewMediator know directly, but we're overriding that to - // play the custom launch animation, so we need to take care of that - // here. The unocclude animation is not overridden, so WM will call - // KeyguardViewMediator's unocclude animation runner when the - // activity is exited. - if ( - keyguardStateController.isShowing && - !keyguardStateController.isKeyguardGoingAway - ) { - Log.d(TAG, "Setting occluded = true in #startActivity.") - keyguardViewMediatorLazy - .get() - .setOccluded(true /* isOccluded */, true /* animate */) - } - } - - override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { - // Set mIsLaunchingActivityOverLockscreen to false before actually - // finishing the animation so that we can assume that - // mIsLaunchingActivityOverLockscreen being true means that we will - // collapse the shade (or at least run the post collapse runnables) - // later on. - centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) - delegate.onTransitionAnimationEnd(isExpandingFullyAbove) - } - - override fun onTransitionAnimationCancelled( - newKeyguardOccludedState: Boolean? - ) { - if (newKeyguardOccludedState != null) { - keyguardViewMediatorLazy - .get() - .setOccluded(newKeyguardOccludedState, false /* animate */) - } - - // Set mIsLaunchingActivityOverLockscreen to false before actually - // finishing the animation so that we can assume that - // mIsLaunchingActivityOverLockscreen being true means that we will - // collapse the shade (or at least run the // post collapse - // runnables) later on. - centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) - delegate.onTransitionAnimationCancelled(newKeyguardOccludedState) - } - } - } - } - - /** Retrieves the current user handle to start the Activity. */ - private fun getActivityUserHandle(intent: Intent): UserHandle { - val packages: Array<String> = - context.resources.getStringArray(R.array.system_ui_packages) - for (pkg in packages) { - val componentName = intent.component ?: break - if (pkg == componentName.packageName) { - return UserHandle(UserHandle.myUserId()) - } - } - return userTracker.userHandle - } + private fun postOnUiThread(delay: Int = 0, runnable: Runnable) { + mainExecutor.executeDelayed(runnable, delay.toLong()) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt new file mode 100644 index 000000000000..e8443982d560 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.app.PendingIntent +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle +import android.view.View +import com.android.systemui.ActivityIntentHelper +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.plugins.ActivityStarter + +interface ActivityStarterInternal { + /** + * Starts a pending intent after dismissing keyguard. + * + * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in the + * main thread). + */ + fun startPendingIntentDismissingKeyguard( + intent: PendingIntent, + intentSentUiThreadCallback: Runnable? = null, + associatedView: View? = null, + animationController: ActivityTransitionAnimator.Controller? = null, + showOverLockscreen: Boolean = false, + fillInIntent: Intent? = null, + extraOptions: Bundle? = null, + ) + + /** Starts an activity after dismissing keyguard. */ + fun startActivityDismissingKeyguard( + intent: Intent, + dismissShade: Boolean, + onlyProvisioned: Boolean = false, + callback: ActivityStarter.Callback? = null, + flags: Int = 0, + animationController: ActivityTransitionAnimator.Controller? = null, + customMessage: String? = null, + disallowEnterPictureInPictureWhileLaunching: Boolean = false, + userHandle: UserHandle? = null, + ) + + /** Starts an Activity. */ + fun startActivity( + intent: Intent, + dismissShade: Boolean, + animationController: ActivityTransitionAnimator.Controller?, + showOverLockscreenWhenLocked: Boolean, + userHandle: UserHandle? = null, + ) + + /** Executes an action after dismissing keyguard. */ + fun dismissKeyguardThenExecute( + action: ActivityStarter.OnDismissAction, + cancel: Runnable?, + afterKeyguardGone: Boolean, + customMessage: String? = null, + ) + + /** Executes an action after dismissing keyguard. */ + fun executeRunnableDismissingKeyguard( + runnable: Runnable?, + cancelAction: Runnable? = null, + dismissShade: Boolean = false, + afterKeyguardGone: Boolean = false, + deferred: Boolean = false, + willAnimateOnKeyguard: Boolean = false, + customMessage: String? = null, + ) + + /** Whether we should animate an activity launch. */ + fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt new file mode 100644 index 000000000000..c101755bcf38 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.app.PendingIntent +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle +import android.view.View +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.ActivityStarter +import javax.inject.Inject + +/** + * Encapsulates the activity logic for activity starter when flexiglass is enabled. + * + * TODO: b/308819693 + */ +@SysUISingleton +class ActivityStarterInternalImpl @Inject constructor() : ActivityStarterInternal { + override fun startPendingIntentDismissingKeyguard( + intent: PendingIntent, + intentSentUiThreadCallback: Runnable?, + associatedView: View?, + animationController: ActivityTransitionAnimator.Controller?, + showOverLockscreen: Boolean, + fillInIntent: Intent?, + extraOptions: Bundle? + ) { + TODO("Not yet implemented b/308819693") + } + + override fun startActivityDismissingKeyguard( + intent: Intent, + dismissShade: Boolean, + onlyProvisioned: Boolean, + callback: ActivityStarter.Callback?, + flags: Int, + animationController: ActivityTransitionAnimator.Controller?, + customMessage: String?, + disallowEnterPictureInPictureWhileLaunching: Boolean, + userHandle: UserHandle? + ) { + TODO("Not yet implemented b/308819693") + } + + override fun startActivity( + intent: Intent, + dismissShade: Boolean, + animationController: ActivityTransitionAnimator.Controller?, + showOverLockscreenWhenLocked: Boolean, + userHandle: UserHandle? + ) { + TODO("Not yet implemented b/308819693") + } + + override fun dismissKeyguardThenExecute( + action: ActivityStarter.OnDismissAction, + cancel: Runnable?, + afterKeyguardGone: Boolean, + customMessage: String? + ) { + TODO("Not yet implemented b/308819693") + } + + override fun executeRunnableDismissingKeyguard( + runnable: Runnable?, + cancelAction: Runnable?, + dismissShade: Boolean, + afterKeyguardGone: Boolean, + deferred: Boolean, + willAnimateOnKeyguard: Boolean, + customMessage: String? + ) { + TODO("Not yet implemented b/308819693") + } + + override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean { + TODO("Not yet implemented b/308819693") + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 8b7b348ede76..79e6a0aa9c8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -67,6 +67,8 @@ import com.android.systemui.util.time.SystemClock; import dagger.Lazy; +import kotlinx.coroutines.ExperimentalCoroutinesApi; + import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -77,8 +79,6 @@ import java.util.Set; import javax.inject.Inject; -import kotlinx.coroutines.ExperimentalCoroutinesApi; - /** * Controller which coordinates all the biometric unlocking actions with the UI. */ @@ -183,6 +183,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private final SystemClock mSystemClock; private final boolean mOrderUnlockAndWake; private final Lazy<SelectedUserInteractor> mSelectedUserInteractor; + private final KeyguardTransitionInteractor mKeyguardTransitionInteractor; private long mLastFpFailureUptimeMillis; private int mNumConsecutiveFpFailures; @@ -323,6 +324,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mOrderUnlockAndWake = resources.getBoolean( com.android.internal.R.bool.config_orderUnlockAndWake); mSelectedUserInteractor = selectedUserInteractor; + mKeyguardTransitionInteractor = keyguardTransitionInteractor; javaAdapter.alwaysCollectFlow( keyguardTransitionInteractor.getStartedKeyguardTransitionStep(), this::consumeTransitionStepOnStartedKeyguardState); @@ -665,7 +667,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp } if (isKeyguardShowing) { if ((mKeyguardViewController.primaryBouncerIsOrWillBeShowing() - || mKeyguardBypassController.getAltBouncerShowing()) && unlockingAllowed) { + || mKeyguardTransitionInteractor.getCurrentState() + == KeyguardState.ALTERNATE_BOUNCER) && unlockingAllowed) { return MODE_DISMISS_BOUNCER; } else if (unlockingAllowed && bypass) { return MODE_UNLOCK_COLLAPSING; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 1d6b744a7bf0..cb3c03ebae4d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -164,7 +164,6 @@ import com.android.systemui.qs.QSPanelController; import com.android.systemui.res.R; import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor; import com.android.systemui.scene.shared.flag.SceneContainerFlag; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.scrim.ScrimView; import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.brightness.BrightnessSliderController; @@ -592,9 +591,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener = (extractor, which) -> updateTheme(); - - private final SceneContainerFlags mSceneContainerFlags; - private final BrightnessMirrorShowingInteractor mBrightnessMirrorShowingInteractor; /** @@ -708,7 +704,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { UserTracker userTracker, Provider<FingerprintManager> fingerprintManager, ActivityStarter activityStarter, - SceneContainerFlags sceneContainerFlags, BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor ) { mContext = context; @@ -804,7 +799,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mUserTracker = userTracker; mFingerprintManager = fingerprintManager; mActivityStarter = activityStarter; - mSceneContainerFlags = sceneContainerFlags; mBrightnessMirrorShowingInteractor = brightnessMirrorShowingInteractor; mLockscreenShadeTransitionController = lockscreenShadeTransitionController; @@ -1088,7 +1082,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mJavaAdapter.alwaysCollectFlow( mCommunalInteractor.isIdleOnCommunal(), mIdleOnCommunalConsumer); - if (mSceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { mJavaAdapter.alwaysCollectFlow( mBrightnessMirrorShowingInteractor.isShowing(), this::setBrightnessMirrorShowing @@ -1277,7 +1271,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // Set up the quick settings tile panel final View container = getNotificationShadeWindowView().findViewById(R.id.qs_frame); - if (container != null && !mSceneContainerFlags.isEnabled()) { + if (container != null && !SceneContainerFlag.isEnabled()) { FragmentHostManager fragmentHostManager = mFragmentService.getFragmentHostManager(container); ExtensionFragmentListener.attachExtensonToFragment( @@ -1545,8 +1539,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mShadeSurface, mShadeExpansionStateManager, mBiometricUnlockController, - mStackScroller, - mKeyguardBypassController); + mStackScroller); mKeyguardStateController.addCallback(mKeyguardStateControllerCallback); mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 3f200d578261..0ddf37db6078 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -91,7 +91,8 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements StateFlowKt.MutableStateFlow(null); private final MutableStateFlow<Set<HeadsUpRowRepository>> mHeadsUpNotificationRows = StateFlowKt.MutableStateFlow(new HashSet<>()); - private final MutableStateFlow<Boolean> mHeadsUpGoingAway = StateFlowKt.MutableStateFlow(false); + private final MutableStateFlow<Boolean> mHeadsUpAnimatingAway = + StateFlowKt.MutableStateFlow(false); private boolean mReleaseOnExpandFinish; private boolean mTrackingHeadsUp; private final HashSet<String> mSwipedOutKeys = new HashSet<>(); @@ -184,7 +185,7 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements // Public methods: /** - * Add a listener to receive callbacks onHeadsUpGoingAway + * Add a listener to receive callbacks {@link #setHeadsUpAnimatingAway(boolean)} */ @Override public void addHeadsUpPhoneListener(OnHeadsUpPhoneListenerChange listener) { @@ -264,7 +265,7 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements if (isExpanded != mIsExpanded) { mIsExpanded = isExpanded; if (isExpanded) { - mHeadsUpGoingAway.setValue(false); + mHeadsUpAnimatingAway.setValue(false); } } } @@ -274,20 +275,15 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements * animating out. This is used to keep the touchable regions in a reasonable state. */ @Override - public void setHeadsUpGoingAway(boolean headsUpGoingAway) { - if (headsUpGoingAway != mHeadsUpGoingAway.getValue()) { + public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) { + if (headsUpAnimatingAway != mHeadsUpAnimatingAway.getValue()) { for (OnHeadsUpPhoneListenerChange listener : mHeadsUpPhoneListeners) { - listener.onHeadsUpGoingAwayStateChanged(headsUpGoingAway); + listener.onHeadsUpAnimatingAwayStateChanged(headsUpAnimatingAway); } - mHeadsUpGoingAway.setValue(headsUpGoingAway); + mHeadsUpAnimatingAway.setValue(headsUpAnimatingAway); } } - @Override - public boolean isHeadsUpGoingAway() { - return mHeadsUpGoingAway.getValue(); - } - /** * Notifies that a remote input textbox in notification gets active or inactive. * @@ -504,8 +500,13 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @Override @NonNull - public Flow<Boolean> getHeadsUpAnimatingAway() { - return mHeadsUpGoingAway; + public Flow<Boolean> isHeadsUpAnimatingAway() { + return mHeadsUpAnimatingAway; + } + + @Override + public boolean isHeadsUpAnimatingAwayValue() { + return mHeadsUpAnimatingAway.getValue(); } /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index a3d316b611a7..a8941bb182ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -17,8 +17,8 @@ package com.android.systemui.statusbar.phone import android.annotation.IntDef -import android.content.Context import android.content.pm.PackageManager +import android.content.res.Resources import android.hardware.biometrics.BiometricSourceType import android.provider.Settings import androidx.annotation.VisibleForTesting @@ -26,7 +26,10 @@ import com.android.app.tracing.ListenersTracing.forEachTraced import com.android.systemui.Dumpable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.res.R import com.android.systemui.shade.data.repository.ShadeRepository @@ -46,12 +49,20 @@ import java.io.PrintWriter import javax.inject.Inject @SysUISingleton -open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassController { +class KeyguardBypassController @Inject constructor( + @Main resources: Resources, + packageManager: PackageManager, + @Application applicationScope: CoroutineScope, + tunerService: TunerService, + private val statusBarStateController: StatusBarStateController, + lockscreenUserManager: NotificationLockscreenUserManager, + private val keyguardStateController: KeyguardStateController, + private val shadeRepository: ShadeRepository, + devicePostureController: DevicePostureController, + private val keyguardTransitionInteractor: KeyguardTransitionInteractor, + dumpManager: DumpManager +) : Dumpable, StackScrollAlgorithm.BypassController { - private val mKeyguardStateController: KeyguardStateController - private val statusBarStateController: StatusBarStateController - private val shadeRepository: ShadeRepository - private val devicePostureController: DevicePostureController @BypassOverride private val bypassOverride: Int private var hasFaceFeature: Boolean @DevicePostureInt private val configFaceAuthSupportedPosture: Int @@ -99,7 +110,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr FACE_UNLOCK_BYPASS_NEVER -> false else -> field } - return enabled && mKeyguardStateController.isFaceEnrolledAndEnabled && + return enabled && keyguardStateController.isFaceEnrolledAndEnabled && isPostureAllowedForFaceAuth() } private set(value) { @@ -108,70 +119,44 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } var bouncerShowing: Boolean = false - var altBouncerShowing: Boolean = false var launchingAffordance: Boolean = false var qsExpanded = false - @Inject - constructor( - context: Context, - @Application applicationScope: CoroutineScope, - tunerService: TunerService, - statusBarStateController: StatusBarStateController, - lockscreenUserManager: NotificationLockscreenUserManager, - keyguardStateController: KeyguardStateController, - shadeRepository: ShadeRepository, - devicePostureController: DevicePostureController, - dumpManager: DumpManager - ) { - this.mKeyguardStateController = keyguardStateController - this.statusBarStateController = statusBarStateController - this.shadeRepository = shadeRepository - this.devicePostureController = devicePostureController - - bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override) + init { + bypassOverride = resources.getInteger(R.integer.config_face_unlock_bypass_override) configFaceAuthSupportedPosture = - context.resources.getInteger(R.integer.config_face_auth_supported_posture) - - hasFaceFeature = context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE) - if (!hasFaceFeature) { - return - } - - - if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) { - devicePostureController.addCallback { posture -> - if (postureState != posture) { - postureState = posture - notifyListeners() - } - } - } - - dumpManager.registerNormalDumpable("KeyguardBypassController", this) - statusBarStateController.addCallback(object : StatusBarStateController.StateListener { - override fun onStateChanged(newState: Int) { - if (newState != StatusBarState.KEYGUARD) { - pendingUnlock = null + resources.getInteger(R.integer.config_face_auth_supported_posture) + hasFaceFeature = packageManager.hasSystemFeature(PackageManager.FEATURE_FACE) + if (hasFaceFeature) { + if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) { + devicePostureController.addCallback { posture -> + if (postureState != posture) { + postureState = posture + notifyListeners() + } } } - }) - - listenForQsExpandedChange(applicationScope) - - val dismissByDefault = if (context.resources.getBoolean( - com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0 - - tunerService.addTunable({ key, _ -> - bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 - }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD) - - lockscreenUserManager.addUserChangedListener( - object : NotificationLockscreenUserManager.UserChangedListener { - override fun onUserChanged(userId: Int) { - pendingUnlock = null + dumpManager.registerNormalDumpable("KeyguardBypassController", this) + statusBarStateController.addCallback(object : StatusBarStateController.StateListener { + override fun onStateChanged(newState: Int) { + if (newState != StatusBarState.KEYGUARD) { + pendingUnlock = null + } } }) + listenForQsExpandedChange(applicationScope) + val dismissByDefault = if (resources.getBoolean( + com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0 + tunerService.addTunable({ key, _ -> + bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 + }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD) + lockscreenUserManager.addUserChangedListener( + object : NotificationLockscreenUserManager.UserChangedListener { + override fun onUserChanged(userId: Int) { + pendingUnlock = null + } + }) + } } @VisibleForTesting @@ -228,7 +213,8 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr if (bypassEnabled) { return when { bouncerShowing -> true - altBouncerShowing -> true + keyguardTransitionInteractor.getCurrentState() == KeyguardState.ALTERNATE_BOUNCER -> + true statusBarStateController.state != StatusBarState.KEYGUARD -> false launchingAffordance -> false isPulseExpanding || qsExpanded -> false @@ -260,7 +246,8 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr pw.println(" bypassEnabled: $bypassEnabled") pw.println(" canBypass: ${canBypass()}") pw.println(" bouncerShowing: $bouncerShowing") - pw.println(" altBouncerShowing: $altBouncerShowing") + pw.println(" altBouncerShowing:" + + " ${keyguardTransitionInteractor.getCurrentState() == KeyguardState.ALTERNATE_BOUNCER}") pw.println(" isPulseExpanding: $isPulseExpanding") pw.println(" launchingAffordance: $launchingAffordance") pw.println(" qSExpanded: $qsExpanded") @@ -273,7 +260,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr val start = listeners.isEmpty() listeners.add(listener) if (start) { - mKeyguardStateController.addCallback(faceAuthEnabledChangedCallback) + keyguardStateController.addCallback(faceAuthEnabledChangedCallback) } } @@ -284,7 +271,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr fun unregisterOnBypassStateChangedListener(listener: OnBypassStateChangedListener) { listeners.remove(listener) if (listeners.isEmpty()) { - mKeyguardStateController.removeCallback(faceAuthEnabledChangedCallback) + keyguardStateController.removeCallback(faceAuthEnabledChangedCallback) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt new file mode 100644 index 000000000000..ebaeb39efe31 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt @@ -0,0 +1,639 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.app.ActivityManager +import android.app.ActivityOptions +import android.app.ActivityTaskManager +import android.app.PendingIntent +import android.app.TaskStackBuilder +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.RemoteException +import android.os.UserHandle +import android.provider.Settings +import android.util.Log +import android.view.RemoteAnimationAdapter +import android.view.View +import android.view.WindowManager +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.ActivityIntentHelper +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.animation.DelegateTransitionAnimatorController +import com.android.systemui.assist.AssistManager +import com.android.systemui.camera.CameraIntents +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.DisplayId +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.keyguard.KeyguardViewMediator +import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.res.R +import com.android.systemui.settings.UserTracker +import com.android.systemui.shade.ShadeController +import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor +import com.android.systemui.statusbar.CommandQueue +import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.NotificationShadeWindowController +import com.android.systemui.statusbar.SysuiStatusBarStateController +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.statusbar.window.StatusBarWindowController +import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.kotlin.getOrNull +import dagger.Lazy +import java.util.Optional +import javax.inject.Inject + +/** Encapsulates the activity logic for activity starter. */ +@SysUISingleton +class LegacyActivityStarterInternalImpl +@Inject +constructor( + private val centralSurfacesOptLazy: Lazy<Optional<CentralSurfaces>>, + private val keyguardStateController: KeyguardStateController, + private val statusBarStateController: SysuiStatusBarStateController, + private val assistManagerLazy: Lazy<AssistManager>, + private val dozeServiceHostLazy: Lazy<DozeServiceHost>, + private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>, + private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>, + private val shadeControllerLazy: Lazy<ShadeController>, + private val commandQueue: CommandQueue, + private val shadeAnimationInteractor: ShadeAnimationInteractor, + private val statusBarKeyguardViewManagerLazy: Lazy<StatusBarKeyguardViewManager>, + private val notifShadeWindowControllerLazy: Lazy<NotificationShadeWindowController>, + private val activityTransitionAnimator: ActivityTransitionAnimator, + private val context: Context, + @DisplayId private val displayId: Int, + private val lockScreenUserManager: NotificationLockscreenUserManager, + private val statusBarWindowController: StatusBarWindowController, + private val wakefulnessLifecycle: WakefulnessLifecycle, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val deviceProvisionedController: DeviceProvisionedController, + private val userTracker: UserTracker, + private val activityIntentHelper: ActivityIntentHelper, + @Main private val mainExecutor: DelayableExecutor, +) : ActivityStarterInternal { + private val centralSurfaces: CentralSurfaces? + get() = centralSurfacesOptLazy.get().getOrNull() + + override fun startActivityDismissingKeyguard( + intent: Intent, + dismissShade: Boolean, + onlyProvisioned: Boolean, + callback: ActivityStarter.Callback?, + flags: Int, + animationController: ActivityTransitionAnimator.Controller?, + customMessage: String?, + disallowEnterPictureInPictureWhileLaunching: Boolean, + userHandle: UserHandle?, + ) { + val userHandle: UserHandle = userHandle ?: getActivityUserHandle(intent) + + if (onlyProvisioned && !deviceProvisionedController.isDeviceProvisioned) return + + val willLaunchResolverActivity: Boolean = + activityIntentHelper.wouldLaunchResolverActivity( + intent, + lockScreenUserManager.currentUserId + ) + + val animate = + animationController != null && + !willLaunchResolverActivity && + shouldAnimateLaunch(isActivityIntent = true) + val animController = + wrapAnimationControllerForShadeOrStatusBar( + animationController = animationController, + dismissShade = dismissShade, + isLaunchForActivity = true, + ) + + // If we animate, we will dismiss the shade only once the animation is done. This is + // taken care of by the StatusBarLaunchAnimationController. + val dismissShadeDirectly = dismissShade && animController == null + + val runnable = Runnable { + assistManagerLazy.get().hideAssist() + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + intent.addFlags(flags) + val result = intArrayOf(ActivityManager.START_CANCELED) + activityTransitionAnimator.startIntentWithAnimation( + animController, + animate, + intent.getPackage() + ) { adapter: RemoteAnimationAdapter? -> + val options = + ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter)) + + // We know that the intent of the caller is to dismiss the keyguard and + // this runnable is called right after the keyguard is solved, so we tell + // WM that we should dismiss it to avoid flickers when opening an activity + // that can also be shown over the keyguard. + options.setDismissKeyguardIfInsecure() + options.setDisallowEnterPictureInPictureWhileLaunching( + disallowEnterPictureInPictureWhileLaunching + ) + if (CameraIntents.isInsecureCameraIntent(intent)) { + // Normally an activity will set it's requested rotation + // animation on its window. However when launching an activity + // causes the orientation to change this is too late. In these cases + // the default animation is used. This doesn't look good for + // the camera (as it rotates the camera contents out of sync + // with physical reality). So, we ask the WindowManager to + // force the cross fade animation if an orientation change + // happens to occur during the launch. + options.rotationAnimationHint = + WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS + } + if (Settings.Panel.ACTION_VOLUME == intent.action) { + // Settings Panel is implemented as activity(not a dialog), so + // underlying app is paused and may enter picture-in-picture mode + // as a result. + // So we need to disable picture-in-picture mode here + // if it is volume panel. + options.setDisallowEnterPictureInPictureWhileLaunching(true) + } + try { + result[0] = + ActivityTaskManager.getService() + .startActivityAsUser( + null, + context.basePackageName, + context.attributionTag, + intent, + intent.resolveTypeIfNeeded(context.contentResolver), + null, + null, + 0, + Intent.FLAG_ACTIVITY_NEW_TASK, + null, + options.toBundle(), + userHandle.identifier, + ) + } catch (e: RemoteException) { + Log.w(TAG, "Unable to start activity", e) + } + result[0] + } + callback?.onActivityStarted(result[0]) + } + val cancelRunnable = Runnable { + callback?.onActivityStarted(ActivityManager.START_CANCELED) + } + // Do not deferKeyguard when occluded because, when keyguard is occluded, + // we do not launch the activity until keyguard is done. + val occluded = (keyguardStateController.isShowing && keyguardStateController.isOccluded) + val deferred = !occluded + executeRunnableDismissingKeyguard( + runnable, + cancelRunnable, + dismissShadeDirectly, + willLaunchResolverActivity, + deferred, + animate, + customMessage, + ) + } + + override fun startPendingIntentDismissingKeyguard( + intent: PendingIntent, + intentSentUiThreadCallback: Runnable?, + associatedView: View?, + animationController: ActivityTransitionAnimator.Controller?, + showOverLockscreen: Boolean, + fillInIntent: Intent?, + extraOptions: Bundle?, + ) { + val animationController = + if (associatedView is ExpandableNotificationRow) { + centralSurfaces?.getAnimatorControllerFromNotification(associatedView) + } else animationController + + val willLaunchResolverActivity = + (intent.isActivity && + activityIntentHelper.wouldPendingLaunchResolverActivity( + intent, + lockScreenUserManager.currentUserId, + )) + + val actuallyShowOverLockscreen = + showOverLockscreen && + intent.isActivity && + activityIntentHelper.wouldPendingShowOverLockscreen( + intent, + lockScreenUserManager.currentUserId + ) + + val animate = + !willLaunchResolverActivity && + animationController != null && + shouldAnimateLaunch(intent.isActivity, actuallyShowOverLockscreen) + + // We wrap animationCallback with a StatusBarLaunchAnimatorController so + // that the shade is collapsed after the animation (or when it is cancelled, + // aborted, etc). + val statusBarController = + wrapAnimationControllerForShadeOrStatusBar( + animationController = animationController, + dismissShade = true, + isLaunchForActivity = intent.isActivity, + ) + val controller = + if (actuallyShowOverLockscreen) { + wrapAnimationControllerForLockscreen(statusBarController) + } else { + statusBarController + } + + // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we + // run the animation on the keyguard). The animation will take care of (instantly) + // collapsing the shade and hiding the keyguard once it is done. + val collapse = !animate + val runnable = Runnable { + try { + activityTransitionAnimator.startPendingIntentWithAnimation( + controller, + animate, + intent.creatorPackage, + actuallyShowOverLockscreen, + object : ActivityTransitionAnimator.PendingIntentStarter { + override fun startPendingIntent( + animationAdapter: RemoteAnimationAdapter? + ): Int { + val options = + ActivityOptions( + CentralSurfaces.getActivityOptions(displayId, animationAdapter) + .apply { extraOptions?.let { putAll(it) } } + ) + // TODO b/221255671: restrict this to only be set for + // notifications + options.isEligibleForLegacyPermissionPrompt = true + options.setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + ) + return intent.sendAndReturnResult( + context, + 0, + fillInIntent, + null, + null, + null, + options.toBundle() + ) + } + }, + ) + } catch (e: PendingIntent.CanceledException) { + // the stack trace isn't very helpful here. + // Just log the exception message. + Log.w(TAG, "Sending intent failed: $e") + if (!collapse) { + // executeRunnableDismissingKeyguard did not collapse for us already. + shadeControllerLazy.get().collapseOnMainThread() + } + // TODO: Dismiss Keyguard. + } + if (intent.isActivity) { + assistManagerLazy.get().hideAssist() + // This activity could have started while the device is dreaming, in which case + // the dream would occlude the activity. In order to show the newly started + // activity, we wake from the dream. + keyguardUpdateMonitor.awakenFromDream() + } + intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) } + } + + if (!actuallyShowOverLockscreen) { + postOnUiThread(delay = 0) { + executeRunnableDismissingKeyguard( + runnable = runnable, + afterKeyguardGone = willLaunchResolverActivity, + dismissShade = collapse, + willAnimateOnKeyguard = animate, + ) + } + } else { + postOnUiThread(delay = 0, runnable) + } + } + + override fun startActivity( + intent: Intent, + dismissShade: Boolean, + animationController: ActivityTransitionAnimator.Controller?, + showOverLockscreenWhenLocked: Boolean, + userHandle: UserHandle?, + ) { + val userHandle = userHandle ?: getActivityUserHandle(intent) + // Make sure that we dismiss the keyguard if it is directly dismissible or when we don't + // want to show the activity above it. + if (keyguardStateController.isUnlocked || !showOverLockscreenWhenLocked) { + startActivityDismissingKeyguard( + intent = intent, + onlyProvisioned = false, + dismissShade = dismissShade, + disallowEnterPictureInPictureWhileLaunching = false, + callback = null, + flags = 0, + animationController = animationController, + userHandle = userHandle, + ) + return + } + + val animate = + animationController != null && + shouldAnimateLaunch(/* isActivityIntent= */ true, showOverLockscreenWhenLocked) + + var controller: ActivityTransitionAnimator.Controller? = null + if (animate) { + // Wrap the animation controller to dismiss the shade and set + // mIsLaunchingActivityOverLockscreen during the animation. + val delegate = + wrapAnimationControllerForShadeOrStatusBar( + animationController = animationController, + dismissShade = dismissShade, + isLaunchForActivity = true, + ) + controller = wrapAnimationControllerForLockscreen(delegate) + } else if (dismissShade) { + // The animation will take care of dismissing the shade at the end of the animation. + // If we don't animate, collapse it directly. + shadeControllerLazy.get().cancelExpansionAndCollapseShade() + } + + // We should exit the dream to prevent the activity from starting below the + // dream. + if (keyguardUpdateMonitor.isDreaming) { + centralSurfaces?.awakenDreams() + } + + activityTransitionAnimator.startIntentWithAnimation( + controller, + animate, + intent.getPackage(), + showOverLockscreenWhenLocked + ) { adapter: RemoteAnimationAdapter? -> + TaskStackBuilder.create(context) + .addNextIntent(intent) + .startActivities(CentralSurfaces.getActivityOptions(displayId, adapter), userHandle) + } + } + + override fun dismissKeyguardThenExecute( + action: ActivityStarter.OnDismissAction, + cancel: Runnable?, + afterKeyguardGone: Boolean, + customMessage: String?, + ) { + if ( + !action.willRunAnimationOnKeyguard() && + wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP && + keyguardStateController.canDismissLockScreen() && + !statusBarStateController.leaveOpenOnKeyguardHide() && + dozeServiceHostLazy.get().isPulsing + ) { + // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a + // pulse. + // TODO: Factor this transition out of BiometricUnlockController. + biometricUnlockControllerLazy + .get() + .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) + } + if (keyguardStateController.isShowing) { + statusBarKeyguardViewManagerLazy + .get() + .dismissWithAction(action, cancel, afterKeyguardGone, customMessage) + } else { + // If the keyguard isn't showing but the device is dreaming, we should exit the + // dream. + if (keyguardUpdateMonitor.isDreaming) { + centralSurfaces?.awakenDreams() + } + action.onDismiss() + } + } + + override fun executeRunnableDismissingKeyguard( + runnable: Runnable?, + cancelAction: Runnable?, + dismissShade: Boolean, + afterKeyguardGone: Boolean, + deferred: Boolean, + willAnimateOnKeyguard: Boolean, + customMessage: String?, + ) { + val onDismissAction: ActivityStarter.OnDismissAction = + object : ActivityStarter.OnDismissAction { + override fun onDismiss(): Boolean { + if (runnable != null) { + if ( + keyguardStateController.isShowing && keyguardStateController.isOccluded + ) { + statusBarKeyguardViewManagerLazy + .get() + .addAfterKeyguardGoneRunnable(runnable) + } else { + mainExecutor.execute(runnable) + } + } + if (dismissShade) { + shadeControllerLazy.get().collapseShadeForActivityStart() + } + return deferred + } + + override fun willRunAnimationOnKeyguard(): Boolean { + return willAnimateOnKeyguard + } + } + dismissKeyguardThenExecute( + onDismissAction, + cancelAction, + afterKeyguardGone, + customMessage, + ) + } + + /** + * Return a [ActivityTransitionAnimator.Controller] wrapping `animationController` so that: + * - if it launches in the notification shade window and `dismissShade` is true, then the shade + * will be instantly dismissed at the end of the animation. + * - if it launches in status bar window, it will make the status bar window match the device + * size during the animation (that way, the animation won't be clipped by the status bar + * size). + * + * @param animationController the controller that is wrapped and will drive the main animation. + * @param dismissShade whether the notification shade will be dismissed at the end of the + * animation. This is ignored if `animationController` is not animating in the shade window. + * @param isLaunchForActivity whether the launch is for an activity. + */ + private fun wrapAnimationControllerForShadeOrStatusBar( + animationController: ActivityTransitionAnimator.Controller?, + dismissShade: Boolean, + isLaunchForActivity: Boolean, + ): ActivityTransitionAnimator.Controller? { + if (animationController == null) { + return null + } + val rootView = animationController.transitionContainer.rootView + val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> = + statusBarWindowController.wrapAnimationControllerIfInStatusBar( + rootView, + animationController + ) + if (controllerFromStatusBar.isPresent) { + return controllerFromStatusBar.get() + } + + centralSurfaces?.let { + // If the view is not in the status bar, then we are animating a view in the shade. + // We have to make sure that we collapse it when the animation ends or is cancelled. + if (dismissShade) { + return StatusBarTransitionAnimatorController( + animationController, + shadeAnimationInteractor, + shadeControllerLazy.get(), + notifShadeWindowControllerLazy.get(), + commandQueue, + displayId, + isLaunchForActivity + ) + } + } + + return animationController + } + + /** + * Wraps an animation controller so that if an activity would be launched on top of the + * lockscreen, the correct flags are set for it to be occluded. + */ + private fun wrapAnimationControllerForLockscreen( + animationController: ActivityTransitionAnimator.Controller? + ): ActivityTransitionAnimator.Controller? { + return animationController?.let { + object : DelegateTransitionAnimatorController(it) { + override fun onIntentStarted(willAnimate: Boolean) { + delegate.onIntentStarted(willAnimate) + if (willAnimate) { + centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) + } + } + + override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { + super.onTransitionAnimationStart(isExpandingFullyAbove) + + // Double check that the keyguard is still showing and not going + // away, but if so set the keyguard occluded. Typically, WM will let + // KeyguardViewMediator know directly, but we're overriding that to + // play the custom launch animation, so we need to take care of that + // here. The unocclude animation is not overridden, so WM will call + // KeyguardViewMediator's unocclude animation runner when the + // activity is exited. + if ( + keyguardStateController.isShowing && + !keyguardStateController.isKeyguardGoingAway + ) { + Log.d(TAG, "Setting occluded = true in #startActivity.") + keyguardViewMediatorLazy + .get() + .setOccluded(true /* isOccluded */, true /* animate */) + } + } + + override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { + // Set mIsLaunchingActivityOverLockscreen to false before actually + // finishing the animation so that we can assume that + // mIsLaunchingActivityOverLockscreen being true means that we will + // collapse the shade (or at least run the post collapse runnables) + // later on. + centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) + delegate.onTransitionAnimationEnd(isExpandingFullyAbove) + } + + override fun onTransitionAnimationCancelled(newKeyguardOccludedState: Boolean?) { + if (newKeyguardOccludedState != null) { + keyguardViewMediatorLazy + .get() + .setOccluded(newKeyguardOccludedState, false /* animate */) + } + + // Set mIsLaunchingActivityOverLockscreen to false before actually + // finishing the animation so that we can assume that + // mIsLaunchingActivityOverLockscreen being true means that we will + // collapse the shade (or at least run the // post collapse + // runnables) later on. + centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) + delegate.onTransitionAnimationCancelled(newKeyguardOccludedState) + } + } + } + } + + /** Retrieves the current user handle to start the Activity. */ + private fun getActivityUserHandle(intent: Intent): UserHandle { + val packages: Array<String> = context.resources.getStringArray(R.array.system_ui_packages) + for (pkg in packages) { + val componentName = intent.component ?: break + if (pkg == componentName.packageName) { + return UserHandle(UserHandle.myUserId()) + } + } + return userTracker.userHandle + } + + /** + * Whether we should animate an activity launch. + * + * Note: This method must be called *before* dismissing the keyguard. + */ + private fun shouldAnimateLaunch( + isActivityIntent: Boolean, + showOverLockscreen: Boolean, + ): Boolean { + // TODO(b/294418322): Support launch animations when occluded. + if (keyguardStateController.isOccluded) { + return false + } + + // Always animate if we are not showing the keyguard or if we animate over the lockscreen + // (without unlocking it). + if (showOverLockscreen || !keyguardStateController.isShowing) { + return true + } + + // We don't animate non-activity launches as they can break the animation. + // TODO(b/184121838): Support non activity launches on the lockscreen. + return isActivityIntent + } + + override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean { + return shouldAnimateLaunch(isActivityIntent, false) + } + + private fun postOnUiThread(delay: Int = 0, runnable: Runnable) { + mainExecutor.executeDelayed(runnable, delay.toLong()) + } + + companion object { + private const val TAG = "LegacyActivityStarterInternalImpl" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index 92fd90a0859a..5206e46a4580 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -24,10 +24,10 @@ import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver import com.android.systemui.Gefingerpoken -import com.android.systemui.res.R import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.res.R +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.ShadeController import com.android.systemui.shade.ShadeLogger @@ -65,7 +65,6 @@ private constructor( private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?, private val userChipViewModel: StatusBarUserChipViewModel, private val viewUtil: ViewUtil, - private val sceneContainerFlags: SceneContainerFlags, private val configurationController: ConfigurationController, private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory, ) : ViewController<PhoneStatusBarView>(view) { @@ -205,7 +204,7 @@ private constructor( // If scene framework is enabled, route the touch to it and // ignore the rest of the gesture. - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled) { windowRootView.get().dispatchTouchEvent(event) return true } @@ -267,7 +266,6 @@ private constructor( @Named(UNFOLD_STATUS_BAR) private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>, private val featureFlags: FeatureFlags, - private val sceneContainerFlags: SceneContainerFlags, private val userChipViewModel: StatusBarUserChipViewModel, private val centralSurfaces: CentralSurfaces, private val statusBarWindowStateController: StatusBarWindowStateController, @@ -301,7 +299,6 @@ private constructor( statusBarMoveFromCenterAnimationController, userChipViewModel, viewUtil, - sceneContainerFlags, configurationController, statusOverlayHoverListenerFactory, ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java index ed1f6ff7e513..87139ac0cada 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java @@ -98,11 +98,11 @@ public class StatusBarHeadsUpChangeListener implements OnHeadsUpChangedListener, // we need to keep the panel open artificially, let's wait until the //animation // is finished. - mHeadsUpManager.setHeadsUpGoingAway(true); + mHeadsUpManager.setHeadsUpAnimatingAway(true); mNsslController.runAfterAnimationFinished(() -> { if (!mHeadsUpManager.hasPinnedHeadsUp()) { mNotificationShadeWindowController.setHeadsUpShowing(false); - mHeadsUpManager.setHeadsUpGoingAway(false); + mHeadsUpManager.setHeadsUpAnimatingAway(false); } mNotificationRemoteInputManager.onPanelCollapsed(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 5f26702ad867..a141b5348574 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -67,12 +67,12 @@ import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; import com.android.systemui.dock.DockManager; import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardWmStateRefactor; import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor; +import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent; import com.android.systemui.keyguard.shared.model.DismissAction; import com.android.systemui.keyguard.shared.model.KeyguardDone; import com.android.systemui.keyguard.shared.model.KeyguardState; @@ -332,7 +332,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private final LatencyTracker mLatencyTracker; private final KeyguardSecurityModel mKeyguardSecurityModel; private final SelectedUserInteractor mSelectedUserInteractor; - @Nullable private KeyguardBypassController mBypassController; @Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI; @Nullable private TaskbarDelegate mTaskbarDelegate; @@ -381,7 +380,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb Lazy<ShadeController> shadeController, LatencyTracker latencyTracker, KeyguardSecurityModel keyguardSecurityModel, - FeatureFlags featureFlags, PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor, PrimaryBouncerInteractor primaryBouncerInteractor, BouncerView primaryBouncerView, @@ -413,7 +411,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mShadeController = shadeController; mLatencyTracker = latencyTracker; mKeyguardSecurityModel = keyguardSecurityModel; - mFlags = featureFlags; mPrimaryBouncerCallbackInteractor = primaryBouncerCallbackInteractor; mPrimaryBouncerInteractor = primaryBouncerInteractor; mPrimaryBouncerView = primaryBouncerView; @@ -442,8 +439,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb ShadeLockscreenInteractor shadeLockscreenInteractor, ShadeExpansionStateManager shadeExpansionStateManager, BiometricUnlockController biometricUnlockController, - View notificationContainer, - KeyguardBypassController bypassController) { + View notificationContainer) { mCentralSurfaces = centralSurfaces; mBiometricUnlockController = biometricUnlockController; @@ -454,7 +450,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb shadeExpansionStateManager.addExpansionListener(this); onPanelExpansionChanged(currentState); } - mBypassController = bypassController; mNotificationContainer = notificationContainer; if (!DeviceEntryUdfpsRefactor.isEnabled()) { mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create( @@ -805,7 +800,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message) { - if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled()) { if (r == null) { return; } @@ -857,7 +852,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb return; } - if (!mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (!RefactorKeyguardDismissIntent.isEnabled()) { mAfterKeyguardGoneAction = r; mKeyguardGoneCancelAction = cancelAction; mDismissActionWillAnimateOnKeyguard = r != null @@ -925,7 +920,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb * Adds a {@param runnable} to be executed after Keyguard is gone. */ public void addAfterKeyguardGoneRunnable(Runnable runnable) { - if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled()) { if (runnable != null) { mKeyguardDismissActionInteractor.get().runAfterKeyguardGone(runnable); } @@ -975,7 +970,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mKeyguardMessageAreaController.setIsVisible(isShowingAlternateBouncer); mKeyguardMessageAreaController.setMessage(""); } - mBypassController.setAltBouncerShowing(isShowingAlternateBouncer); mKeyguardUpdateManager.setAlternateBouncerShowing(isShowingAlternateBouncer); if (updateScrim) { @@ -1118,7 +1112,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb // We update the state (which will show the keyguard) only if an animation will run on // the keyguard. If there is no animation, we wait before updating the state so that we // go directly from bouncer to launcher/app. - if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled()) { if (mKeyguardDismissActionInteractor.get().runDismissAnimationOnKeyguard()) { updateStates(); } @@ -1245,7 +1239,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } private void executeAfterKeyguardGoneAction() { - if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) { + if (RefactorKeyguardDismissIntent.isEnabled()) { return; } if (mAfterKeyguardGoneAction != null) { @@ -1298,9 +1292,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb return; } + boolean hideBouncerOverDream = isBouncerShowing() + && mDreamOverlayStateController.isOverlayActive(); mCentralSurfaces.endAffordanceLaunch(); // The second condition is for SIM card locked bouncer - if (primaryBouncerIsScrimmed() && !needsFullscreenBouncer()) { + if (hideBouncerOverDream || (primaryBouncerIsScrimmed() && !needsFullscreenBouncer())) { hideBouncer(false); updateStates(); } else { @@ -1634,7 +1630,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb pw.println(" bouncerIsOrWillBeShowing(): " + primaryBouncerIsOrWillBeShowing()); pw.println(" Registered KeyguardViewManagerCallbacks:"); pw.println(" refactorKeyguardDismissIntent enabled:" - + mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)); + + RefactorKeyguardDismissIntent.isEnabled()); for (KeyguardViewManagerCallback callback : mCallbacks) { pw.println(" " + callback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java index c615887d5c25..d1189e1e5e1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java @@ -37,7 +37,7 @@ import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.res.R; import com.android.systemui.scene.domain.interactor.SceneInteractor; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.NotificationShadeWindowController; @@ -91,7 +91,6 @@ public final class StatusBarTouchableRegionManager implements Dumpable { ShadeInteractor shadeInteractor, Provider<SceneInteractor> sceneInteractor, JavaAdapter javaAdapter, - SceneContainerFlags sceneContainerFlags, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, PrimaryBouncerInteractor primaryBouncerInteractor, AlternateBouncerInteractor alternateBouncerInteractor @@ -121,7 +120,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { updateTouchableRegion(); } }); - mHeadsUpManager.addHeadsUpPhoneListener(this::onHeadsUpGoingAwayStateChanged); + mHeadsUpManager.addHeadsUpPhoneListener(this::onHeadsUpAnimatingAwayStateChanged); mNotificationShadeWindowController = notificationShadeWindowController; mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> { @@ -130,7 +129,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; - if (sceneContainerFlags.isEnabled()) { + if (SceneContainerFlag.isEnabled()) { javaAdapter.alwaysCollectFlow( sceneInteractor.get().isVisible(), this::onSceneContainerVisibilityChanged); @@ -214,7 +213,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { && (mNotificationShadeWindowView.getRootWindowInsets() != null) && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null); boolean shouldObserve = mHeadsUpManager.hasPinnedHeadsUp() - || mHeadsUpManager.isHeadsUpGoingAway() + || mHeadsUpManager.isHeadsUpAnimatingAwayValue() || mForceCollapsedUntilLayout || hasCutoutInset || mNotificationShadeWindowController.getForcePluginOpen(); @@ -288,8 +287,8 @@ public final class StatusBarTouchableRegionManager implements Dumpable { || mUnlockedScreenOffAnimationController.isAnimationPlaying(); } - private void onHeadsUpGoingAwayStateChanged(boolean headsUpGoingAway) { - if (!headsUpGoingAway) { + private void onHeadsUpAnimatingAwayStateChanged(boolean headsUpAnimatingAway) { + if (!headsUpAnimatingAway) { updateTouchableRegionAfterLayout(); } else { updateTouchableRegion(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt index 541ac48a2feb..31c213434abf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt @@ -15,36 +15,55 @@ */ package com.android.systemui.statusbar.phone +import android.annotation.StyleRes import android.app.Dialog import android.content.Context -import android.content.res.Configuration import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.Gravity import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import android.view.WindowInsets -import android.view.WindowInsets.Type.InsetsType -import android.view.WindowInsetsAnimation import android.view.WindowManager.LayoutParams.MATCH_PARENT import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION import android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL +import androidx.activity.ComponentDialog +import androidx.annotation.VisibleForTesting +import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ConfigurationController -import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener +import com.android.systemui.statusbar.policy.onConfigChanged +import dagger.Lazy +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.launch /** A dialog shown as a bottom sheet. */ -open class SystemUIBottomSheetDialog( +class SystemUIBottomSheetDialog +@VisibleForTesting +constructor( context: Context, - private val configurationController: ConfigurationController? = null, - theme: Int = R.style.Theme_SystemUI_Dialog -) : Dialog(context, theme) { + private val coroutineScope: CoroutineScope, + private val configurationController: ConfigurationController, + private val delegate: DialogDelegate<in Dialog>, + private val windowLayout: WindowLayout, + theme: Int, +) : ComponentDialog(context, theme) { + + private var job: Job? = null + override fun onCreate(savedInstanceState: Bundle?) { + delegate.beforeCreate(this, savedInstanceState) super.onCreate(savedInstanceState) setupWindow() - setupEdgeToEdge() setCanceledOnTouchOutside(true) + delegate.onCreate(this, savedInstanceState) } private fun setupWindow() { @@ -62,60 +81,84 @@ open class SystemUIBottomSheetDialog( } } - private fun setupEdgeToEdge() { - val edgeToEdgeHorizontally = - context.resources.getBoolean(R.bool.config_edgeToEdgeBottomSheetDialog) - val width = if (edgeToEdgeHorizontally) MATCH_PARENT else WRAP_CONTENT - val height = WRAP_CONTENT - window?.setLayout(width, height) - } - override fun onStart() { super.onStart() - configurationController?.addCallback(onConfigChanged) - window?.decorView?.setWindowInsetsAnimationCallback(insetsAnimationCallback) + job?.cancel() + job = + coroutineScope.launch { + windowLayout + .calculate() + .onEach { window?.apply { setLayout(it.width, it.height) } } + .launchIn(this) + configurationController.onConfigChanged + .onEach { delegate.onConfigurationChanged(this@SystemUIBottomSheetDialog, it) } + .launchIn(this) + } + delegate.onStart(this) } override fun onStop() { + job?.cancel() + delegate.onStop(this) super.onStop() - configurationController?.removeCallback(onConfigChanged) - window?.decorView?.setWindowInsetsAnimationCallback(null) } - /** Called after any insets change. */ - open fun onInsetsChanged(@InsetsType changedTypes: Int, insets: WindowInsets) {} + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + delegate.onWindowFocusChanged(this, hasFocus) + } - /** Can be overridden by subclasses to receive config changed events. */ - open fun onConfigurationChanged() {} + class Factory + @Inject + constructor( + @Application private val context: Context, + @Application private val coroutineScope: CoroutineScope, + private val defaultWindowLayout: Lazy<WindowLayout.LimitedEdgeToEdge>, + private val configurationController: ConfigurationController, + ) { - private val insetsAnimationCallback = - object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) { + fun create( + delegate: DialogDelegate<in Dialog>, + windowLayout: WindowLayout = defaultWindowLayout.get(), + @StyleRes theme: Int = R.style.Theme_SystemUI_Dialog, + ): SystemUIBottomSheetDialog = + SystemUIBottomSheetDialog( + context = context, + configurationController = configurationController, + coroutineScope = coroutineScope, + delegate = delegate, + windowLayout = windowLayout, + theme = theme, + ) + } - private var lastInsets: WindowInsets? = null + /** [SystemUIBottomSheetDialog] uses this to determine the [android.view.Window] layout. */ + interface WindowLayout { - override fun onEnd(animation: WindowInsetsAnimation) { - lastInsets?.let { onInsetsChanged(animation.typeMask, it) } - } + /** Returns a [Layout] to apply to [android.view.Window.setLayout]. */ + fun calculate(): Flow<Layout> - override fun onProgress( - insets: WindowInsets, - animations: MutableList<WindowInsetsAnimation>, - ): WindowInsets { - lastInsets = insets - onInsetsChanged(changedTypes = allAnimationMasks(animations), insets) - return insets - } + /** Edge to edge with which doesn't fill the whole space on the large screen. */ + class LimitedEdgeToEdge + @Inject + constructor( + @Application private val context: Context, + private val configurationController: ConfigurationController, + ) : WindowLayout { - private fun allAnimationMasks(animations: List<WindowInsetsAnimation>): Int = - animations.fold(0) { acc: Int, it -> acc or it.typeMask } - } + override fun calculate(): Flow<Layout> { + return configurationController.onConfigChanged + .onStart { emit(context.resources.configuration) } + .map { + val edgeToEdgeHorizontally = + context.resources.getBoolean(R.bool.config_edgeToEdgeBottomSheetDialog) + val width = if (edgeToEdgeHorizontally) MATCH_PARENT else WRAP_CONTENT - private val onConfigChanged = - object : ConfigurationListener { - override fun onConfigChanged(newConfig: Configuration?) { - super.onConfigChanged(newConfig) - setupEdgeToEdge() - onConfigurationChanged() + Layout(width, WRAP_CONTENT) + } } } + + data class Layout(val width: Int, val height: Int) + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt index 3b2930f78d19..f4e3eab8593d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.pipeline.mobile.data.model import android.os.PersistableBundle import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL -import android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT import android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL import androidx.annotation.VisibleForTesting import kotlinx.coroutines.flow.MutableStateFlow @@ -43,11 +42,10 @@ import kotlinx.coroutines.flow.asStateFlow * using the default config for logging purposes. * * NOTE to add new keys to be tracked: - * 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig] or [IntCarrierConfig] - * 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config] or - * [IntCarrierConfig.config] - * 3. Add the new wrapped public flow to the list of tracked configs, so they are properly updated - * when a new carrier config comes down + * 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig] + * 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config] + * 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly + * updated when a new carrier config comes down */ class SystemUiCarrierConfig internal constructor( @@ -68,16 +66,10 @@ internal constructor( /** Flow tracking the [KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL] config */ val showOperatorNameInStatusBar: StateFlow<Boolean> = showOperatorName.config - private val satelliteHysteresisSeconds = - IntCarrierConfig(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, defaultConfig) - /** Flow tracking the [KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT] config */ - val satelliteConnectionHysteresisSeconds: StateFlow<Int> = satelliteHysteresisSeconds.config - private val trackedConfigs = listOf( inflateSignalStrength, showOperatorName, - satelliteHysteresisSeconds, ) /** Ingest a new carrier config, and switch all of the tracked keys over to the new values */ @@ -98,19 +90,15 @@ internal constructor( override fun toString(): String = trackedConfigs.joinToString { it.toString() } } -interface CarrierConfig { - fun update(config: PersistableBundle) -} - /** Extracts [key] from the carrier config, and stores it in a flow */ private class BooleanCarrierConfig( val key: String, defaultConfig: PersistableBundle, -) : CarrierConfig { +) { private val _configValue = MutableStateFlow(defaultConfig.getBoolean(key)) val config = _configValue.asStateFlow() - override fun update(config: PersistableBundle) { + fun update(config: PersistableBundle) { _configValue.value = config.getBoolean(key) } @@ -118,20 +106,3 @@ private class BooleanCarrierConfig( return "$key=${config.value}" } } - -/** Extracts [key] from the carrier config, and stores it in a flow */ -private class IntCarrierConfig( - val key: String, - defaultConfig: PersistableBundle, -) : CarrierConfig { - private val _configValue = MutableStateFlow(defaultConfig.getInt(key)) - val config = _configValue.asStateFlow() - - override fun update(config: PersistableBundle) { - _configValue.value = config.getInt(key) - } - - override fun toString(): String { - return "$key=${config.value}" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt index 8f00b43e79f8..22785979f3ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt @@ -44,6 +44,9 @@ interface MobileConnectionRepository { /** The carrierId for this connection. See [TelephonyManager.getSimCarrierId] */ val carrierId: StateFlow<Int> + /** Reflects the value from the carrier config INFLATE_SIGNAL_STRENGTH for this connection */ + val inflateSignalStrength: StateFlow<Boolean> + /** * The table log buffer created for this connection. Will have the name "MobileConnectionLog * [subId]" @@ -141,9 +144,6 @@ interface MobileConnectionRepository { */ val hasPrioritizedNetworkCapabilities: StateFlow<Boolean> - /** Duration in seconds of the hysteresis to use when losing satellite connection. */ - val satelliteConnectionHysteresisSeconds: StateFlow<Int> - /** * True if this connection is in emergency callback mode. * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt index af34a57c7242..83d5f2b5d325 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt @@ -43,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.F import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** @@ -67,6 +68,17 @@ class DemoMobileConnectionRepository( ) .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value) + private val _inflateSignalStrength: MutableStateFlow<Boolean> = MutableStateFlow(false) + override val inflateSignalStrength = + _inflateSignalStrength + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = "inflate", + _inflateSignalStrength.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _inflateSignalStrength.value) + private val _isEmergencyOnly = MutableStateFlow(false) override val isEmergencyOnly = _isEmergencyOnly @@ -191,7 +203,16 @@ class DemoMobileConnectionRepository( .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value) .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value) - override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS) + override val numberOfLevels = + _inflateSignalStrength + .map { shouldInflate -> + if (shouldInflate) { + DEFAULT_NUM_LEVELS + 1 + } else { + DEFAULT_NUM_LEVELS + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS) override val dataEnabled = MutableStateFlow(true) @@ -206,8 +227,6 @@ class DemoMobileConnectionRepository( override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false) - override val satelliteConnectionHysteresisSeconds = MutableStateFlow(0) - override suspend fun isInEcmMode(): Boolean = false /** @@ -226,8 +245,7 @@ class DemoMobileConnectionRepository( _carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID - numberOfLevels.value = - if (event.inflateStrength) DEFAULT_NUM_LEVELS + 1 else DEFAULT_NUM_LEVELS + _inflateSignalStrength.value = event.inflateStrength cdmaRoaming.value = event.roaming _isRoaming.value = event.roaming @@ -258,7 +276,6 @@ class DemoMobileConnectionRepository( carrierName.value = NetworkNameModel.SubscriptionDerived(CARRIER_MERGED_NAME) // TODO(b/276943904): is carrierId a thing with carrier merged networks? _carrierId.value = INVALID_SUBSCRIPTION_ID - numberOfLevels.value = event.numberOfLevels cdmaRoaming.value = false _primaryLevel.value = event.level _cdmaLevel.value = event.level diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt index 2bc3bcbc8bf5..a532e6227451 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt @@ -165,6 +165,7 @@ class CarrierMergedConnectionRepository( override val isRoaming = MutableStateFlow(false).asStateFlow() override val carrierId = MutableStateFlow(INVALID_SUBSCRIPTION_ID).asStateFlow() + override val inflateSignalStrength = MutableStateFlow(false).asStateFlow() override val isEmergencyOnly = MutableStateFlow(false).asStateFlow() override val operatorAlphaShort = MutableStateFlow(null).asStateFlow() override val isInService = MutableStateFlow(true).asStateFlow() @@ -186,9 +187,6 @@ class CarrierMergedConnectionRepository( */ override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false).asStateFlow() - /** Non-applicable to carrier merged connections. */ - override val satelliteConnectionHysteresisSeconds = MutableStateFlow(0).asStateFlow() - override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled override suspend fun isInEcmMode(): Boolean = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt index b085d8046b12..41559b2c1455 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod +import android.util.IndentingPrintWriter import androidx.annotation.VisibleForTesting import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.log.table.TableLogBuffer @@ -24,6 +25,7 @@ import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository +import java.io.PrintWriter import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -291,6 +293,21 @@ class FullMobileConnectionRepository( ) .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.dataEnabled.value) + override val inflateSignalStrength = + activeRepo + .flatMapLatest { it.inflateSignalStrength } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = "inflate", + initialValue = activeRepo.value.inflateSignalStrength.value, + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.inflateSignalStrength.value + ) + override val numberOfLevels = activeRepo .flatMapLatest { it.numberOfLevels } @@ -334,17 +351,29 @@ class FullMobileConnectionRepository( activeRepo.value.hasPrioritizedNetworkCapabilities.value, ) - override val satelliteConnectionHysteresisSeconds = - activeRepo - .flatMapLatest { it.satelliteConnectionHysteresisSeconds } - .stateIn( - scope, - SharingStarted.WhileSubscribed(), - activeRepo.value.satelliteConnectionHysteresisSeconds.value - ) - override suspend fun isInEcmMode(): Boolean = activeRepo.value.isInEcmMode() + fun dump(pw: PrintWriter) { + val ipw = IndentingPrintWriter(pw, " ") + + ipw.println("MobileConnectionRepository[$subId]") + ipw.increaseIndent() + + ipw.println("carrierMerged=${_isCarrierMerged.value}") + + ipw.print("Type (cellular or carrier merged): ") + when (activeRepo.value) { + is CarrierMergedConnectionRepository -> ipw.println("Carrier merged") + is MobileConnectionRepositoryImpl -> ipw.println("Cellular") + } + + ipw.increaseIndent() + ipw.println("Provider: ${activeRepo.value}") + ipw.decreaseIndent() + + ipw.decreaseIndent() + } + class Factory @Inject constructor( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index 5ab2ae899370..b3885d247949 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -302,8 +302,10 @@ class MobileConnectionRepositoryImpl( } .stateIn(scope, SharingStarted.WhileSubscribed(), UnknownNetworkType) + override val inflateSignalStrength = systemUiCarrierConfig.shouldInflateSignalStrength + override val numberOfLevels = - systemUiCarrierConfig.shouldInflateSignalStrength + inflateSignalStrength .map { shouldInflate -> if (shouldInflate) { DEFAULT_NUM_LEVELS + 1 @@ -448,9 +450,6 @@ class MobileConnectionRepositoryImpl( .flowOn(bgDispatcher) .stateIn(scope, SharingStarted.WhileSubscribed(), false) - override val satelliteConnectionHysteresisSeconds: StateFlow<Int> = - systemUiCarrierConfig.satelliteConnectionHysteresisSeconds - class Factory @Inject constructor( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt index a455db2e67ce..5d91ef323ead 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt @@ -26,17 +26,20 @@ import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID import android.telephony.TelephonyCallback import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener import android.telephony.TelephonyManager +import android.util.IndentingPrintWriter import androidx.annotation.VisibleForTesting import com.android.internal.telephony.PhoneConstants import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.settingslib.SignalIcon.MobileIconGroup import com.android.settingslib.mobile.MobileMappings.Config +import com.android.systemui.Dumpable import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dump.DumpManager import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.res.R @@ -52,6 +55,8 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.Connectivi import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.util.kotlin.pairwise +import java.io.PrintWriter +import java.lang.ref.WeakReference import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -97,8 +102,12 @@ constructor( wifiRepository: WifiRepository, private val fullMobileRepoFactory: FullMobileConnectionRepository.Factory, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, -) : MobileConnectionsRepository { - private var subIdRepositoryCache: MutableMap<Int, FullMobileConnectionRepository> = + private val dumpManager: DumpManager, +) : MobileConnectionsRepository, Dumpable { + + // TODO(b/333912012): for now, we are never invalidating the cache. We can do better though + private var subIdRepositoryCache: + MutableMap<Int, WeakReference<FullMobileConnectionRepository>> = mutableMapOf() private val defaultNetworkName = @@ -109,6 +118,10 @@ constructor( private val networkNameSeparator: String = context.getString(R.string.status_bar_network_name_separator) + init { + dumpManager.registerNormalDumpable("MobileConnectionsRepository", this) + } + private val carrierMergedSubId: StateFlow<Int?> = combine( wifiRepository.wifiNetwork, @@ -283,8 +296,10 @@ constructor( getOrCreateRepoForSubId(subId) private fun getOrCreateRepoForSubId(subId: Int) = - subIdRepositoryCache[subId] - ?: createRepositoryForSubId(subId).also { subIdRepositoryCache[subId] = it } + subIdRepositoryCache[subId]?.get() + ?: createRepositoryForSubId(subId).also { + subIdRepositoryCache[subId] = WeakReference(it) + } override val mobileIsDefault: StateFlow<Boolean> = connectivityRepository.defaultConnections @@ -374,9 +389,8 @@ constructor( } private fun updateRepos(newInfos: List<SubscriptionModel>) { - dropUnusedReposFromCache(newInfos) subIdRepositoryCache.forEach { (subId, repo) -> - repo.setIsCarrierMerged(isCarrierMerged(subId)) + repo.get()?.setIsCarrierMerged(isCarrierMerged(subId)) } } @@ -384,13 +398,6 @@ constructor( return subId == carrierMergedSubId.value } - private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) { - // Remove any connection repository from the cache that isn't in the new set of IDs. They - // will get garbage collected once their subscribers go away - subIdRepositoryCache = - subIdRepositoryCache.filter { checkSub(it.key, newInfos) }.toMutableMap() - } - /** * True if the checked subId is in the list of current subs or the active mobile data subId * @@ -422,6 +429,22 @@ constructor( profileClass = profileClass, ) + override fun dump(pw: PrintWriter, args: Array<String>) { + val ipw = IndentingPrintWriter(pw, " ") + ipw.println("Connection cache:") + + ipw.increaseIndent() + subIdRepositoryCache.entries.forEach { (subId, repo) -> + ipw.println("$subId: ${repo.get()}") + } + ipw.decreaseIndent() + + ipw.println("Connections (${subIdRepositoryCache.size} total):") + ipw.increaseIndent() + subIdRepositoryCache.values.forEach { it.get()?.dump(ipw) } + ipw.decreaseIndent() + } + companion object { private const val LOGGING_PREFIX = "Repo" } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt index 9d194cfca350..ed9e4056535f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt @@ -35,25 +35,18 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIc import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.util.kotlin.pairwiseBy -import kotlin.time.DurationUnit -import kotlin.time.toDuration import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch interface MobileIconInteractor { /** The table log created for this connection */ @@ -269,43 +262,6 @@ class MobileIconInteractorImpl( MutableStateFlow(false).asStateFlow() } - private val hysteresisActive = MutableStateFlow(false) - - private val isNonTerrestrialWithHysteresis: StateFlow<Boolean> = - combine(isNonTerrestrial, hysteresisActive) { isNonTerrestrial, hysteresisActive -> - if (hysteresisActive) { - true - } else { - isNonTerrestrial - } - } - .logDiffsForTable( - tableLogBuffer = tableLogBuffer, - columnName = "isNonTerrestrialWithHysteresis", - columnPrefix = "", - initialValue = Flags.carrierEnabledSatelliteFlag(), - ) - .stateIn(scope, SharingStarted.Eagerly, Flags.carrierEnabledSatelliteFlag()) - - private val lostSatelliteConnection = - isNonTerrestrial.pairwiseBy { old, new -> hysteresisActive.value = old && !new } - - init { - scope.launch { lostSatelliteConnection.collect() } - scope.launch { - hysteresisActive.collectLatest { - if (it) { - delay( - connectionRepository.satelliteConnectionHysteresisSeconds.value.toDuration( - DurationUnit.SECONDS - ) - ) - hysteresisActive.value = false - } - } - } - } - override val isRoaming: StateFlow<Boolean> = combine( connectionRepository.carrierNetworkChangeActive, @@ -367,8 +323,11 @@ class MobileIconInteractorImpl( combine( level, isInService, - ) { level, isInService -> - if (isInService) level else 0 + connectionRepository.inflateSignalStrength, + ) { level, isInService, inflate -> + if (isInService) { + if (inflate) level + 1 else level + } else 0 } .stateIn(scope, SharingStarted.WhileSubscribed(), 0) @@ -404,7 +363,7 @@ class MobileIconInteractorImpl( showExclamationMark.value, carrierNetworkChangeActive.value, ) - isNonTerrestrialWithHysteresis + isNonTerrestrial .flatMapLatest { ntn -> if (ntn) { satelliteIcon diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt index a0c5618041f6..5f08afdee74a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt @@ -128,6 +128,8 @@ object MobileIconBinder { mobileGroupView, dotView, ) + + view.requestLayout() } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt index eda5c44b5c2f..103b0e3a6f27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel -import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH +import com.android.settingslib.AccessibilityContentDescriptions import com.android.systemui.Flags.statusBarStaticInoutIndicators import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon @@ -50,7 +50,7 @@ interface MobileIconViewModelCommon { /** True if this view should be visible at all. */ val isVisible: StateFlow<Boolean> val icon: Flow<SignalIconModel> - val contentDescription: Flow<ContentDescription> + val contentDescription: Flow<ContentDescription?> val roaming: Flow<Boolean> /** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */ val networkTypeIcon: Flow<Icon.Resource?> @@ -123,7 +123,7 @@ class MobileIconViewModel( override val icon: Flow<SignalIconModel> = vmProvider.flatMapLatest { it.icon } - override val contentDescription: Flow<ContentDescription> = + override val contentDescription: Flow<ContentDescription?> = vmProvider.flatMapLatest { it.contentDescription } override val roaming: Flow<Boolean> = vmProvider.flatMapLatest { it.roaming } @@ -206,12 +206,26 @@ private class CellularIconViewModel( override val icon: Flow<SignalIconModel> = iconInteractor.signalLevelIcon - override val contentDescription: Flow<ContentDescription> = run { - val initial = ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[0]) + override val contentDescription: Flow<ContentDescription?> = iconInteractor.signalLevelIcon - .map { ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[it.level]) } - .stateIn(scope, SharingStarted.WhileSubscribed(), initial) - } + .map { + // We expect the signal icon to be cellular here since this is the cellular vm + if (it !is SignalIconModel.Cellular) { + null + } else { + val resId = + AccessibilityContentDescriptions.getDescriptionForLevel( + it.level, + it.numberOfLevels + ) + if (resId != 0) { + ContentDescription.Resource(resId) + } else { + null + } + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), null) private val showNetworkTypeIcon: Flow<Boolean> = combine( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt index 08ed0305bd13..054116dbdfc2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt @@ -22,6 +22,8 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -41,6 +43,7 @@ constructor( val repo: DeviceBasedSatelliteRepository, iconsInteractor: MobileIconsInteractor, deviceProvisioningInteractor: DeviceProvisioningInteractor, + wifiInteractor: WifiInteractor, @Application scope: CoroutineScope, ) { /** Must be observed by any UI showing Satellite iconography */ @@ -73,6 +76,9 @@ constructor( val isDeviceProvisioned: Flow<Boolean> = deviceProvisioningInteractor.isDeviceProvisioned + val isWifiActive: Flow<Boolean> = + wifiInteractor.wifiNetwork.map { it is WifiNetworkModel.Active } + /** When all connections are considered OOS, satellite connectivity is potentially valid */ val areAllConnectionsOutOfService = if (Flags.oemEnabledSatelliteFlag()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt index 40641bed0602..a0291b81c9a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt @@ -59,9 +59,10 @@ constructor( combine( interactor.isSatelliteAllowed, interactor.isDeviceProvisioned, + interactor.isWifiActive, airplaneModeRepository.isAirplaneMode - ) { isSatelliteAllowed, isDeviceProvisioned, isAirplaneMode -> - isSatelliteAllowed && isDeviceProvisioned && !isAirplaneMode + ) { isSatelliteAllowed, isDeviceProvisioned, isWifiActive, isAirplaneMode -> + isSatelliteAllowed && isDeviceProvisioned && !isWifiActive && !isAirplaneMode } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt index 52a6d8cf0952..cc87e8a45d13 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt @@ -19,6 +19,9 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING +import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN +import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor @@ -77,15 +80,13 @@ constructor( @Application coroutineScope: CoroutineScope, ) : CollapsedStatusBarViewModel { override val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean> = - keyguardTransitionInteractor.lockscreenToOccludedTransition - .map { - it.transitionState == TransitionState.STARTED || - it.transitionState == TransitionState.RUNNING - } + keyguardTransitionInteractor + .isInTransition(LOCKSCREEN, OCCLUDED) .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false) override val transitionFromLockscreenToDreamStartedEvent: Flow<Unit> = - keyguardTransitionInteractor.lockscreenToDreamingTransition + keyguardTransitionInteractor + .transition(LOCKSCREEN, DREAMING) .filter { it.transitionState == TransitionState.STARTED } .map {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt index 9cdecef3f6e8..1b56702f3907 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt @@ -115,13 +115,16 @@ class AvalancheController @Inject constructor( * Run or ignore Runnable for given HeadsUpEntry. If entry was never shown, ignore and delete * all Runnables associated with that entry. */ - fun delete(entry: HeadsUpEntry, runnable: Runnable, label: String) { + fun delete(entry: HeadsUpEntry?, runnable: Runnable, label: String) { if (!NotificationThrottleHun.isEnabled) { runnable.run() return } val fn = "[$label] => AvalancheController.delete " + getKey(entry) - + if (entry == null) { + log { "$fn => cannot remove NULL entry" } + return + } if (entry in nextMap) { log { "$fn => [remove from next]" } if (entry in nextMap) nextMap.remove(entry) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java index d99af2ddb95d..b8318a7dfb61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java @@ -256,10 +256,15 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { // A copy is necessary here as we are changing the underlying map. This would cause // undefined behavior if we iterated over the key set directly. ArraySet<String> keysToRemove = new ArraySet<>(mHeadsUpEntryMap.keySet()); + + // Must get waiting keys before calling removeEntry, which clears waiting entries in + // AvalancheController + List<String> waitingKeysToRemove = mAvalancheController.getWaitingKeys(); + for (String key : keysToRemove) { removeEntry(key); } - for (String key : mAvalancheController.getWaitingKeys()) { + for (String key : waitingKeysToRemove) { removeEntry(key); } } @@ -903,8 +908,12 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { mLogger.logAutoRemoveCanceled(mEntry, reason); } }; - mAvalancheController.update(this, runnable, - reason + " removeAutoRemovalCallbacks"); + if (isHeadsUpEntry(this.mEntry.getKey())) { + mAvalancheController.update(this, runnable, reason + " cancelAutoRemovalCallbacks"); + } else { + // Just removed + runnable.run(); + } } public void scheduleAutoRemovalCallback(FinishTimeUpdater finishTimeCalculator, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt index 52a2e9ccc163..28a2a1f49bf6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt @@ -73,7 +73,8 @@ interface HeadsUpManager : Dumpable { /** Returns whether or not the given notification is managed by this manager. */ fun isHeadsUpEntry(key: String): Boolean - fun isHeadsUpGoingAway(): Boolean + /** @see setHeadsUpAnimatingAway */ + fun isHeadsUpAnimatingAwayValue(): Boolean /** Returns if the given notification is snoozed or not. */ fun isSnoozed(packageName: String): Boolean @@ -130,7 +131,7 @@ interface HeadsUpManager : Dumpable { * Set that we are exiting the headsUp pinned mode, but some notifications might still be * animating out. This is used to keep the touchable regions in a reasonable state. */ - fun setHeadsUpGoingAway(headsUpGoingAway: Boolean) + fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean) /** * Notifies that a remote input textbox in notification gets active or inactive. @@ -194,10 +195,10 @@ interface AnimationStateHandler { interface OnHeadsUpPhoneListenerChange { /** * Called when a heads up notification is 'going away' or no longer 'going away'. See - * [HeadsUpManager.setHeadsUpGoingAway]. + * [HeadsUpManager.setHeadsUpAnimatingAway]. */ // TODO(b/325936094) delete this callback, and listen to the flow instead - fun onHeadsUpGoingAwayStateChanged(headsUpGoingAway: Boolean) + fun onHeadsUpAnimatingAwayStateChanged(headsUpAnimatingAway: Boolean) } /* No op impl of HeadsUpManager. */ @@ -215,7 +216,7 @@ class HeadsUpManagerEmptyImpl @Inject constructor() : HeadsUpManager { override fun getTopEntry() = null override fun hasPinnedHeadsUp() = false override fun isHeadsUpEntry(key: String) = false - override fun isHeadsUpGoingAway() = false + override fun isHeadsUpAnimatingAwayValue() = false override fun isSnoozed(packageName: String) = false override fun isSticky(key: String?) = false override fun isTrackingHeadsUp() = false @@ -228,7 +229,7 @@ class HeadsUpManagerEmptyImpl @Inject constructor() : HeadsUpManager { override fun setAnimationStateHandler(handler: AnimationStateHandler) {} override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {} override fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean) {} - override fun setHeadsUpGoingAway(headsUpGoingAway: Boolean) {} + override fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean) {} override fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean) {} override fun setTrackingHeadsUp(tracking: Boolean) {} override fun setUser(user: Int) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt index a30660645990..11cbc9c66923 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt @@ -176,7 +176,7 @@ class HeadsUpManagerLogger @Inject constructor( bool1 = alert bool2 = hasEntry }, { - "request: update notification $str1 alert: $bool1 hasEntry: $bool2 reason: $str2" + "request: update notification $str1 alert: $bool1 hasEntry: $bool2" }) } @@ -186,7 +186,7 @@ class HeadsUpManagerLogger @Inject constructor( bool1 = alert bool2 = hasEntry }, { - "update notification $str1 alert: $bool1 hasEntry: $bool2 reason: $str2" + "update notification $str1 alert: $bool1 hasEntry: $bool2" }) } diff --git a/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt index 0d3682c9a24b..fbbd2b9c5de8 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt @@ -15,9 +15,11 @@ */ package com.android.systemui.unfold.data.repository +import androidx.annotation.FloatRange import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.unfold.UnfoldTransitionProgressProvider import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished +import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionInProgress import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted import com.android.systemui.util.kotlin.getOrNull import java.util.Optional @@ -42,6 +44,10 @@ interface UnfoldTransitionRepository { sealed class UnfoldTransitionStatus { /** Status that is sent when fold or unfold transition is in started state */ data object TransitionStarted : UnfoldTransitionStatus() + /** Status that is sent while fold or unfold transition is in progress */ + data class TransitionInProgress( + @FloatRange(from = 0.0, to = 1.0) val progress: Float, + ) : UnfoldTransitionStatus() /** Status that is sent when fold or unfold transition is finished */ data object TransitionFinished : UnfoldTransitionStatus() } @@ -66,6 +72,10 @@ constructor( trySend(TransitionStarted) } + override fun onTransitionProgress(progress: Float) { + trySend(TransitionInProgress(progress)) + } + override fun onTransitionFinished() { trySend(TransitionFinished) } diff --git a/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt index 3e2e564c307c..a8e4496d7804 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt @@ -17,10 +17,14 @@ package com.android.systemui.unfold.domain.interactor import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished +import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionInProgress import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map /** * Contains business-logic related to fold-unfold transitions while interacting with @@ -30,6 +34,8 @@ interface UnfoldTransitionInteractor { /** Returns availability of fold/unfold transitions on the device */ val isAvailable: Boolean + val unfoldProgress: Flow<Float> + /** Suspends and waits for a fold/unfold transition to finish */ suspend fun waitForTransitionFinish() @@ -44,6 +50,11 @@ constructor(private val repository: UnfoldTransitionRepository) : UnfoldTransiti override val isAvailable: Boolean get() = repository.isAvailable + override val unfoldProgress: Flow<Float> = + repository.transitionStatus + .map { (it as? TransitionInProgress)?.progress ?: 1f } + .distinctUntilChanged() + override suspend fun waitForTransitionFinish() { repository.transitionStatus.filter { it is TransitionFinished }.first() } diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/ReduceBrightColorsControllerExt.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/ReduceBrightColorsControllerExt.kt new file mode 100644 index 000000000000..ee00e8b04ef1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/ReduceBrightColorsControllerExt.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.kotlin + +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.qs.ReduceBrightColorsController +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.onStart + +fun ReduceBrightColorsController.isEnabled(): Flow<Boolean> { + return conflatedCallbackFlow { + val callback = + object : ReduceBrightColorsController.Listener { + override fun onActivated(activated: Boolean) { + trySend(activated) + } + } + addCallback(callback) + awaitClose { removeCallback(callback) } + } + .onStart { emit(isReduceBrightColorsActivated) } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/Util.java b/packages/SystemUI/src/com/android/systemui/volume/Util.java index 7edb5a55a9ae..df19013ce2c6 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/Util.java +++ b/packages/SystemUI/src/com/android/systemui/volume/Util.java @@ -17,6 +17,7 @@ package com.android.systemui.volume; import android.media.AudioManager; +import android.util.MathUtils; import android.view.View; /** @@ -46,4 +47,27 @@ class Util extends com.android.settingslib.volume.Util { if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return; v.setVisibility(vis ? View.VISIBLE : View.GONE); } + + /** + * Translates a value from one range to another. + * + * ``` + * Given: currentValue=3, currentRange=[0, 8], targetRange=[0, 100] + * Result: 37.5 + * ``` + */ + public static float translateToRange(float value, + float valueRangeStart, + float valueRangeEnd, + float targetRangeStart, + float targetRangeEnd) { + float currentRangeLength = valueRangeEnd - valueRangeStart; + float targetRangeLength = targetRangeEnd - targetRangeStart; + if (currentRangeLength == 0f || targetRangeLength == 0f) { + return targetRangeStart; + } + float valueFraction = (value - valueRangeStart) / currentRangeLength; + return MathUtils.constrain(targetRangeStart + valueFraction * targetRangeLength, + targetRangeStart, targetRangeEnd); + } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 27a708a00cb7..22455417b647 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -137,13 +137,13 @@ import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.volume.domain.interactor.VolumePanelNavigationInteractor; import com.android.systemui.volume.ui.navigation.VolumeNavigator; -import dagger.Lazy; - import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import dagger.Lazy; + /** * Visual presentation of the volume dialog. * @@ -166,6 +166,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private static final int DRAWER_ANIMATION_DURATION_SHORT = 175; private static final int DRAWER_ANIMATION_DURATION = 250; + private static final int DISPLAY_RANGE_MULTIPLIER = 100; /** Shows volume dialog show animation. */ private static final String TYPE_SHOW = "show"; @@ -826,12 +827,14 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, writer.print(" mSilentMode: "); writer.println(mSilentMode); } - private static int getImpliedLevel(SeekBar seekBar, int progress) { - final int m = seekBar.getMax(); - final int n = m / 100 - 1; - final int level = progress == 0 ? 0 - : progress == m ? (m / 100) : (1 + (int) ((progress / (float) m) * n)); - return level; + private static int getVolumeFromProgress(StreamState state, SeekBar seekBar, int progress) { + return (int) Util.translateToRange(progress, seekBar.getMin(), seekBar.getMax(), + state.levelMin, state.levelMax); + } + + private static int getProgressFromVolume(StreamState state, SeekBar seekBar, int volume) { + return (int) Util.translateToRange(volume, state.levelMin, state.levelMax, seekBar.getMin(), + seekBar.getMax()); } @SuppressLint("InflateParams") @@ -854,6 +857,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, addSliderHapticsToRow(row); row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); row.number = row.view.findViewById(R.id.volume_number); + row.slider.setAccessibilityDelegate( + new VolumeDialogSeekBarAccessibilityDelegate(DISPLAY_RANGE_MULTIPLIER)); row.anim = null; @@ -1129,7 +1134,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } updateSelectedRingerContainerDescription(true); - + mSelectedRingerContainer.setImportantForAccessibility( + View.IMPORTANT_FOR_ACCESSIBILITY_NO); + mSelectedRingerContainer.clearFocus(); mIsRingerDrawerOpen = true; } @@ -1175,7 +1182,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, .start(); updateSelectedRingerContainerDescription(false); - + mSelectedRingerContainer.setImportantForAccessibility( + View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); mIsRingerDrawerOpen = false; } @@ -1746,7 +1754,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, boolean isZenMuted = mState.zenMode == Global.ZEN_MODE_ALARMS || mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS || (mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS - && mState.disallowRinger); + && mState.disallowRinger); enableRingerViewsH(!isZenMuted); switch (mState.ringerModeInternal) { case AudioManager.RINGER_MODE_VIBRATE: @@ -1796,7 +1804,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); info.addAction(new AccessibilityNodeInfo.AccessibilityAction( - AccessibilityNodeInfo.ACTION_CLICK, hintLabel)); + AccessibilityNodeInfo.ACTION_CLICK, hintLabel)); } }); } @@ -1913,12 +1921,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, : false; // update slider max - final int max = ss.levelMax * 100; + final int max = ss.levelMax * DISPLAY_RANGE_MULTIPLIER; if (max != row.slider.getMax()) { row.slider.setMax(max); } // update slider min - final int min = ss.levelMin * 100; + final int min = ss.levelMin * DISPLAY_RANGE_MULTIPLIER; if (min != row.slider.getMin()) { row.slider.setMin(min); } @@ -2066,7 +2074,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, return; // don't update if user is sliding } final int progress = row.slider.getProgress(); - final int level = getImpliedLevel(row.slider, progress); + final int level = getVolumeFromProgress(row.ss, row.slider, progress); final boolean rowVisible = row.view.getVisibility() == VISIBLE; final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt) < USER_ATTEMPT_GRACE_PERIOD; @@ -2082,7 +2090,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, return; // don't clamp if visible } } - final int newProgress = vlevel * 100; + final int newProgress = getProgressFromVolume(row.ss, row.slider, vlevel); if (progress != newProgress) { if (mShowing && rowVisible) { // animate! @@ -2527,13 +2535,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, + " onProgressChanged " + progress + " fromUser=" + fromUser); if (!fromUser) return; if (mRow.ss.levelMin > 0) { - final int minProgress = mRow.ss.levelMin * 100; + final int minProgress = getProgressFromVolume(mRow.ss, seekBar, mRow.ss.levelMin); if (progress < minProgress) { seekBar.setProgress(minProgress); progress = minProgress; } } - final int userLevel = getImpliedLevel(seekBar, progress); + final int userLevel = getVolumeFromProgress(mRow.ss, seekBar, progress); if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) { mRow.userAttempt = SystemClock.uptimeMillis(); if (mRow.requestedLevel != userLevel) { @@ -2566,7 +2574,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } mRow.tracking = false; mRow.userAttempt = SystemClock.uptimeMillis(); - final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); + final int userLevel = getVolumeFromProgress(mRow.ss, seekBar, seekBar.getProgress()); Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel); if (mRow.ss.level != userLevel) { mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow), diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogSeekBarAccessibilityDelegate.kt b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogSeekBarAccessibilityDelegate.kt new file mode 100644 index 000000000000..cd31a9531db6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogSeekBarAccessibilityDelegate.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume + +import android.os.Bundle +import android.view.View +import android.view.View.AccessibilityDelegate +import android.view.accessibility.AccessibilityNodeInfo +import android.widget.SeekBar +import com.android.internal.R + +class VolumeDialogSeekBarAccessibilityDelegate( + private val accessibilityStep: Int, +) : AccessibilityDelegate() { + + override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean { + require(host is SeekBar) { "This class only works with the SeekBar" } + val seekBar: SeekBar = host + if ( + action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD || + action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD + ) { + var increment = accessibilityStep + if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) { + increment = -increment + } + + return super.performAccessibilityAction( + host, + R.id.accessibilityActionSetProgress, + Bundle().apply { + putFloat( + AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE, + (seekBar.progress + increment).coerceIn(seekBar.min, seekBar.max).toFloat(), + ) + }, + ) + } + return super.performAccessibilityAction(host, action, args) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/UiEventLoggerStartableModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/UiEventLoggerStartableModule.kt new file mode 100644 index 000000000000..9b84090d72cd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/UiEventLoggerStartableModule.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.dagger + +import com.android.systemui.volume.domain.startable.AudioModeLoggerStartable +import com.android.systemui.volume.panel.domain.VolumePanelStartable +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoSet + +@Module +interface UiEventLoggerStartableModule { + + @Binds + @IntoSet + fun bindAudioModeLoggerStartable( + audioModeLoggerStartable: AudioModeLoggerStartable, + ): VolumePanelStartable +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt new file mode 100644 index 000000000000..12447577e945 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.domain.startable + +import com.android.internal.logging.UiEventLogger +import com.android.settingslib.volume.domain.interactor.AudioModeInteractor +import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import com.android.systemui.volume.panel.domain.VolumePanelStartable +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.launch + +/** Logger for audio mode */ +@VolumePanelScope +class AudioModeLoggerStartable +@Inject +constructor( + @VolumePanelScope private val scope: CoroutineScope, + private val uiEventLogger: UiEventLogger, + private val audioModeInteractor: AudioModeInteractor, +) : VolumePanelStartable { + + override fun start() { + scope.launch { + audioModeInteractor.isOngoingCall.distinctUntilChanged().collect { ongoingCall -> + uiEventLogger.log( + if (ongoingCall) VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_CALLING + else VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_NORMAL + ) + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt index 8f18aa8021ae..8ce3b1fa1e73 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt @@ -41,12 +41,14 @@ import kotlinx.coroutines.flow.map interface AncSliceRepository { /** - * ANC slice with a given width. Emits null when there is no ANC slice available. This can mean - * that: + * ANC slice with a given width. [isCollapsed] slice shows a single button, and expanded shows a + * row buttons. + * + * Emits null when there is no ANC slice available. This can mean that: * - there is no supported device connected; * - there is no slice provider for the uri; */ - fun ancSlice(width: Int): Flow<Slice?> + fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> } @OptIn(ExperimentalCoroutinesApi::class) @@ -60,9 +62,14 @@ constructor( private val localMediaRepository = mediaRepositoryFactory.create(null) - override fun ancSlice(width: Int): Flow<Slice?> { + override fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> { return localMediaRepository.currentConnectedDevice - .map { (it as? BluetoothMediaDevice)?.cachedDevice?.device?.getExtraControlUri(width) } + .map { + (it as? BluetoothMediaDevice) + ?.cachedDevice + ?.device + ?.getExtraControlUri(width, isCollapsed, hideLabel) + } .distinctUntilChanged() .flatMapLatest { sliceUri -> sliceUri ?: return@flatMapLatest flowOf(null) @@ -71,7 +78,11 @@ constructor( .flowOn(backgroundCoroutineContext) } - private fun BluetoothDevice.getExtraControlUri(width: Int): Uri? { + private fun BluetoothDevice.getExtraControlUri( + width: Int, + isCollapsed: Boolean, + hideLabel: Boolean + ): Uri? { val uri: String? = BluetoothUtils.getControlUriMetaData(this) uri ?: return null @@ -81,7 +92,8 @@ constructor( Uri.parse( "$uri$width" + "&version=${SliceParameters.VERSION}" + - "&is_collapsed=${SliceParameters.IS_COLLAPSED}" + "&is_collapsed=$isCollapsed" + + "&hide_label=$hideLabel" ) } } @@ -98,11 +110,5 @@ constructor( * 2) new slice */ const val VERSION = 2 - - /** - * Collapsed slice shows a single button, and expanded shows a row buttons. Supported since - * [VERSION]==2. - */ - const val IS_COLLAPSED = false } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt index 89b927480783..dc4be2696204 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt @@ -17,6 +17,7 @@ package com.android.systemui.volume.panel.component.anc.domain import com.android.systemui.volume.panel.component.anc.domain.interactor.AncSliceInteractor +import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria import javax.inject.Inject @@ -31,5 +32,6 @@ constructor( private val ancSliceInteractor: AncSliceInteractor, ) : ComponentAvailabilityCriteria { - override fun isAvailable(): Flow<Boolean> = ancSliceInteractor.ancSlice.map { it != null } + override fun isAvailable(): Flow<Boolean> = + ancSliceInteractor.ancSlices.map { it is AncSlices.Ready } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt index 91af622074a0..cefa26907710 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt @@ -20,16 +20,19 @@ import android.app.slice.Slice.HINT_ERROR import android.app.slice.SliceItem.FORMAT_SLICE import androidx.slice.Slice import com.android.systemui.volume.panel.component.anc.data.repository.AncSliceRepository +import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.shareIn +import kotlinx.coroutines.flow.stateIn /** Provides a valid slice from [AncSliceRepository]. */ @OptIn(ExperimentalCoroutinesApi::class) @@ -41,25 +44,35 @@ constructor( scope: CoroutineScope, ) { - // Start with a positive width to check is the Slice is available. - private val width = MutableStateFlow(1) + // Any positive width to check if the Slice is available. + private val buttonSliceWidth = MutableStateFlow(1) + private val popupSliceWidth = MutableStateFlow(1) - /** Provides a valid ANC slice. */ - val ancSlice: SharedFlow<Slice?> = - width - .flatMapLatest { width -> ancSliceRepository.ancSlice(width) } - .map { slice -> - if (slice?.isValidSlice() == true) { - slice + val ancSlices: StateFlow<AncSlices> = + combine( + buttonSliceWidth.flatMapLatest { + ancSlice(width = it, isCollapsed = true, hideLabel = true) + }, + popupSliceWidth.flatMapLatest { + ancSlice(width = it, isCollapsed = false, hideLabel = false) + } + ) { buttonSlice, popupSlice -> + if (buttonSlice != null && popupSlice != null) { + AncSlices.Ready(buttonSlice = buttonSlice, popupSlice = popupSlice) } else { - null + AncSlices.Unavailable } } - .shareIn(scope, SharingStarted.Eagerly, replay = 1) + .stateIn(scope, SharingStarted.Eagerly, AncSlices.Unavailable) - /** Updates the width of the [ancSlice] */ - fun changeWidth(newWidth: Int) { - width.value = newWidth + /** + * Provides a valid [isCollapsed] ANC slice for a given [width]. Use [hideLabel] == true to + * remove the labels from the [Slice]. + */ + private fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> { + return ancSliceRepository + .ancSlice(width = width, isCollapsed = isCollapsed, hideLabel = hideLabel) + .filter { it?.isValidSlice() != false } } private fun Slice.isValidSlice(): Boolean { @@ -73,4 +86,20 @@ constructor( } return false } + + /** + * Call this to update [AncSlices.Ready.popupSlice] width in a reaction to container size + * change. + */ + fun onPopupSliceWidthChanged(width: Int) { + popupSliceWidth.tryEmit(width) + } + + /** + * Call this to update [AncSlices.Ready.buttonSlice] width in a reaction to container size + * change. + */ + fun onButtonSliceWidthChanged(width: Int) { + buttonSliceWidth.tryEmit(width) + } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/model/AncSlices.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/model/AncSlices.kt new file mode 100644 index 000000000000..3cd4e672ce56 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/model/AncSlices.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.component.anc.domain.model + +import androidx.slice.Slice + +/** Modes current ANC slices state */ +sealed interface AncSlices { + + data class Ready( + val popupSlice: Slice, + val buttonSlice: Slice, + ) : AncSlices + + /** Couldn't one or both slices. */ + data object Unavailable : AncSlices +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt index eb96f6cad8f2..bee79bb68141 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt @@ -16,52 +16,56 @@ package com.android.systemui.volume.panel.component.anc.ui.viewmodel -import android.content.Context import androidx.slice.Slice -import com.android.systemui.common.shared.model.Icon -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.res.R +import com.android.systemui.volume.panel.component.anc.domain.AncAvailabilityCriteria import com.android.systemui.volume.panel.component.anc.domain.interactor.AncSliceInteractor -import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel +import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import javax.inject.Inject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** Volume Panel ANC component view model. */ +@OptIn(ExperimentalCoroutinesApi::class) @VolumePanelScope class AncViewModel @Inject constructor( - @Application private val context: Context, @VolumePanelScope private val coroutineScope: CoroutineScope, private val interactor: AncSliceInteractor, + private val availabilityCriteria: AncAvailabilityCriteria, ) { + val isAvailable: Flow<Boolean> + get() = availabilityCriteria.isAvailable() + /** ANC [Slice]. Null when there is no slice available for ANC. */ - val slice: StateFlow<Slice?> = - interactor.ancSlice.stateIn(coroutineScope, SharingStarted.Eagerly, null) + val popupSlice: StateFlow<Slice?> = + interactor.ancSlices + .filterIsInstance<AncSlices.Ready>() + .map { it.popupSlice } + .stateIn(coroutineScope, SharingStarted.Eagerly, null) - /** - * ButtonViewModel to be shown in the VolumePanel. Null when there is no ANC Slice available. - */ - val button: StateFlow<ButtonViewModel?> = - interactor.ancSlice - .map { slice -> - slice?.let { - ButtonViewModel( - Icon.Resource(R.drawable.ic_noise_aware, null), - context.getString(R.string.volume_panel_noise_control_title) - ) - } - } + /** Button [Slice] to be shown in the VolumePanel. Null when there is no ANC Slice available. */ + val buttonSlice: StateFlow<Slice?> = + interactor.ancSlices + .filterIsInstance<AncSlices.Ready>() + .map { it.buttonSlice } .stateIn(coroutineScope, SharingStarted.Eagerly, null) - /** Call this to update [slice] width in a reaction to container size change. */ - fun changeSliceWidth(width: Int) { - interactor.changeWidth(width) + /** Call this to update [popupSlice] width in a reaction to container size change. */ + fun onPopupSliceWidthChanged(width: Int) { + interactor.onPopupSliceWidthChanged(width) + } + + /** Call this to update [buttonSlice] width in a reaction to container size change. */ + fun onButtonSliceWidthChanged(width: Int) { + interactor.onButtonSliceWidthChanged(width) } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt index 04d7b1fa6532..3ca9cdfe285c 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt @@ -18,8 +18,10 @@ package com.android.systemui.volume.panel.component.bottombar.ui.viewmodel import android.content.Intent import android.provider.Settings +import com.android.internal.logging.UiEventLogger import com.android.systemui.plugins.ActivityStarter import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel import javax.inject.Inject @@ -29,6 +31,7 @@ class BottomBarViewModel constructor( private val activityStarter: ActivityStarter, private val volumePanelViewModel: VolumePanelViewModel, + private val uiEventLogger: UiEventLogger, ) { fun onDoneClicked() { @@ -36,6 +39,7 @@ constructor( } fun onSettingsClicked() { + uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_SOUND_SETTINGS_CLICKED) activityStarter.startActivityDismissingKeyguard( /* intent = */ Intent(Settings.ACTION_SOUND_SETTINGS), /* onlyProvisioned = */ false, diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt index aab825fb9f5e..85da1d0efe3a 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt @@ -16,18 +16,36 @@ package com.android.systemui.volume.panel.component.captioning.domain +import com.android.internal.logging.UiEventLogger import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.shareIn @VolumePanelScope class CaptioningAvailabilityCriteria @Inject -constructor(private val captioningInteractor: CaptioningInteractor) : - ComponentAvailabilityCriteria { +constructor( + captioningInteractor: CaptioningInteractor, + @VolumePanelScope private val scope: CoroutineScope, + private val uiEventLogger: UiEventLogger, +) : ComponentAvailabilityCriteria { - override fun isAvailable(): Flow<Boolean> = + private val availability = captioningInteractor.isSystemAudioCaptioningUiEnabled + .onEach { visible -> + uiEventLogger.log( + if (visible) VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_SHOWN + else VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_GONE + ) + } + .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1) + + override fun isAvailable(): Flow<Boolean> = availability } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt index 92f8f221d918..01421f86311f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt @@ -17,11 +17,13 @@ package com.android.systemui.volume.panel.component.captioning.ui.viewmodel import android.content.Context +import com.android.internal.logging.UiEventLogger import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor import com.android.systemui.common.shared.model.Icon import com.android.systemui.res.R import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted @@ -38,6 +40,7 @@ constructor( private val context: Context, private val captioningInteractor: CaptioningInteractor, @VolumePanelScope private val coroutineScope: CoroutineScope, + private val uiEventLogger: UiEventLogger, ) { val buttonViewModel: StateFlow<ToggleButtonViewModel?> = @@ -57,6 +60,13 @@ constructor( .stateIn(coroutineScope, SharingStarted.Eagerly, null) fun setIsSystemAudioCaptioningEnabled(enabled: Boolean) { + uiEventLogger.logWithPosition( + VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_CLICKED, + 0, + null, + if (enabled) VolumePanelUiEvent.LIVE_CAPTION_TOGGLE_ENABLED + else VolumePanelUiEvent.LIVE_CAPTION_TOGGLE_DISABLED + ) coroutineScope.launch { captioningInteractor.setIsSystemAudioCaptioningEnabled(enabled) } } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt index fc9602e6017f..6b237f8e329b 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt @@ -17,6 +17,7 @@ package com.android.systemui.volume.panel.component.mediaoutput.ui.viewmodel import android.content.Context +import com.android.internal.logging.UiEventLogger import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Color import com.android.systemui.common.shared.model.Icon @@ -26,6 +27,7 @@ import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlayback import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -48,6 +50,7 @@ constructor( private val actionsInteractor: MediaOutputActionsInteractor, private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, interactor: MediaOutputInteractor, + private val uiEventLogger: UiEventLogger, ) { private val sessionWithPlayback: StateFlow<SessionWithPlayback?> = @@ -126,6 +129,7 @@ constructor( ) fun onBarClick(expandable: Expandable) { + uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_MEDIA_OUTPUT_CLICKED) actionsInteractor.onBarClick(sessionWithPlayback.value, expandable) } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt index 9f9275baf4f9..e5c5a655c73e 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt @@ -16,13 +16,10 @@ package com.android.systemui.volume.panel.component.spatial.ui.viewmodel -import com.android.systemui.common.shared.model.Color import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel data class SpatialAudioButtonViewModel( val model: SpatialAudioEnabledModel, val button: ToggleButtonViewModel, - val iconColor: Color, - val labelColor: Color, ) diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt index f022039e9cde..b5e9ed27d664 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt @@ -17,7 +17,7 @@ package com.android.systemui.volume.panel.component.spatial.ui.viewmodel import android.content.Context -import com.android.systemui.common.shared.model.Color +import com.android.internal.logging.UiEventLogger import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R @@ -29,6 +29,7 @@ import com.android.systemui.volume.panel.component.spatial.domain.interactor.Spa import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioAvailabilityModel import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted @@ -46,6 +47,7 @@ constructor( @VolumePanelScope private val scope: CoroutineScope, availabilityCriteria: SpatialAudioAvailabilityCriteria, private val interactor: SpatialAudioComponentInteractor, + private val uiEventLogger: UiEventLogger, ) { val spatialAudioButton: StateFlow<ButtonViewModel?> = @@ -76,31 +78,25 @@ constructor( val isChecked = isEnabled == currentIsEnabled val buttonViewModel: ToggleButtonViewModel = isEnabled.toViewModel(isChecked) - SpatialAudioButtonViewModel( - button = buttonViewModel, - model = isEnabled, - iconColor = - Color.Attribute( - if (isChecked) { - com.android.internal.R.attr.materialColorOnPrimaryContainer - } else { - com.android.internal.R.attr.materialColorOnSurfaceVariant - } - ), - labelColor = - Color.Attribute( - if (isChecked) { - com.android.internal.R.attr.materialColorOnSurface - } else { - com.android.internal.R.attr.materialColorOnSurfaceVariant - } - ), - ) + SpatialAudioButtonViewModel(button = buttonViewModel, model = isEnabled) } } .stateIn(scope, SharingStarted.Eagerly, emptyList()) fun setEnabled(model: SpatialAudioEnabledModel) { + uiEventLogger.logWithPosition( + VolumePanelUiEvent.VOLUME_PANEL_SPATIAL_AUDIO_TOGGLE_CLICKED, + 0, + null, + when (model) { + SpatialAudioEnabledModel.Disabled -> 0 + SpatialAudioEnabledModel.SpatialAudioEnabled -> 1 + SpatialAudioEnabledModel.HeadTrackingEnabled -> 2 + else -> { + -1 + } + } + ) scope.launch { interactor.setEnabled(model) } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt deleted file mode 100644 index ecd89eab1d4b..000000000000 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.volume.panel.component.volume.domain.interactor - -import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope -import javax.inject.Inject - -/** Converts from slider value to volume and back. */ -@VolumePanelScope -class VolumeSliderInteractor @Inject constructor() { - - /** mimic percentage volume setting */ - private val displayValueRange: ClosedFloatingPointRange<Float> = 0f..100f - - /** - * Translates [volume], that belongs to [volumeRange] to the value that belongs to - * [displayValueRange]. - */ - fun processVolumeToValue( - volume: Int, - volumeRange: ClosedRange<Int>, - ): Float { - val currentRangeStart: Float = volumeRange.start.toFloat() - val targetRangeStart: Float = displayValueRange.start - val currentRangeLength: Float = (volumeRange.endInclusive.toFloat() - currentRangeStart) - val targetRangeLength: Float = displayValueRange.endInclusive - targetRangeStart - if (currentRangeLength == 0f || targetRangeLength == 0f) { - return 0f - } - val volumeFraction: Float = (volume.toFloat() - currentRangeStart) / currentRangeLength - return targetRangeStart + volumeFraction * targetRangeLength - } -} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt index 57b5d570fbbd..c8cd6fdbea70 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt @@ -18,13 +18,14 @@ package com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel import android.content.Context import android.media.AudioManager +import com.android.internal.logging.UiEventLogger import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.settingslib.volume.shared.model.AudioStreamModel import com.android.settingslib.volume.shared.model.RingerMode import com.android.systemui.common.shared.model.Icon import com.android.systemui.res.R -import com.android.systemui.volume.panel.component.volume.domain.interactor.VolumeSliderInteractor +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -44,7 +45,7 @@ constructor( @Assisted private val coroutineScope: CoroutineScope, private val context: Context, private val audioVolumeInteractor: AudioVolumeInteractor, - private val volumeSliderInteractor: VolumeSliderInteractor, + private val uiEventLogger: UiEventLogger, ) : SliderViewModel { private val audioStream = audioStreamWrapper.audioStream @@ -71,6 +72,19 @@ constructor( AudioStream(AudioManager.STREAM_ALARM) to R.string.stream_alarm_unavailable, AudioStream(AudioManager.STREAM_MUSIC) to R.string.stream_media_unavailable, ) + private val uiEventByStream = + mapOf( + AudioStream(AudioManager.STREAM_MUSIC) to + VolumePanelUiEvent.VOLUME_PANEL_MUSIC_SLIDER_TOUCHED, + AudioStream(AudioManager.STREAM_VOICE_CALL) to + VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED, + AudioStream(AudioManager.STREAM_RING) to + VolumePanelUiEvent.VOLUME_PANEL_RING_SLIDER_TOUCHED, + AudioStream(AudioManager.STREAM_NOTIFICATION) to + VolumePanelUiEvent.VOLUME_PANEL_NOTIFICATION_SLIDER_TOUCHED, + AudioStream(AudioManager.STREAM_ALARM) to + VolumePanelUiEvent.VOLUME_PANEL_ALARM_SLIDER_TOUCHED, + ) override val slider: StateFlow<SliderState> = combine( @@ -90,6 +104,10 @@ constructor( } } + override fun onValueChangeFinished() { + uiEventByStream[audioStream]?.let { uiEventLogger.log(it) } + } + override fun toggleMuted(state: SliderState) { val audioViewModel = state as? State audioViewModel ?: return @@ -105,10 +123,6 @@ constructor( return State( value = volume.toFloat(), valueRange = volumeRange.first.toFloat()..volumeRange.last.toFloat(), - valueText = - SliderViewModel.formatValue( - volumeSliderInteractor.processVolumeToValue(volume, volumeRange) - ), icon = getIcon(ringerMode), label = labelsByStream[audioStream]?.let(context::getString) ?: error("No label for the stream: $audioStream"), @@ -157,7 +171,6 @@ constructor( override val valueRange: ClosedFloatingPointRange<Float>, override val icon: Icon, override val label: String, - override val valueText: String, override val disabledMessage: String?, override val isEnabled: Boolean, override val a11yStep: Int, diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt index 8d8fa17bf986..956ab66ac0c3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt @@ -22,7 +22,6 @@ import com.android.systemui.common.shared.model.Icon import com.android.systemui.res.R import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession -import com.android.systemui.volume.panel.component.volume.domain.interactor.VolumeSliderInteractor import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -41,7 +40,6 @@ constructor( @Assisted private val coroutineScope: CoroutineScope, private val context: Context, private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, - private val volumeSliderInteractor: VolumeSliderInteractor, ) : SliderViewModel { override val slider: StateFlow<SliderState> = @@ -56,6 +54,8 @@ constructor( } } + override fun onValueChangeFinished() {} + override fun toggleMuted(state: SliderState) { // do nothing because this action isn't supported for Cast sliders. } @@ -66,13 +66,6 @@ constructor( value = currentVolume.toFloat(), valueRange = volumeRange.first.toFloat()..volumeRange.last.toFloat(), icon = Icon.Resource(R.drawable.ic_cast, null), - valueText = - SliderViewModel.formatValue( - volumeSliderInteractor.processVolumeToValue( - volume = currentVolume, - volumeRange = volumeRange, - ) - ), label = context.getString(R.string.media_device_cast), isEnabled = true, a11yStep = 1 @@ -83,13 +76,13 @@ constructor( override val value: Float, override val valueRange: ClosedFloatingPointRange<Float>, override val icon: Icon, - override val valueText: String, override val label: String, override val isEnabled: Boolean, override val a11yStep: Int, ) : SliderState { override val disabledMessage: String? get() = null + override val isMutable: Boolean get() = false } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt index 8eb0b8947c37..d71a9d8dae94 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt @@ -28,7 +28,6 @@ sealed interface SliderState { val valueRange: ClosedFloatingPointRange<Float> val icon: Icon? val isEnabled: Boolean - val valueText: String val label: String /** * A11y slider controls works by adjusting one step up or down. The default slider step isn't @@ -42,7 +41,6 @@ sealed interface SliderState { override val value: Float = 0f override val valueRange: ClosedFloatingPointRange<Float> = 0f..1f override val icon: Icon? = null - override val valueText: String = "" override val label: String = "" override val disabledMessage: String? = null override val a11yStep: Int = 0 diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt index e78f833086f8..7ded8c5c9fc1 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt @@ -25,10 +25,7 @@ interface SliderViewModel { fun onValueChanged(state: SliderState, newValue: Float) - fun toggleMuted(state: SliderState) - - companion object { + fun onValueChangeFinished() - fun formatValue(value: Float): String = "%.0f".format(value) - } + fun toggleMuted(state: SliderState) } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt index d1d539003f93..f889ed6e06be 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt @@ -17,6 +17,7 @@ package com.android.systemui.volume.panel.dagger import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria +import com.android.systemui.volume.panel.domain.VolumePanelStartable import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent import dagger.Module @@ -31,4 +32,6 @@ interface DefaultMultibindsModule { @Multibinds fun criteriaMap(): Map<VolumePanelComponentKey, ComponentAvailabilityCriteria> @Multibinds fun components(): Map<VolumePanelComponentKey, VolumePanelUiComponent> + + @Multibinds fun startables(): Set<VolumePanelStartable> } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt index d868c33d0887..ec64f3d93012 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt @@ -16,6 +16,7 @@ package com.android.systemui.volume.panel.dagger +import com.android.systemui.volume.dagger.UiEventLoggerStartableModule import com.android.systemui.volume.panel.component.anc.AncModule import com.android.systemui.volume.panel.component.bottombar.BottomBarModule import com.android.systemui.volume.panel.component.captioning.CaptioningModule @@ -25,6 +26,7 @@ import com.android.systemui.volume.panel.component.volume.VolumeSlidersModule import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import com.android.systemui.volume.panel.domain.DomainModule +import com.android.systemui.volume.panel.domain.VolumePanelStartable import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor import com.android.systemui.volume.panel.ui.UiModule import com.android.systemui.volume.panel.ui.composable.ComponentsFactory @@ -47,6 +49,7 @@ import kotlinx.coroutines.CoroutineScope DefaultMultibindsModule::class, DomainModule::class, UiModule::class, + UiEventLoggerStartableModule::class, // Components modules BottomBarModule::class, AncModule::class, @@ -66,6 +69,8 @@ interface VolumePanelComponent { fun componentsLayoutManager(): ComponentsLayoutManager + fun volumePanelStartables(): Set<VolumePanelStartable> + @Subcomponent.Factory interface Factory : VolumePanelComponentFactory { diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/domain/VolumePanelStartable.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/VolumePanelStartable.kt new file mode 100644 index 000000000000..9c39f5e75f88 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/VolumePanelStartable.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.domain + +/** Code that needs to be run when Volume Panel is started.. */ +interface VolumePanelStartable { + fun start() +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/VolumePanelUiEvent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/VolumePanelUiEvent.kt new file mode 100644 index 000000000000..8b8714fcca8c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/VolumePanelUiEvent.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume.panel.ui + +import com.android.internal.logging.UiEvent +import com.android.internal.logging.UiEventLogger + +/** UI events for Volume Panel. */ +enum class VolumePanelUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum { + @UiEvent(doc = "The volume panel is shown") VOLUME_PANEL_SHOWN(1634), + @UiEvent(doc = "The volume panel is gone") VOLUME_PANEL_GONE(1635), + @UiEvent(doc = "Media output is clicked") VOLUME_PANEL_MEDIA_OUTPUT_CLICKED(1636), + @UiEvent(doc = "Audio mode changed to normal") VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_NORMAL(1680), + @UiEvent(doc = "Audio mode changed to calling") VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_CALLING(1681), + @UiEvent(doc = "Sound settings is clicked") VOLUME_PANEL_SOUND_SETTINGS_CLICKED(1638), + @UiEvent(doc = "The music volume slider is touched") VOLUME_PANEL_MUSIC_SLIDER_TOUCHED(1639), + @UiEvent(doc = "The voice call volume slider is touched") + VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED(1640), + @UiEvent(doc = "The ring volume slider is touched") VOLUME_PANEL_RING_SLIDER_TOUCHED(1641), + @UiEvent(doc = "The notification volume slider is touched") + VOLUME_PANEL_NOTIFICATION_SLIDER_TOUCHED(1642), + @UiEvent(doc = "The alarm volume slider is touched") VOLUME_PANEL_ALARM_SLIDER_TOUCHED(1643), + @UiEvent(doc = "Live caption toggle is shown") VOLUME_PANEL_LIVE_CAPTION_TOGGLE_SHOWN(1644), + @UiEvent(doc = "Live caption toggle is gone") VOLUME_PANEL_LIVE_CAPTION_TOGGLE_GONE(1645), + @UiEvent(doc = "Live caption toggle is clicked") VOLUME_PANEL_LIVE_CAPTION_TOGGLE_CLICKED(1646), + @UiEvent(doc = "Spatial audio button is shown") VOLUME_PANEL_SPATIAL_AUDIO_BUTTON_SHOWN(1647), + @UiEvent(doc = "Spatial audio button is gone") VOLUME_PANEL_SPATIAL_AUDIO_BUTTON_GONE(1648), + @UiEvent(doc = "Spatial audio popup is shown") VOLUME_PANEL_SPATIAL_AUDIO_POP_UP_SHOWN(1649), + @UiEvent(doc = "Spatial audio toggle is clicked") + VOLUME_PANEL_SPATIAL_AUDIO_TOGGLE_CLICKED(1650), + @UiEvent(doc = "ANC button is shown") VOLUME_PANEL_ANC_BUTTON_SHOWN(1651), + @UiEvent(doc = "ANC button is gone") VOLUME_PANEL_ANC_BUTTON_GONE(1652), + @UiEvent(doc = "ANC popup is shown") VOLUME_PANEL_ANC_POPUP_SHOWN(1653), + @UiEvent(doc = "ANC toggle is clicked") VOLUME_PANEL_ANC_TOGGLE_CLICKED(1654); + + override fun getId() = metricId + + companion object { + const val LIVE_CAPTION_TOGGLE_DISABLED = 0 + const val LIVE_CAPTION_TOGGLE_ENABLED = 1 + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt index c728fefa77e6..ccb91ac79b6a 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt @@ -21,8 +21,10 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels +import com.android.internal.logging.UiEventLogger import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag +import com.android.systemui.volume.panel.ui.VolumePanelUiEvent import com.android.systemui.volume.panel.ui.composable.VolumePanelRoot import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel import javax.inject.Inject @@ -34,6 +36,7 @@ constructor( private val volumePanelViewModelFactory: Provider<VolumePanelViewModel.Factory>, private val volumePanelFlag: VolumePanelFlag, private val configurationController: ConfigurationController, + private val uiEventLogger: UiEventLogger, ) : ComponentActivity() { private val viewModel: VolumePanelViewModel by @@ -43,8 +46,16 @@ constructor( enableEdgeToEdge() super.onCreate(savedInstanceState) volumePanelFlag.assertNewVolumePanel() - - setContent { VolumePanelRoot(viewModel = viewModel, onDismiss = ::finish) } + uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_SHOWN) + setContent { + VolumePanelRoot( + viewModel = viewModel, + onDismiss = { + uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_GONE) + finish() + } + ) + } } override fun onContentChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt index 5ae827ff4e3d..1de4fd1f9593 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt @@ -26,6 +26,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.onConfigChanged import com.android.systemui.volume.panel.dagger.VolumePanelComponent import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory +import com.android.systemui.volume.panel.domain.VolumePanelStartable import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor import com.android.systemui.volume.panel.ui.composable.ComponentsFactory import com.android.systemui.volume.panel.ui.layout.ComponentsLayout @@ -109,6 +110,10 @@ class VolumePanelViewModel( replay = 1, ) + init { + volumePanelComponent.volumePanelStartables().onEach(VolumePanelStartable::start) + } + fun dismissPanel() { mutablePanelVisibility.update { false } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index ca55dd8ba5fa..e72027a921b7 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -142,7 +142,6 @@ class ClockEventControllerTest : SysuiTestCase() { context.resources, context, mainExecutor, - IMMEDIATE, bgExecutor, clockBuffers, withDeps.featureFlags, @@ -320,9 +319,19 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForDozeAmountTransition_updatesClockDozeAmount() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) - whenever(keyguardTransitionInteractor.lockscreenToAodTransition) + whenever( + keyguardTransitionInteractor.transition( + KeyguardState.LOCKSCREEN, + KeyguardState.AOD + ) + ) .thenReturn(transitionStep) - whenever(keyguardTransitionInteractor.aodToLockscreenTransition) + whenever( + keyguardTransitionInteractor.transition( + KeyguardState.AOD, + KeyguardState.LOCKSCREEN + ) + ) .thenReturn(transitionStep) val job = underTest.listenForDozeAmountTransition(this) @@ -362,6 +371,27 @@ class ClockEventControllerTest : SysuiTestCase() { } @Test + fun listenForTransitionToLSFromOccluded_updatesClockDozeAmountToOne() = + runBlocking(IMMEDIATE) { + val transitionStep = MutableStateFlow(TransitionStep()) + whenever(keyguardTransitionInteractor.transitionStepsToState(KeyguardState.LOCKSCREEN)) + .thenReturn(transitionStep) + + val job = underTest.listenForAnyStateToLockscreenTransition(this) + transitionStep.value = + TransitionStep( + from = KeyguardState.OCCLUDED, + to = KeyguardState.LOCKSCREEN, + transitionState = TransitionState.STARTED, + ) + yield() + + verify(animations, times(2)).doze(0f) + + job.cancel() + } + + @Test fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) @@ -379,6 +409,27 @@ class ClockEventControllerTest : SysuiTestCase() { verify(animations, never()).doze(1f) + job.cancel() + } + + @Test + fun listenForAnyStateToLockscreenTransition_neverUpdatesClockDozeAmount() = + runBlocking(IMMEDIATE) { + val transitionStep = MutableStateFlow(TransitionStep()) + whenever(keyguardTransitionInteractor.transitionStepsToState(KeyguardState.LOCKSCREEN)) + .thenReturn(transitionStep) + + val job = underTest.listenForAnyStateToLockscreenTransition(this) + transitionStep.value = + TransitionStep( + from = KeyguardState.AOD, + to = KeyguardState.LOCKSCREEN, + transitionState = TransitionState.STARTED, + ) + yield() + + verify(animations, never()).doze(0f) + job.cancel() } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java index a2499615e18c..319b61512f12 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java @@ -205,9 +205,9 @@ public class KeyguardClockSwitchControllerBaseTest extends SysuiTestCase { when(mClockRegistry.createCurrentClock()).thenReturn(mClockController); when(mClockEventController.getClock()).thenReturn(mClockController); when(mSmallClockController.getConfig()) - .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false)); + .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false, false)); when(mLargeClockController.getConfig()) - .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false)); + .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false, false)); mSliceView = new View(getContext()); when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index 9d81b960336f..99b5a4b631a7 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -272,9 +272,9 @@ public class KeyguardClockSwitchControllerTest extends KeyguardClockSwitchContro assertEquals(View.VISIBLE, mFakeDateView.getVisibility()); when(mSmallClockController.getConfig()) - .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false)); + .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false, true)); when(mLargeClockController.getConfig()) - .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false)); + .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false, true)); verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture()); listenerArgumentCaptor.getValue().onCurrentClockChanged(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java index 11fe86277903..b2828a41c4b0 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java @@ -98,7 +98,7 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll public void updatePosition_primaryClockAnimation() { ClockController mockClock = mock(ClockController.class); when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock); - when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", false, true)); + when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", false, true, false)); mController.updatePosition(10, 15, 20f, true); @@ -113,7 +113,7 @@ public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControll public void updatePosition_alternateClockAnimation() { ClockController mockClock = mock(ClockController.class); when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock); - when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", true, true)); + when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", true, true, false)); mController.updatePosition(10, 15, 20f, true); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java index f924ab4a4617..bcea4116d169 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java @@ -36,6 +36,7 @@ import android.util.Pair; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; +import android.widget.ImageView; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; @@ -78,6 +79,7 @@ public class LegacyLockIconViewControllerBaseTest extends SysuiTestCase { protected final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); protected @Mock DeviceEntryInteractor mDeviceEntryInteractor; protected @Mock LockIconView mLockIconView; + protected @Mock ImageView mLockIcon; protected @Mock AnimatedStateListDrawable mIconDrawable; protected @Mock Context mContext; protected @Mock Resources mResources; @@ -146,8 +148,10 @@ public class LegacyLockIconViewControllerBaseTest extends SysuiTestCase { when(mStatusBarStateController.isDozing()).thenReturn(false); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); - mSetFlagsRule.disableFlags(Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR); - mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); + if (!Flags.sceneContainer()) { + mSetFlagsRule.disableFlags(Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR); + mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); + } mFeatureFlags = new FakeFeatureFlags(); mFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false); @@ -172,8 +176,7 @@ public class LegacyLockIconViewControllerBaseTest extends SysuiTestCase { mFeatureFlags, mPrimaryBouncerInteractor, mContext, - () -> mDeviceEntryInteractor, - mKosmos.getFakeSceneContainerFlags() + () -> mDeviceEntryInteractor ); } @@ -225,6 +228,7 @@ public class LegacyLockIconViewControllerBaseTest extends SysuiTestCase { protected void setupLockIconViewMocks() { when(mLockIconView.getResources()).thenReturn(mResources); when(mLockIconView.getContext()).thenReturn(mContext); + when(mLockIconView.getLockIcon()).thenReturn(mLockIcon); } protected void resetLockIconView() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java index 868984233816..255c7d909194 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java @@ -43,6 +43,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.biometrics.UdfpsController; import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams; import com.android.systemui.doze.util.BurnInHelperKt; +import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.statusbar.StatusBarState; import org.junit.Test; @@ -373,7 +374,6 @@ public class LegacyLockIconViewControllerTest extends LegacyLockIconViewControll @Test public void longPress_showBouncer_sceneContainerNotEnabled() { init(/* useMigrationFlag= */ false); - mKosmos.getFakeSceneContainerFlags().setEnabled(false); when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(false); // WHEN longPress @@ -385,9 +385,9 @@ public class LegacyLockIconViewControllerTest extends LegacyLockIconViewControll } @Test + @EnableSceneContainer public void longPress_showBouncer() { init(/* useMigrationFlag= */ false); - mKosmos.getFakeSceneContainerFlags().setEnabled(true); when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(false); // WHEN longPress @@ -399,9 +399,9 @@ public class LegacyLockIconViewControllerTest extends LegacyLockIconViewControll } @Test + @EnableSceneContainer public void longPress_falsingTriggered_doesNotShowBouncer() { init(/* useMigrationFlag= */ false); - mKosmos.getFakeSceneContainerFlags().setEnabled(true); when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(true); // WHEN longPress diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index c20367efa5da..d267ad449f45 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -1274,6 +1274,28 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Test + public void delayedFaceSensorLocationChangesAddsFaceScanningOverlay() { + setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, + null /* roundedTopDrawable */, null /* roundedBottomDrawable */, + 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); + mScreenDecorations.start(); + verifyFaceScanningViewExists(false); // face scanning view not added yet + + // WHEN the sensor location is updated + mFaceScanningProviders = new ArrayList<>(); + mFaceScanningProviders.add(mFaceScanningDecorProvider); + when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders); + when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(true); + final Point location = new Point(); + mFakeFacePropertyRepository.setSensorLocation(location); + mScreenDecorations.onFaceSensorLocationChanged(location); + mExecutor.runAllReady(); + + // THEN the face scanning view is added + verifyFaceScanningViewExists(true); + } + + @Test public void testPrivacyDotShowingListenerWorkWellWithNullParameter() { mPrivacyDotShowingListener.onPrivacyDotShown(null); mPrivacyDotShowingListener.onPrivacyDotHidden(null); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java index 69cd592d8f50..44207a0c434b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -181,7 +181,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -220,7 +220,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { mWaitAnimationDuration, /* targetScale= */ 1.0f, DEFAULT_CENTER_X, DEFAULT_CENTER_Y, mAnimationCallback); - verify(mSpyController).enableWindowMagnificationInternal(1.0f, DEFAULT_CENTER_X, + verify(mSpyController).updateWindowMagnificationInternal(1.0f, DEFAULT_CENTER_X, DEFAULT_CENTER_Y, 0f, 0f); verify(mAnimationCallback).onResult(true); } @@ -244,7 +244,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { advanceTimeBy(mWaitAnimationDuration); }); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -299,7 +299,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { advanceTimeBy(mWaitAnimationDuration); }); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -341,7 +341,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { advanceTimeBy(mWaitAnimationDuration); }); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -377,7 +377,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { advanceTimeBy(mWaitAnimationDuration); }); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -439,7 +439,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { enableWindowMagnificationAndWaitAnimating( mWaitAnimationDuration, Float.NaN, Float.NaN, Float.NaN, mAnimationCallback2); - verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(), + verify(mSpyController, never()).updateWindowMagnificationInternal(anyFloat(), anyFloat(), anyFloat()); verify(mAnimationCallback).onResult(false); verify(mAnimationCallback2).onResult(true); @@ -477,9 +477,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { }); // Verify the method is called in - // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once and - // {@link Animator.AnimatorListener#onAnimationEnd} once in {@link ValueAnimator#end()} - verify(mSpyController, times(2)).enableWindowMagnificationInternal( + // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once + verify(mSpyController).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -526,7 +525,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, Float.NaN, Float.NaN, Float.NaN, mAnimationCallback2); - verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(), + verify(mSpyController, never()).updateWindowMagnificationInternal(anyFloat(), anyFloat(), anyFloat()); verify(mSpyController, never()).deleteWindowMagnification(); verify(mAnimationCallback).onResult(false); @@ -551,7 +550,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { advanceTimeBy(mWaitAnimationDuration); }); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -594,10 +593,10 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { final float expectedY = (int) (windowBounds.exactCenterY() + expectedOffset - defaultMagnificationWindowSize / 2); - // This is called 5 times when (1) first creating WindowlessMirrorWindow (2) SurfaceView is + // This is called 4 times when (1) first creating WindowlessMirrorWindow (2) SurfaceView is // created and we place the mirrored content as a child of the SurfaceView - // (3) the animation starts (4) the animation updates (5) the animation ends - verify(mTransaction, times(5)) + // (3) the animation starts (4) the animation updates + verify(mTransaction, times(4)) .setPosition(any(SurfaceControl.class), eq(expectedX), eq(expectedY)); } @@ -720,7 +719,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback); - verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(), + verify(mSpyController, never()).updateWindowMagnificationInternal(anyFloat(), anyFloat(), anyFloat()); verify(mAnimationCallback).onResult(true); } @@ -733,7 +732,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { resetMockObjects(); deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback); - verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal( + verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -788,9 +787,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { waitForIdleSync(); // Verify the method is called in - // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once and - // {@link Animator.AnimatorListener#onAnimationEnd} once in {@link ValueAnimator#end()} - verify(mSpyController, times(2)).enableWindowMagnificationInternal( + // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once + verify(mSpyController).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -832,10 +830,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback2); // Verify the method is called in - // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once and - // {@link Animator.AnimatorListener#onAnimationEnd} once when running the animation at - // the final duration time. - verify(mSpyController, times(2)).enableWindowMagnificationInternal( + // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once + verify(mSpyController).updateWindowMagnificationInternal( mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture(), mOffsetXCaptor.capture(), mOffsetYCaptor.capture()); @@ -1040,17 +1036,17 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { } @Override - void enableWindowMagnificationInternal(float scale, float centerX, float centerY) { - super.enableWindowMagnificationInternal(scale, centerX, centerY); - mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY); + void updateWindowMagnificationInternal(float scale, float centerX, float centerY) { + super.updateWindowMagnificationInternal(scale, centerX, centerY); + mSpyController.updateWindowMagnificationInternal(scale, centerX, centerY); } @Override - void enableWindowMagnificationInternal(float scale, float centerX, float centerY, + void updateWindowMagnificationInternal(float scale, float centerX, float centerY, float magnificationOffsetFrameRatioX, float magnificationOffsetFrameRatioY) { - super.enableWindowMagnificationInternal(scale, centerX, centerY, + super.updateWindowMagnificationInternal(scale, centerX, centerY, magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY); - mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY, + mSpyController.updateWindowMagnificationInternal(scale, centerX, centerY, magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 6f285fb01cf5..cb42078460c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -273,7 +273,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnification_showControlAndNotifyBoundsChanged() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -341,7 +341,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnification_systemGestureExclusionRectsIsSet() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); // Wait for Rects updated. @@ -358,7 +358,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize)); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -373,7 +373,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void deleteWindowMagnification_destroyControlAndUnregisterComponentCallback() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); @@ -391,7 +391,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { setSystemGestureInsets(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, bounds.bottom); }); ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag); @@ -407,7 +407,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void deleteWindowMagnification_notifySourceBoundsChanged() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); @@ -423,7 +423,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void moveMagnifier_schedulesFrame() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.moveWindowMagnifier(100f, 100f); }); @@ -506,7 +506,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void setScale_enabled_expectedValueAndUpdateStateDescription() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(2.0f, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(2.0f, Float.NaN, Float.NaN)); mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f)); @@ -539,7 +539,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final float displayWidth = windowBounds.width(); final PointF magnifiedCenter = new PointF(center, center + 5f); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, magnifiedCenter.x, magnifiedCenter.y); // Get the center again in case the center we set is out of screen. magnifiedCenter.set(mWindowMagnificationController.getCenterX(), @@ -582,7 +582,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final float expectedRatio = 0.5f; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -621,8 +621,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { preferredWindowSize.toString()) .commit(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController - .enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, + Float.NaN); }); // Change screen density and size to trigger restoring the preferred window size @@ -649,7 +649,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); final int screenSize = mWindowManager.getCurrentWindowMetrics().getBounds().width() * 10; @@ -674,7 +674,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); Mockito.reset(mWindowManager); Mockito.reset(mMirrorWindowControl); @@ -703,7 +703,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void initializeA11yNode_enabled_expectedValues() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN, Float.NaN); }); final View mirrorView = mWindowManager.getAttachedView(); @@ -727,7 +727,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { public void performA11yActions_visible_expectedResults() { final int displayId = mContext.getDisplayId(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(1.5f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(1.5f, Float.NaN, Float.NaN); }); @@ -761,7 +761,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { public void performA11yActions_visible_notifyAccessibilityActionPerformed() { final int displayId = mContext.getDisplayId(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN, Float.NaN); }); @@ -774,7 +774,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void windowMagnifierEditMode_performA11yClickAction_exitEditMode() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setEditMagnifierSizeMode(true); }); @@ -812,7 +812,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -852,7 +852,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -888,7 +888,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int startingHeight = windowBounds.height(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -908,7 +908,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int startingHeight = windowBounds.height(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -931,7 +931,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { /* base= */ 1, /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -971,7 +971,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -1007,7 +1007,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int startingSize = mMinWindowSize; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -1027,7 +1027,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int startingSize = mMinWindowSize; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -1043,7 +1043,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnification_hasA11yWindowTitle() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -1054,12 +1054,12 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnificationWithScaleLessThanOne_enabled_disabled() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(0.9f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(0.9f, Float.NaN, Float.NaN); }); @@ -1078,7 +1078,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int newRotation = simulateRotateTheDevice(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); assertEquals(newRotation, mWindowMagnificationController.mRotation); @@ -1087,7 +1087,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnification_registerComponentCallback() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); @@ -1098,7 +1098,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { public void onLocaleChanged_enabled_updateA11yWindowTitle() { final String newA11yWindowTitle = "new a11y window title"; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); final TestableResources testableResources = getContext().getOrCreateTestableResources(); @@ -1116,7 +1116,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void onSingleTap_enabled_scaleAnimates() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -1143,7 +1143,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); setSystemGestureInsets(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -1161,7 +1161,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { setSystemGestureInsets(); mInstrumentation.runOnMainSync( () -> { - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN); }); @@ -1197,7 +1197,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { setSystemGestureInsets(); mInstrumentation.runOnMainSync( () -> { - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN); }); @@ -1232,7 +1232,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int expectedWindowHeight = minimumWindowSize; final int expectedWindowWidth = minimumWindowSize; mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1259,7 +1259,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final AtomicInteger actualWindowWidth = new AtomicInteger(); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.setWindowSize(expectedWindowWidth, expectedWindowHeight); - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height); actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width); @@ -1274,7 +1274,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final int minimumWindowSize = mResources.getDimensionPixelSize( com.android.internal.R.dimen.accessibility_window_magnifier_min_size); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1294,7 +1294,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { public void setWindowSizeLargerThanScreenSize_enabled_windowSizeIsScreenSize() { final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1323,7 +1323,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mInstrumentation.runOnMainSync( () -> - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1348,7 +1348,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mInstrumentation.runOnMainSync( () -> - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1382,7 +1382,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mInstrumentation.runOnMainSync( () -> - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1408,7 +1408,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { com.android.internal.R.dimen.accessibility_window_magnifier_min_size); final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger magnificationCenterX = new AtomicInteger(); @@ -1429,7 +1429,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mInstrumentation.runOnMainSync( () -> { - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( 1.5f, bounds.centerX(), bounds.centerY()); }); View dragButton = getInternalView(R.id.drag_handle); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java index e9d36b861776..01e4d58b68c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java @@ -46,6 +46,7 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; @@ -282,7 +283,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void enableWindowMagnification_showControlAndNotifyBoundsChanged() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -351,7 +352,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void enableWindowMagnification_systemGestureExclusionRectsIsSet() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); // Wait for Rects updated. @@ -368,7 +369,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize)); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -383,7 +384,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void deleteWindowMagnification_destroyControlAndUnregisterComponentCallback() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); @@ -401,7 +402,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT setSystemGestureInsets(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, bounds.bottom); }); ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag); @@ -417,7 +418,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void deleteWindowMagnification_notifySourceBoundsChanged() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); @@ -433,7 +434,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void moveMagnifier_schedulesFrame() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -459,6 +460,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final float targetCenterX = sourceBoundsCaptor.getValue().exactCenterX() + 10; final float targetCenterY = sourceBoundsCaptor.getValue().exactCenterY() + 10; + reset(mWindowMagnifierCallback); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.moveWindowMagnifierToPosition( targetCenterX, targetCenterY, mAnimationCallback); @@ -491,6 +493,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final float centerX = sourceBoundsCaptor.getValue().exactCenterX(); final float centerY = sourceBoundsCaptor.getValue().exactCenterY(); + reset(mWindowMagnifierCallback); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.moveWindowMagnifierToPosition( centerX + 10, centerY + 10, mAnimationCallback); @@ -520,7 +523,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void setScale_enabled_expectedValueAndUpdateStateDescription() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(2.0f, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(2.0f, Float.NaN, Float.NaN)); mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f)); @@ -553,7 +556,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final float displayWidth = windowBounds.width(); final PointF magnifiedCenter = new PointF(center, center + 5f); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, magnifiedCenter.x, magnifiedCenter.y); // Get the center again in case the center we set is out of screen. magnifiedCenter.set(mWindowMagnificationController.getCenterX(), @@ -596,7 +599,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final float expectedRatio = 0.5f; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -635,8 +638,8 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT preferredWindowSize.toString()) .commit(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController - .enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, + Float.NaN); }); // Screen density and size change @@ -663,7 +666,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); final int screenSize = mWindowManager.getCurrentWindowMetrics().getBounds().width() * 10; @@ -688,7 +691,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); Mockito.reset(mWindowManager); Mockito.reset(mMirrorWindowControl); @@ -717,7 +720,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void initializeA11yNode_enabled_expectedValues() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN, Float.NaN); }); final View mirrorView = mSurfaceControlViewHost.getView(); @@ -741,7 +744,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT public void performA11yActions_visible_expectedResults() { final int displayId = mContext.getDisplayId(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(1.5f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(1.5f, Float.NaN, Float.NaN); }); @@ -775,7 +778,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT public void performA11yActions_visible_notifyAccessibilityActionPerformed() { final int displayId = mContext.getDisplayId(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN, Float.NaN); }); @@ -788,7 +791,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void windowMagnifierEditMode_performA11yClickAction_exitEditMode() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setEditMagnifierSizeMode(true); }); @@ -829,7 +832,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -871,7 +874,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -909,7 +912,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int startingHeight = windowBounds.height(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -929,7 +932,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int startingHeight = windowBounds.height(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingWidth, startingHeight); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -952,7 +955,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT /* base= */ 1, /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -994,7 +997,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT /* pbase= */ 1); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -1032,7 +1035,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int startingSize = mMinWindowSize; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -1052,7 +1055,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int startingSize = mMinWindowSize; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); mWindowMagnificationController.setWindowSize(startingSize, startingSize); mWindowMagnificationController.setEditMagnifierSizeMode(true); @@ -1068,7 +1071,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void enableWindowMagnification_hasA11yWindowTitle() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -1079,12 +1082,12 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void enableWindowMagnificationWithScaleLessThanOne_enabled_disabled() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(0.9f, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(0.9f, Float.NaN, Float.NaN); }); @@ -1103,7 +1106,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int newRotation = simulateRotateTheDevice(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); assertEquals(newRotation, mWindowMagnificationController.mRotation); @@ -1112,7 +1115,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void enableWindowMagnification_registerComponentCallback() { mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); @@ -1123,7 +1126,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT public void onLocaleChanged_enabled_updateA11yWindowTitle() { final String newA11yWindowTitle = "new a11y window title"; mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); final TestableResources testableResources = getContext().getOrCreateTestableResources(); @@ -1141,7 +1144,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT @Test public void onSingleTap_enabled_scaleAnimates() { mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -1168,7 +1171,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); setSystemGestureInsets(); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); }); @@ -1186,7 +1189,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT setSystemGestureInsets(); mInstrumentation.runOnMainSync( () -> { - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN); }); // Wait for Region updated. @@ -1215,7 +1218,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT setSystemGestureInsets(); mInstrumentation.runOnMainSync( () -> { - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN); }); // Wait for Region updated. @@ -1244,7 +1247,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int expectedWindowHeight = minimumWindowSize; final int expectedWindowWidth = minimumWindowSize; mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1271,7 +1274,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final AtomicInteger actualWindowWidth = new AtomicInteger(); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.setWindowSize(expectedWindowWidth, expectedWindowHeight); - mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN); actualWindowHeight.set(mSurfaceControlViewHost.getView().getLayoutParams().height); actualWindowWidth.set(mSurfaceControlViewHost.getView().getLayoutParams().width); @@ -1286,7 +1289,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final int minimumWindowSize = mResources.getDimensionPixelSize( com.android.internal.R.dimen.accessibility_window_magnifier_min_size); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1306,7 +1309,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT public void setWindowSizeLargerThanScreenSize_enabled_windowSizeIsScreenSize() { final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1335,7 +1338,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT mInstrumentation.runOnMainSync( () -> - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1362,7 +1365,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT mInstrumentation.runOnMainSync( () -> - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1398,7 +1401,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT mInstrumentation.runOnMainSync( () -> - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger actualWindowHeight = new AtomicInteger(); @@ -1426,7 +1429,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT com.android.internal.R.dimen.accessibility_window_magnifier_min_size); final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN)); final AtomicInteger magnificationCenterX = new AtomicInteger(); @@ -1447,7 +1450,7 @@ public class WindowMagnificationControllerWindowlessMagnifierTest extends SysuiT final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mInstrumentation.runOnMainSync( () -> { - mWindowMagnificationController.enableWindowMagnificationInternal( + mWindowMagnificationController.updateWindowMagnificationInternal( 1.5f, bounds.centerX(), bounds.centerY()); }); View dragButton = getInternalView(R.id.drag_handle); diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/InputSessionTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/InputSessionTest.java new file mode 100644 index 000000000000..2f4999b1b326 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/InputSessionTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.ambient.touch; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.platform.test.annotations.EnableFlags; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.Choreographer; +import android.view.GestureDetector; +import android.view.InputEvent; +import android.view.MotionEvent; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.Flags; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.shared.system.InputChannelCompat; +import com.android.systemui.shared.system.InputMonitorCompat; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +/** + * A test suite for exercising {@link InputSession}. + */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper() +public class InputSessionTest extends SysuiTestCase { + @Mock + InputMonitorCompat mInputMonitor; + + @Mock + GestureDetector mGestureDetector; + + @Mock + InputChannelCompat.InputEventListener mInputEventListener; + + TestableLooper mLooper; + + @Mock + Choreographer mChoreographer; + + @Mock + InputChannelCompat.InputEventReceiver mInputEventReceiver; + + InputSession mSession; + + InputChannelCompat.InputEventListener mEventListener; + + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mLooper = TestableLooper.get(this); + } + + private void createSession(boolean pilfer) { + when(mInputMonitor.getInputReceiver(any(), any(), any())) + .thenReturn(mInputEventReceiver); + mSession = new InputSession(mInputMonitor, mGestureDetector, + mInputEventListener, mChoreographer, mLooper.getLooper(), pilfer); + final ArgumentCaptor<InputChannelCompat.InputEventListener> listenerCaptor = + ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class); + verify(mInputMonitor).getInputReceiver(any(), any(), listenerCaptor.capture()); + mEventListener = listenerCaptor.getValue(); + } + + /** + * Ensures consumed motion events are pilfered when option is set. + */ + @Test + public void testPilferOnMotionEventGestureConsume() { + createSession(true); + final MotionEvent event = Mockito.mock(MotionEvent.class); + when(mGestureDetector.onTouchEvent(event)).thenReturn(true); + mEventListener.onInputEvent(event); + verify(mInputEventListener).onInputEvent(eq(event)); + verify(mInputMonitor).pilferPointers(); + } + + /** + * Ensures consumed motion events are not pilfered when option is not set. + */ + @Test + public void testNoPilferOnMotionEventGestureConsume() { + createSession(false); + final MotionEvent event = Mockito.mock(MotionEvent.class); + when(mGestureDetector.onTouchEvent(event)).thenReturn(true); + mEventListener.onInputEvent(event); + verify(mInputEventListener).onInputEvent(eq(event)); + verify(mInputMonitor, never()).pilferPointers(); + } + + /** + * Ensures input events are never pilfered. + */ + @Test + public void testNoPilferOnInputEvent() { + createSession(true); + final InputEvent event = Mockito.mock(InputEvent.class); + mEventListener.onInputEvent(event); + verify(mInputEventListener).onInputEvent(eq(event)); + verify(mInputMonitor, never()).pilferPointers(); + } + + @Test + @EnableFlags(Flags.FLAG_DREAM_INPUT_SESSION_PILFER_ONCE) + public void testPilferOnce() { + createSession(true); + final MotionEvent event = Mockito.mock(MotionEvent.class); + when(mGestureDetector.onTouchEvent(event)).thenReturn(true); + mEventListener.onInputEvent(event); + mEventListener.onInputEvent(event); + verify(mInputEventListener, times(2)).onInputEvent(eq(event)); + verify(mInputMonitor, times(1)).pilferPointers(); + } + + /** + * Ensures components are properly disposed. + */ + @Test + public void testDispose() { + createSession(true); + mSession.dispose(); + verify(mInputMonitor).dispose(); + verify(mInputEventReceiver).dispose(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java index a127631a536d..1e3b55695849 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.dreams.touch; +package com.android.systemui.ambient.touch; import static com.google.common.truth.Truth.assertThat; @@ -43,7 +43,7 @@ import androidx.lifecycle.LifecycleOwner; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.dreams.touch.dagger.InputSessionComponent; +import com.android.systemui.ambient.touch.dagger.InputSessionComponent; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.display.DisplayHelper; @@ -67,7 +67,7 @@ import java.util.stream.Stream; @SmallTest @RunWith(AndroidTestingRunner.class) -public class DreamOverlayTouchMonitorTest extends SysuiTestCase { +public class TouchMonitorTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -78,7 +78,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { private final InputSession mInputSession; private final Lifecycle mLifecycle; private final LifecycleOwner mLifecycleOwner; - private final DreamOverlayTouchMonitor mMonitor; + private final TouchMonitor mMonitor; private final DefaultLifecycleObserver mLifecycleObserver; private final InputChannelCompat.InputEventListener mEventListener; private final GestureDetector.OnGestureListener mGestureListener; @@ -88,7 +88,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { private final Rect mDisplayBounds = Mockito.mock(Rect.class); private final IWindowManager mIWindowManager; - Environment(Set<DreamTouchHandler> handlers) { + Environment(Set<TouchHandler> handlers) { mLifecycle = Mockito.mock(Lifecycle.class); mLifecycleOwner = Mockito.mock(LifecycleOwner.class); mIWindowManager = Mockito.mock(IWindowManager.class); @@ -104,7 +104,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { mDisplayHelper = Mockito.mock(DisplayHelper.class); when(mDisplayHelper.getMaxBounds(anyInt(), anyInt())) .thenReturn(mDisplayBounds); - mMonitor = new DreamOverlayTouchMonitor(mExecutor, mBackgroundExecutor, + mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor, mLifecycle, mInputFactory, mDisplayHelper, handlers, mIWindowManager, 0); mMonitor.init(); @@ -157,7 +157,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testReportedDisplayBounds() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -169,8 +169,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { // Verify display bounds passed into TouchHandler#getTouchInitiationRegion verify(touchHandler).getTouchInitiationRegion( eq(environment.getDisplayBounds()), any(), any()); - final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor = - ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class); + final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor = + ArgumentCaptor.forClass(TouchHandler.TouchSession.class); verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture()); // Verify that display bounds provided from TouchSession#getBounds @@ -180,7 +180,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testEntryTouchZone() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Rect touchArea = new Rect(4, 4, 8 , 8); doAnswer(invocation -> { @@ -208,10 +208,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testSessionCount() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Rect touchArea = new Rect(4, 4, 8 , 8); - final DreamTouchHandler unzonedTouchHandler = createTouchHandler(); + final TouchHandler unzonedTouchHandler = createTouchHandler(); doAnswer(invocation -> { final Region region = (Region) invocation.getArguments()[1]; region.set(touchArea); @@ -227,13 +227,13 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { when(initialEvent.getY()).thenReturn(1.0f); environment.publishInputEvent(initialEvent); - ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionCaptor = ArgumentCaptor.forClass( - DreamTouchHandler.TouchSession.class); + ArgumentCaptor<TouchHandler.TouchSession> touchSessionCaptor = ArgumentCaptor.forClass( + TouchHandler.TouchSession.class); // Make sure only one active session. { verify(unzonedTouchHandler).onSessionStart(touchSessionCaptor.capture()); - final DreamTouchHandler.TouchSession touchSession = touchSessionCaptor.getValue(); + final TouchHandler.TouchSession touchSession = touchSessionCaptor.getValue(); assertThat(touchSession.getActiveSessionCount()).isEqualTo(1); touchSession.pop(); environment.executeAll(); @@ -247,7 +247,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { // Make sure there are two active sessions. { verify(touchHandler).onSessionStart(touchSessionCaptor.capture()); - final DreamTouchHandler.TouchSession touchSession = touchSessionCaptor.getValue(); + final TouchHandler.TouchSession touchSession = touchSessionCaptor.getValue(); assertThat(touchSession.getActiveSessionCount()).isEqualTo(2); touchSession.pop(); } @@ -256,7 +256,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testNoActiveSessionWhenHandlerDisabled() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final TouchHandler touchHandler = Mockito.mock(TouchHandler.class); // disable the handler when(touchHandler.isEnabled()).thenReturn(false); @@ -274,7 +274,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testInputEventPropagation() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -294,7 +294,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testInputEventPropagationAfterRemoval() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -303,7 +303,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { environment.publishInputEvent(initialEvent); // Ensure session started - final DreamTouchHandler.TouchSession session = captureSession(touchHandler); + final TouchHandler.TouchSession session = captureSession(touchHandler); final InputChannelCompat.InputEventListener eventListener = registerInputEventListener(session); @@ -318,7 +318,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testInputGesturePropagation() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -337,7 +337,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testGestureConsumption() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -360,8 +360,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testBroadcast() { - final DreamTouchHandler touchHandler = createTouchHandler(); - final DreamTouchHandler touchHandler2 = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler2 = createTouchHandler(); when(touchHandler2.isEnabled()).thenReturn(true); final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2) @@ -386,7 +386,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPush() throws InterruptedException, ExecutionException { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -394,13 +394,13 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { final InputEvent initialEvent = Mockito.mock(InputEvent.class); environment.publishInputEvent(initialEvent); - final DreamTouchHandler.TouchSession session = captureSession(touchHandler); + final TouchHandler.TouchSession session = captureSession(touchHandler); final InputChannelCompat.InputEventListener eventListener = registerInputEventListener(session); - final ListenableFuture<DreamTouchHandler.TouchSession> frontSessionFuture = session.push(); + final ListenableFuture<TouchHandler.TouchSession> frontSessionFuture = session.push(); environment.executeAll(); - final DreamTouchHandler.TouchSession frontSession = frontSessionFuture.get(); + final TouchHandler.TouchSession frontSession = frontSessionFuture.get(); final InputChannelCompat.InputEventListener frontEventListener = registerInputEventListener(frontSession); @@ -412,10 +412,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { Mockito.clearInvocations(eventListener, frontEventListener); - ListenableFuture<DreamTouchHandler.TouchSession> sessionFuture = frontSession.pop(); + ListenableFuture<TouchHandler.TouchSession> sessionFuture = frontSession.pop(); environment.executeAll(); - DreamTouchHandler.TouchSession returnedSession = sessionFuture.get(); + TouchHandler.TouchSession returnedSession = sessionFuture.get(); assertThat(session == returnedSession).isTrue(); environment.executeAll(); @@ -429,10 +429,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPop() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); - final DreamTouchHandler.TouchSession.Callback callback = - Mockito.mock(DreamTouchHandler.TouchSession.Callback.class); + final TouchHandler.TouchSession.Callback callback = + Mockito.mock(TouchHandler.TouchSession.Callback.class); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -440,7 +440,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { final InputEvent initialEvent = Mockito.mock(InputEvent.class); environment.publishInputEvent(initialEvent); - final DreamTouchHandler.TouchSession session = captureSession(touchHandler); + final TouchHandler.TouchSession session = captureSession(touchHandler); session.registerCallback(callback); session.pop(); environment.executeAll(); @@ -450,7 +450,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPauseWithNoActiveSessions() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -464,7 +464,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testDeferredPauseWithActiveSessions() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -481,8 +481,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { environment.publishInputEvent(event); verify(eventListener).onInputEvent(eq(event)); - final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor = - ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class); + final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor = + ArgumentCaptor.forClass(TouchHandler.TouchSession.class); verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture()); @@ -502,7 +502,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testDestroyWithActiveSessions() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -519,8 +519,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { environment.publishInputEvent(event); verify(eventListener).onInputEvent(eq(event)); - final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor = - ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class); + final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor = + ArgumentCaptor.forClass(TouchHandler.TouchSession.class); verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture()); @@ -535,19 +535,19 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPilfering() { - final DreamTouchHandler touchHandler1 = createTouchHandler(); - final DreamTouchHandler touchHandler2 = createTouchHandler(); + final TouchHandler touchHandler1 = createTouchHandler(); + final TouchHandler touchHandler2 = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2) .collect(Collectors.toCollection(HashSet::new))); final InputEvent initialEvent = Mockito.mock(InputEvent.class); environment.publishInputEvent(initialEvent); - final DreamTouchHandler.TouchSession session1 = captureSession(touchHandler1); + final TouchHandler.TouchSession session1 = captureSession(touchHandler1); final GestureDetector.OnGestureListener gestureListener1 = registerGestureListener(session1); - final DreamTouchHandler.TouchSession session2 = captureSession(touchHandler2); + final TouchHandler.TouchSession session2 = captureSession(touchHandler2); final GestureDetector.OnGestureListener gestureListener2 = registerGestureListener(session2); when(gestureListener2.onDown(any())).thenReturn(true); @@ -568,10 +568,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testOnRemovedCallbackOnStopMonitoring() { - final DreamTouchHandler touchHandler = createTouchHandler(); + final TouchHandler touchHandler = createTouchHandler(); - final DreamTouchHandler.TouchSession.Callback callback = - Mockito.mock(DreamTouchHandler.TouchSession.Callback.class); + final TouchHandler.TouchSession.Callback callback = + Mockito.mock(TouchHandler.TouchSession.Callback.class); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -579,7 +579,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { final InputEvent initialEvent = Mockito.mock(InputEvent.class); environment.publishInputEvent(initialEvent); - final DreamTouchHandler.TouchSession session = captureSession(touchHandler); + final TouchHandler.TouchSession session = captureSession(touchHandler); session.registerCallback(callback); environment.executeAll(); @@ -593,19 +593,19 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { verify(callback).onRemoved(); } - public GestureDetector.OnGestureListener registerGestureListener(DreamTouchHandler handler) { + private GestureDetector.OnGestureListener registerGestureListener(TouchHandler handler) { final GestureDetector.OnGestureListener gestureListener = Mockito.mock( GestureDetector.OnGestureListener.class); - final ArgumentCaptor<DreamTouchHandler.TouchSession> sessionCaptor = - ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class); + final ArgumentCaptor<TouchHandler.TouchSession> sessionCaptor = + ArgumentCaptor.forClass(TouchHandler.TouchSession.class); verify(handler).onSessionStart(sessionCaptor.capture()); sessionCaptor.getValue().registerGestureListener(gestureListener); return gestureListener; } - public GestureDetector.OnGestureListener registerGestureListener( - DreamTouchHandler.TouchSession session) { + private GestureDetector.OnGestureListener registerGestureListener( + TouchHandler.TouchSession session) { final GestureDetector.OnGestureListener gestureListener = Mockito.mock( GestureDetector.OnGestureListener.class); session.registerGestureListener(gestureListener); @@ -613,8 +613,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { return gestureListener; } - public InputChannelCompat.InputEventListener registerInputEventListener( - DreamTouchHandler.TouchSession session) { + private InputChannelCompat.InputEventListener registerInputEventListener( + TouchHandler.TouchSession session) { final InputChannelCompat.InputEventListener eventListener = Mockito.mock( InputChannelCompat.InputEventListener.class); session.registerInputListener(eventListener); @@ -622,20 +622,20 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { return eventListener; } - public DreamTouchHandler.TouchSession captureSession(DreamTouchHandler handler) { - final ArgumentCaptor<DreamTouchHandler.TouchSession> sessionCaptor = - ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class); + private TouchHandler.TouchSession captureSession(TouchHandler handler) { + final ArgumentCaptor<TouchHandler.TouchSession> sessionCaptor = + ArgumentCaptor.forClass(TouchHandler.TouchSession.class); verify(handler).onSessionStart(sessionCaptor.capture()); return sessionCaptor.getValue(); } - public InputChannelCompat.InputEventListener registerInputEventListener( - DreamTouchHandler handler) { + private InputChannelCompat.InputEventListener registerInputEventListener( + TouchHandler handler) { return registerInputEventListener(captureSession(handler)); } - private DreamTouchHandler createTouchHandler() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + private TouchHandler createTouchHandler() { + final TouchHandler touchHandler = Mockito.mock(TouchHandler.class); // enable the handler by default when(touchHandler.isEnabled()).thenReturn(true); return touchHandler; diff --git a/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt index f490f3c56987..cbad133ba4f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt @@ -41,7 +41,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.QuickSettingsController import com.android.systemui.shade.ShadeController @@ -109,7 +108,6 @@ class BackActionInteractorTest : SysuiTestCase() { headsUpManager, powerInteractor, activeNotificationsInteractor, - kosmos.sceneContainerFlags, kosmos::sceneInteractor, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt index 33a6010d816c..8f3fed74fe97 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.biometrics +import android.app.ActivityTaskManager import android.app.admin.DevicePolicyManager import android.content.pm.PackageManager import android.hardware.biometrics.BiometricAuthenticator @@ -44,9 +45,12 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.widget.LockPatternUtils import com.android.systemui.Flags.FLAG_CONSTRAINT_BP import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository +import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor +import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor @@ -120,10 +124,12 @@ open class AuthContainerViewTest : SysuiTestCase() { lateinit var selectedUserInteractor: SelectedUserInteractor @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var activityTaskManager: ActivityTaskManager private val testScope = TestScope(StandardTestDispatcher()) private val fakeExecutor = FakeExecutor(FakeSystemClock()) private val biometricPromptRepository = FakePromptRepository() + private val biometricStatusRepository = FakeBiometricStatusRepository() private val fingerprintRepository = FakeFingerprintPropertyRepository() private val displayStateRepository = FakeDisplayStateRepository() private val credentialInteractor = FakeCredentialInteractor() @@ -143,6 +149,7 @@ open class AuthContainerViewTest : SysuiTestCase() { private lateinit var displayRepository: FakeDisplayRepository private lateinit var displayStateInteractor: DisplayStateInteractor private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor + private lateinit var biometricStatusInteractor: BiometricStatusInteractor private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor) private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android) @@ -168,6 +175,8 @@ open class AuthContainerViewTest : SysuiTestCase() { selectedUserInteractor, testScope.backgroundScope, ) + biometricStatusInteractor = + BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository) // Set up default logo icon whenever(packageManager.getApplicationIcon(OP_PACKAGE_NAME)).thenReturn(defaultLogoIcon) context.setMockPackageManager(packageManager) @@ -645,6 +654,7 @@ open class AuthContainerViewTest : SysuiTestCase() { promptSelectorInteractor, context, udfpsOverlayInteractor, + biometricStatusInteractor, udfpsUtils ), { credentialViewModel }, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt index bf6caad688e2..31bdde2bc895 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt @@ -1,13 +1,11 @@ package com.android.systemui.biometrics.domain.interactor -import android.view.Display import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.shared.model.DisplayRotation import com.android.systemui.coroutines.collectLastValue import com.android.systemui.display.data.repository.FakeDisplayRepository -import com.android.systemui.display.data.repository.display import com.android.systemui.unfold.compat.ScreenSizeFoldProvider import com.android.systemui.unfold.updates.FoldProvider import com.android.systemui.util.concurrency.FakeExecutor @@ -101,14 +99,11 @@ class DisplayStateInteractorImplTest : SysuiTestCase() { fun isDefaultDisplayOffChanges() = testScope.runTest { val isDefaultDisplayOff by collectLastValue(interactor.isDefaultDisplayOff) - runCurrent() - displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_OFF))) - displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY) + displayRepository.setDefaultDisplayOff(true) assertThat(isDefaultDisplayOff).isTrue() - displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_ON))) - displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY) + displayRepository.setDefaultDisplayOff(false) assertThat(isDefaultDisplayOff).isFalse() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt index 99c2c4076403..aff93bd339ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt @@ -465,10 +465,34 @@ private val ROTATION_90_INPUTS = nativeYOutsideSensor = 150f, ) -/* ROTATION_180 is not supported. It's treated the same as ROTATION_0. */ +/* + * ROTATION_180 map: + * _ _ _ _ + * _ _ s _ + * _ _ s _ + * _ _ _ _ + * _ O _ _ + * _ _ _ _ + * + * (_) empty space + * (S) sensor + * (O) touch outside of the sensor + */ +private val ROTATION_180_NATIVE_SENSOR_BOUNDS = + Rect( + 200, /* left */ + 100, /* top */ + 300, /* right */ + 300, /* bottom */ + ) private val ROTATION_180_INPUTS = - ROTATION_0_INPUTS.copy( + OrientationBasedInputs( rotation = Surface.ROTATION_180, + nativeOrientation = (ORIENTATION - Math.PI.toFloat() / 2), + nativeXWithinSensor = ROTATION_180_NATIVE_SENSOR_BOUNDS.exactCenterX(), + nativeYWithinSensor = ROTATION_180_NATIVE_SENSOR_BOUNDS.exactCenterY(), + nativeXOutsideSensor = 150f, + nativeYOutsideSensor = 450f, ) /* @@ -639,33 +663,6 @@ private fun genPositiveTestCases( } } -private fun genTestCasesForUnsupportedAction( - motionEventAction: Int -): List<SinglePointerTouchProcessorTest.TestCase> { - val isGoodOverlap = true - val previousPointerOnSensorIds = listOf(INVALID_POINTER_ID, POINTER_ID_1) - return previousPointerOnSensorIds.map { previousPointerOnSensorId -> - val overlayParams = ROTATION_0_INPUTS.toOverlayParams(scaleFactor = 1f) - val nativeX = ROTATION_0_INPUTS.getNativeX(isGoodOverlap) - val nativeY = ROTATION_0_INPUTS.getNativeY(isGoodOverlap) - val event = - MOTION_EVENT.copy( - action = motionEventAction, - x = nativeX, - y = nativeY, - minor = NATIVE_MINOR, - major = NATIVE_MAJOR, - ) - SinglePointerTouchProcessorTest.TestCase( - event = event, - currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = isGoodOverlap)), - previousPointerOnSensorId = previousPointerOnSensorId, - overlayParams = overlayParams, - expected = TouchProcessorResult.Failure(), - ) - } -} - private fun obtainMotionEvent( action: Int, pointerId: Int, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt index 30c5e6ed4812..d3cc23296b46 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt @@ -78,7 +78,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR import com.android.systemui.statusbar.phone.dozeServiceHost import com.android.systemui.statusbar.policy.KeyguardStateController @@ -239,7 +238,6 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { testScope.backgroundScope, mContext, deviceEntryFingerprintAuthRepository, - kosmos.fakeSceneContainerFlags, kosmos.sceneInteractor, primaryBouncerInteractor, alternateBouncerInteractor, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index 5b0df5d05703..a6c7f728ff3d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt @@ -16,12 +16,14 @@ package com.android.systemui.biometrics.ui.viewmodel +import android.app.ActivityTaskManager import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.Point import android.graphics.drawable.BitmapDrawable +import android.hardware.biometrics.BiometricFingerprintConstants import android.hardware.biometrics.Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT import android.hardware.biometrics.PromptContentItemBulletedText import android.hardware.biometrics.PromptContentView @@ -40,9 +42,12 @@ import com.android.systemui.Flags.FLAG_CONSTRAINT_BP import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.AuthController import com.android.systemui.biometrics.UdfpsUtils +import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository +import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor +import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor @@ -51,6 +56,7 @@ import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor import com.android.systemui.biometrics.extractAuthenticatorTypes import com.android.systemui.biometrics.faceSensorPropertiesInternal import com.android.systemui.biometrics.fingerprintSensorPropertiesInternal +import com.android.systemui.biometrics.shared.model.AuthenticationReason import com.android.systemui.biometrics.shared.model.BiometricModalities import com.android.systemui.biometrics.shared.model.BiometricModality import com.android.systemui.biometrics.shared.model.DisplayRotation @@ -59,6 +65,7 @@ import com.android.systemui.biometrics.shared.model.toSensorType import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.display.data.repository.FakeDisplayRepository +import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus import com.android.systemui.res.R import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.concurrency.FakeExecutor @@ -102,6 +109,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa @Mock private lateinit var packageManager: PackageManager @Mock private lateinit var applicationInfoWithIcon: ApplicationInfo @Mock private lateinit var applicationInfoNoIcon: ApplicationInfo + @Mock private lateinit var activityTaskManager: ActivityTaskManager private val fakeExecutor = FakeExecutor(FakeSystemClock()) private val testScope = TestScope() @@ -115,9 +123,11 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa private lateinit var fingerprintRepository: FakeFingerprintPropertyRepository private lateinit var promptRepository: FakePromptRepository private lateinit var displayStateRepository: FakeDisplayStateRepository + private lateinit var biometricStatusRepository: FakeBiometricStatusRepository private lateinit var displayRepository: FakeDisplayRepository private lateinit var displayStateInteractor: DisplayStateInteractor private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor + private lateinit var biometricStatusInteractor: BiometricStatusInteractor private lateinit var selector: PromptSelectorInteractor private lateinit var viewModel: PromptViewModel @@ -157,6 +167,9 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa selectedUserInteractor, testScope.backgroundScope ) + biometricStatusRepository = FakeBiometricStatusRepository() + biometricStatusInteractor = + BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository) selector = PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils) selector.resetPrompt() @@ -178,6 +191,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa selector, mContext, udfpsOverlayInteractor, + biometricStatusInteractor, udfpsUtils ) iconViewModel = viewModel.iconViewModel @@ -1053,8 +1067,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa fun auto_confirm_authentication_when_finger_down() = runGenericTest { val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false) - // No icon button when face only, can't confirm before auth - if (!testCase.isFaceOnly) { + if (testCase.isCoex) { viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_DOWN)) } viewModel.showAuthenticated(testCase.authenticatedModality, 0) @@ -1069,14 +1082,18 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa assertThat(canTryAgain).isFalse() assertThat(authenticated?.isAuthenticated).isTrue() - if (testCase.isFaceOnly && expectConfirmation) { - assertThat(size).isEqualTo(PromptSize.MEDIUM) - assertButtonsVisible( - cancel = true, - confirm = true, - ) + if (expectConfirmation) { + if (testCase.isFaceOnly) { + assertThat(size).isEqualTo(PromptSize.MEDIUM) + assertButtonsVisible( + cancel = true, + confirm = true, + ) - viewModel.confirmAuthenticated() + viewModel.confirmAuthenticated() + } else if (testCase.isCoex) { + assertThat(authenticated?.isAuthenticatedAndConfirmed).isTrue() + } assertThat(message).isEqualTo(PromptMessage.Empty) assertButtonsVisible() } @@ -1086,8 +1103,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa fun cannot_auto_confirm_authentication_when_finger_up() = runGenericTest { val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false) - // No icon button when face only, can't confirm before auth - if (!testCase.isFaceOnly) { + if (testCase.isCoex) { viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_DOWN)) viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_UP)) } @@ -1413,6 +1429,12 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa packageName = packageName, ) + biometricStatusRepository.setFingerprintAcquiredStatus( + AcquiredFingerprintAuthenticationStatus( + AuthenticationReason.BiometricPromptAuthentication, + BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN + ) + ) // put the view model in the initial authenticating state, unless explicitly skipped val startMode = when { diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt index 238a76eb7400..415da022cd32 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt @@ -77,7 +77,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR import com.android.systemui.statusbar.phone.dozeServiceHost import com.android.systemui.statusbar.policy.KeyguardStateController @@ -236,7 +235,6 @@ class SideFpsOverlayViewModelTest : SysuiTestCase() { testScope.backgroundScope, mContext, deviceEntryFingerprintAuthRepository, - kosmos.fakeSceneContainerFlags, kosmos.sceneInteractor, primaryBouncerInteractor, alternateBouncerInteractor, diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt new file mode 100644 index 000000000000..8a1a08249856 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bluetooth.qsdialog + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession +import com.android.dx.mockito.inline.extended.StaticMockitoSession +import com.android.settingslib.bluetooth.BluetoothUtils +import com.android.settingslib.bluetooth.CachedBluetoothDevice +import com.android.settingslib.bluetooth.LocalBluetoothManager +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.res.R +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class AudioSharingInteractorTest : SysuiTestCase() { + private val testDispatcher = UnconfinedTestDispatcher() + private val testScope = TestScope(testDispatcher) + private val bluetoothState = MutableStateFlow(false) + private val deviceItemUpdate: MutableSharedFlow<List<DeviceItem>> = MutableSharedFlow() + @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice + @Mock private lateinit var localBluetoothManager: LocalBluetoothManager + @Mock private lateinit var bluetoothStateInteractor: BluetoothStateInteractor + @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor + @Mock private lateinit var deviceItem: DeviceItem + private lateinit var mockitoSession: StaticMockitoSession + private lateinit var audioSharingInteractor: AudioSharingInteractor + + @Before + fun setUp() { + mockitoSession = + mockitoSession().initMocks(this).mockStatic(BluetoothUtils::class.java).startMocking() + whenever(bluetoothStateInteractor.bluetoothStateUpdate).thenReturn(bluetoothState) + whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(deviceItemUpdate) + audioSharingInteractor = + AudioSharingInteractor( + localBluetoothManager, + bluetoothStateInteractor, + deviceItemInteractor, + testScope.backgroundScope, + testDispatcher, + ) + } + + @After + fun tearDown() { + mockitoSession.finishMocking() + } + + @Test + fun testButtonStateUpdate_bluetoothOff_returnGone() { + testScope.runTest { + val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate) + + assertThat(actual).isEqualTo(AudioSharingButtonState.Gone) + } + } + + @Test + fun testButtonStateUpdate_noDevice_returnGone() { + testScope.runTest { + val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate) + bluetoothState.value = true + runCurrent() + + assertThat(actual).isEqualTo(AudioSharingButtonState.Gone) + } + } + + @Test + fun testButtonStateUpdate_isBroadcasting_returnSharingAudio() { + testScope.runTest { + whenever(BluetoothUtils.isBroadcasting(localBluetoothManager)).thenReturn(true) + + val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate) + bluetoothState.value = true + deviceItemUpdate.emit(listOf()) + runCurrent() + + assertThat(actual) + .isEqualTo( + AudioSharingButtonState.Visible( + R.string.quick_settings_bluetooth_audio_sharing_button_sharing + ) + ) + } + } + + @Test + fun testButtonStateUpdate_hasSource_returnGone() { + testScope.runTest { + whenever(BluetoothUtils.isBroadcasting(localBluetoothManager)).thenReturn(false) + whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice) + whenever( + BluetoothUtils.hasConnectedBroadcastSource( + cachedBluetoothDevice, + localBluetoothManager + ) + ) + .thenReturn(true) + + val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate) + bluetoothState.value = true + deviceItemUpdate.emit(listOf(deviceItem)) + runCurrent() + + assertThat(actual).isEqualTo(AudioSharingButtonState.Gone) + } + } + + @Test + fun testButtonStateUpdate_hasActiveDevice_returnAudioSharing() { + testScope.runTest { + whenever(BluetoothUtils.isBroadcasting(localBluetoothManager)).thenReturn(false) + whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice) + whenever( + BluetoothUtils.hasConnectedBroadcastSource( + cachedBluetoothDevice, + localBluetoothManager + ) + ) + .thenReturn(false) + whenever(BluetoothUtils.isActiveLeAudioDevice(cachedBluetoothDevice)).thenReturn(true) + + val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate) + bluetoothState.value = true + deviceItemUpdate.emit(listOf(deviceItem)) + runCurrent() + + assertThat(actual) + .isEqualTo( + AudioSharingButtonState.Visible( + R.string.quick_settings_bluetooth_audio_sharing_button + ) + ) + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt index a8f82eda51c7..6fe7d86faab8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt @@ -23,6 +23,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothAdapter import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before @@ -41,7 +42,8 @@ import org.mockito.junit.MockitoRule @TestableLooper.RunWithLooper(setAsMainLooper = true) class BluetoothStateInteractorTest : SysuiTestCase() { @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() - private val testScope = TestScope() + private val testDispatcher = StandardTestDispatcher() + private val testScope = TestScope(testDispatcher) private lateinit var bluetoothStateInteractor: BluetoothStateInteractor @@ -52,7 +54,12 @@ class BluetoothStateInteractorTest : SysuiTestCase() { @Before fun setUp() { bluetoothStateInteractor = - BluetoothStateInteractor(localBluetoothManager, logger, testScope.backgroundScope) + BluetoothStateInteractor( + localBluetoothManager, + logger, + testScope.backgroundScope, + testDispatcher + ) `when`(localBluetoothManager.bluetoothAdapter).thenReturn(bluetoothAdapter) } @@ -61,7 +68,7 @@ class BluetoothStateInteractorTest : SysuiTestCase() { testScope.runTest { `when`(bluetoothAdapter.isEnabled).thenReturn(true) - assertThat(bluetoothStateInteractor.isBluetoothEnabled).isTrue() + assertThat(bluetoothStateInteractor.isBluetoothEnabled()).isTrue() } } @@ -70,7 +77,7 @@ class BluetoothStateInteractorTest : SysuiTestCase() { testScope.runTest { `when`(bluetoothAdapter.isEnabled).thenReturn(false) - assertThat(bluetoothStateInteractor.isBluetoothEnabled).isFalse() + assertThat(bluetoothStateInteractor.isBluetoothEnabled()).isFalse() } } @@ -79,7 +86,7 @@ class BluetoothStateInteractorTest : SysuiTestCase() { testScope.runTest { `when`(bluetoothAdapter.isEnabled).thenReturn(false) - bluetoothStateInteractor.isBluetoothEnabled = true + bluetoothStateInteractor.setBluetoothEnabled(true) verify(bluetoothAdapter).enable() verify(logger) .logBluetoothState(BluetoothStateStage.BLUETOOTH_STATE_VALUE_SET, true.toString()) @@ -91,7 +98,7 @@ class BluetoothStateInteractorTest : SysuiTestCase() { testScope.runTest { `when`(bluetoothAdapter.isEnabled).thenReturn(false) - bluetoothStateInteractor.isBluetoothEnabled = false + bluetoothStateInteractor.setBluetoothEnabled(false) verify(bluetoothAdapter, never()).enable() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt index 12dfe97649d3..62c98b05cbd5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt @@ -110,7 +110,6 @@ class BluetoothTileDialogDelegateTest : SysuiTestCase() { BluetoothTileDialogDelegate( uiProperties, CONTENT_HEIGHT, - ENABLED, bluetoothTileDialogCallback, {}, dispatcher, @@ -211,7 +210,6 @@ class BluetoothTileDialogDelegateTest : SysuiTestCase() { BluetoothTileDialogDelegate( uiProperties, CONTENT_HEIGHT, - ENABLED, bluetoothTileDialogCallback, {}, dispatcher, @@ -267,7 +265,6 @@ class BluetoothTileDialogDelegateTest : SysuiTestCase() { BluetoothTileDialogDelegate( BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED), cachedHeight, - ENABLED, bluetoothTileDialogCallback, {}, dispatcher, @@ -291,7 +288,6 @@ class BluetoothTileDialogDelegateTest : SysuiTestCase() { BluetoothTileDialogDelegate( BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED), MATCH_PARENT, - ENABLED, bluetoothTileDialogCallback, {}, dispatcher, @@ -315,7 +311,6 @@ class BluetoothTileDialogDelegateTest : SysuiTestCase() { BluetoothTileDialogDelegate( BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED), MATCH_PARENT, - ENABLED, bluetoothTileDialogCallback, {}, dispatcher, diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt index 6d99c5b62e9b..b05d9591d8a8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt @@ -52,7 +52,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito.anyBoolean @@ -74,7 +73,7 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { @Mock private lateinit var bluetoothStateInteractor: BluetoothStateInteractor - @Mock private lateinit var bluetoothAutoOnInteractor: BluetoothAutoOnInteractor + @Mock private lateinit var audioSharingInteractor: AudioSharingInteractor @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor @@ -92,6 +91,8 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { @Mock private lateinit var localBluetoothManager: LocalBluetoothManager + @Mock private lateinit var bluetoothTileDialogLogger: BluetoothTileDialogLogger + @Mock private lateinit var mBluetoothTileDialogDelegateDelegateFactory: BluetoothTileDialogDelegate.Factory @@ -115,7 +116,12 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { bluetoothTileDialogViewModel = BluetoothTileDialogViewModel( deviceItemInteractor, - bluetoothStateInteractor, + BluetoothStateInteractor( + localBluetoothManager, + bluetoothTileDialogLogger, + testScope.backgroundScope, + dispatcher + ), // TODO(b/316822488): Create FakeBluetoothAutoOnInteractor. BluetoothAutoOnInteractor( BluetoothAutoOnRepository( @@ -125,6 +131,7 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { dispatcher ) ), + audioSharingInteractor, mDialogTransitionAnimator, activityStarter, uiEventLogger, @@ -135,20 +142,9 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { mBluetoothTileDialogDelegateDelegateFactory ) whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow()) - whenever(bluetoothStateInteractor.bluetoothStateUpdate) - .thenReturn(MutableStateFlow(null).asStateFlow()) whenever(deviceItemInteractor.deviceItemUpdateRequest) .thenReturn(MutableStateFlow(Unit).asStateFlow()) - whenever(bluetoothStateInteractor.isBluetoothEnabled).thenReturn(true) - whenever( - mBluetoothTileDialogDelegateDelegateFactory.create( - any(), - anyInt(), - ArgumentMatchers.anyBoolean(), - any(), - any() - ) - ) + whenever(mBluetoothTileDialogDelegateDelegateFactory.create(any(), anyInt(), any(), any())) .thenReturn(bluetoothTileDialogDelegate) whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog) whenever(sysuiDialog.context).thenReturn(mContext) @@ -159,6 +155,8 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { whenever(bluetoothTileDialogDelegate.contentHeight).thenReturn(getMutableStateFlow(0)) whenever(bluetoothTileDialogDelegate.bluetoothAutoOnToggle) .thenReturn(getMutableStateFlow(false)) + whenever(audioSharingInteractor.audioSharingButtonStateUpdate) + .thenReturn(getMutableStateFlow(AudioSharingButtonState.Gone)) } @Test @@ -201,15 +199,6 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { } @Test - fun testShowDialog_withBluetoothStateValue() { - testScope.runTest { - bluetoothTileDialogViewModel.showDialog(null) - - verify(bluetoothStateInteractor).bluetoothStateUpdate - } - } - - @Test fun testStartSettingsActivity_activityLaunched_dialogDismissed() { testScope.runTest { whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice) diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt index eb735cbfec47..daf4a3cbb9de 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 The Android Open Source Project + * Copyright (C) 2023 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. @@ -281,7 +281,7 @@ class DeviceItemInteractorTest : SysuiTestCase() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, - audioManager: AudioManager? + audioManager: AudioManager ) = isFilterMatchFunc(cachedDevice) override fun create(context: Context, cachedDevice: CachedBluetoothDevice) = deviceItem diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt index dac88a340cb1..e06134bdf982 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt @@ -119,6 +119,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { fun faceAuthIsRequestedWhenLockscreenBecomesVisibleFromOffState() = testScope.runTest { underTest.start() + runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_LID) faceWakeUpTriggersConfig.setTriggerFaceAuthOnWakeUpFrom( @@ -160,6 +161,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { fun faceAuthIsRequestedWhenLockscreenBecomesVisibleFromAodState() = testScope.runTest { underTest.start() + runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_LID) faceWakeUpTriggersConfig.setTriggerFaceAuthOnWakeUpFrom( @@ -207,6 +209,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { fun faceAuthIsRequestedWhenLockscreenBecomesVisibleFromDozingState() = testScope.runTest { underTest.start() + runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_LID) faceWakeUpTriggersConfig.setTriggerFaceAuthOnWakeUpFrom( diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt index 806930d091b1..68d49c78c567 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt @@ -22,6 +22,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.Display import android.view.Display.TYPE_EXTERNAL +import android.view.Display.TYPE_INTERNAL import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.FlowValue @@ -427,6 +428,35 @@ class DisplayRepositoryTest : SysuiTestCase() { assertThat(display!!.type).isEqualTo(TYPE_EXTERNAL) } + @Test + fun defaultDisplayOff_changes() = + testScope.runTest { + val defaultDisplayOff by latestDefaultDisplayOffFlowValue() + setDisplays( + listOf( + display( + type = TYPE_INTERNAL, + id = Display.DEFAULT_DISPLAY, + state = Display.STATE_OFF + ) + ) + ) + displayListener.value.onDisplayChanged(Display.DEFAULT_DISPLAY) + assertThat(defaultDisplayOff).isTrue() + + setDisplays( + listOf( + display( + type = TYPE_INTERNAL, + id = Display.DEFAULT_DISPLAY, + state = Display.STATE_ON + ) + ) + ) + displayListener.value.onDisplayChanged(Display.DEFAULT_DISPLAY) + assertThat(defaultDisplayOff).isFalse() + } + private fun Iterable<Display>.ids(): List<Int> = map { it.displayId } // Wrapper to capture the displayListener. @@ -436,6 +466,13 @@ class DisplayRepositoryTest : SysuiTestCase() { return flowValue } + // Wrapper to capture the displayListener. + private fun TestScope.latestDefaultDisplayOffFlowValue(): FlowValue<Boolean?> { + val flowValue = collectLastValue(displayRepository.defaultDisplayOff) + captureAddedRemovedListener() + return flowValue + } + private fun TestScope.lastPendingDisplay(): FlowValue<DisplayRepository.PendingDisplay?> { val flowValue = collectLastValue(displayRepository.pendingDisplay) captureAddedRemovedListener() diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt index 30519b0569d7..d118cc718aed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt @@ -16,51 +16,74 @@ package com.android.systemui.display.ui.view +import android.app.Dialog import android.graphics.Insets import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import android.view.LayoutInflater import android.view.View +import android.view.Window import android.view.WindowInsets +import android.view.WindowInsetsAnimation import androidx.test.filters.SmallTest +import com.android.app.animation.Interpolators import com.android.systemui.SysuiTestCase import com.android.systemui.res.R import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor import org.mockito.Mockito.never import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) -class MirroringConfirmationDialogTest : SysuiTestCase() { +class MirroringConfirmationDialogDelegateTest : SysuiTestCase() { - private lateinit var dialog: MirroringConfirmationDialog + private lateinit var underTest: MirroringConfirmationDialogDelegate private val onStartMirroringCallback = mock<View.OnClickListener>() private val onCancelCallback = mock<View.OnClickListener>() + private val windowDecorView: View = mock {} + private val windowInsetsAnimationCallbackCaptor = + ArgumentCaptor.forClass(WindowInsetsAnimation.Callback::class.java) + private val dialog: Dialog = + mock<Dialog> { + var view: View? = null + whenever(setContentView(any<Int>())).then { + view = + LayoutInflater.from(this@MirroringConfirmationDialogDelegateTest.context) + .inflate(it.arguments[0] as Int, null, false) + Unit + } + whenever(requireViewById<View>(any<Int>())).then { + view?.requireViewById(it.arguments[0] as Int) + } + val window: Window = mock { whenever(decorView).thenReturn(windowDecorView) } + whenever(this.window).thenReturn(window) + } @Before fun setUp() { - MockitoAnnotations.initMocks(this) - - dialog = - MirroringConfirmationDialog( - context, - onStartMirroringCallback, - onCancelCallback, + underTest = + MirroringConfirmationDialogDelegate( + context = context, + showConcurrentDisplayInfo = false, + onStartMirroringClickListener = onStartMirroringCallback, + onCancelMirroring = onCancelCallback, navbarBottomInsetsProvider = { 0 }, ) } @Test fun startMirroringButton_clicked_callsCorrectCallback() { - dialog.show() + underTest.onCreate(dialog, null) dialog.requireViewById<View>(R.id.enable_display).callOnClick() @@ -70,7 +93,7 @@ class MirroringConfirmationDialogTest : SysuiTestCase() { @Test fun cancelButton_clicked_callsCorrectCallback() { - dialog.show() + underTest.onCreate(dialog, null) dialog.requireViewById<View>(R.id.cancel).callOnClick() @@ -80,10 +103,10 @@ class MirroringConfirmationDialogTest : SysuiTestCase() { @Test fun onCancel_afterEnablingMirroring_cancelCallbackNotCalled() { - dialog.show() + underTest.onCreate(dialog, null) dialog.requireViewById<View>(R.id.enable_display).callOnClick() - dialog.cancel() + underTest.onStop(dialog) verify(onCancelCallback, never()).onClick(any()) verify(onStartMirroringCallback).onClick(any()) @@ -91,10 +114,10 @@ class MirroringConfirmationDialogTest : SysuiTestCase() { @Test fun onDismiss_afterEnablingMirroring_cancelCallbackNotCalled() { - dialog.show() + underTest.onCreate(dialog, null) dialog.requireViewById<View>(R.id.enable_display).callOnClick() - dialog.dismiss() + underTest.onStop(dialog) verify(onCancelCallback, never()).onClick(any()) verify(onStartMirroringCallback).onClick(any()) @@ -102,10 +125,12 @@ class MirroringConfirmationDialogTest : SysuiTestCase() { @Test fun onInsetsChanged_navBarInsets_updatesBottomPadding() { - dialog.show() + underTest.onCreate(dialog, null) + underTest.onStart(dialog) val insets = buildInsets(WindowInsets.Type.navigationBars(), TEST_BOTTOM_INSETS) - dialog.onInsetsChanged(WindowInsets.Type.navigationBars(), insets) + + triggerInsetsChanged(WindowInsets.Type.navigationBars(), insets) assertThat(dialog.requireViewById<View>(R.id.cd_bottom_sheet).paddingBottom) .isEqualTo(TEST_BOTTOM_INSETS) @@ -113,10 +138,11 @@ class MirroringConfirmationDialogTest : SysuiTestCase() { @Test fun onInsetsChanged_otherType_doesNotUpdateBottomPadding() { - dialog.show() + underTest.onCreate(dialog, null) + underTest.onStart(dialog) val insets = buildInsets(WindowInsets.Type.ime(), TEST_BOTTOM_INSETS) - dialog.onInsetsChanged(WindowInsets.Type.ime(), insets) + triggerInsetsChanged(WindowInsets.Type.ime(), insets) assertThat(dialog.requireViewById<View>(R.id.cd_bottom_sheet).paddingBottom) .isNotEqualTo(TEST_BOTTOM_INSETS) @@ -126,11 +152,13 @@ class MirroringConfirmationDialogTest : SysuiTestCase() { return WindowInsets.Builder().setInsets(type, Insets.of(0, 0, 0, bottom)).build() } - @After - fun teardown() { - if (::dialog.isInitialized) { - dialog.dismiss() - } + private fun triggerInsetsChanged(type: Int, insets: WindowInsets) { + verify(windowDecorView) + .setWindowInsetsAnimationCallback(capture(windowInsetsAnimationCallbackCaptor)) + windowInsetsAnimationCallbackCaptor.value.onProgress( + insets, + listOf(WindowInsetsAnimation(type, Interpolators.INSTANT, 0)) + ) } private companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 11ec417fc5f8..709f7797d2bf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -25,8 +25,8 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; -import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER; import static com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR; +import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER; import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION; import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT; import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE; @@ -91,6 +91,7 @@ import com.android.systemui.biometrics.AuthController; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel; import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dreams.ui.viewmodel.DreamViewModel; import com.android.systemui.dump.DumpManager; @@ -101,7 +102,6 @@ import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.log.SessionTracker; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.scene.FakeWindowRootViewComponent; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.scene.ui.view.WindowRootView; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.NotificationShadeWindowControllerImpl; @@ -219,8 +219,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock CoroutineDispatcher mDispatcher; private @Mock DreamViewModel mDreamViewModel; + private @Mock CommunalTransitionViewModel mCommunalTransitionViewModel; private @Mock SystemPropertiesHelper mSystemPropertiesHelper; - private @Mock SceneContainerFlags mSceneContainerFlags; private FakeFeatureFlags mFeatureFlags; private final int mDefaultUserId = 100; @@ -241,6 +241,10 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { .thenReturn(mock(Flow.class)); when(mDreamViewModel.getTransitionEnded()) .thenReturn(mock(Flow.class)); + when(mCommunalTransitionViewModel.getShowByDefault()) + .thenReturn(mock(Flow.class)); + when(mCommunalTransitionViewModel.getTransitionFromOccludedEnded()) + .thenReturn(mock(Flow.class)); when(mSelectedUserInteractor.getSelectedUserId()).thenReturn(mDefaultUserId); when(mSelectedUserInteractor.getSelectedUserId(anyBoolean())).thenReturn(mDefaultUserId); mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl( @@ -264,7 +268,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, - mSceneContainerFlags, mKosmos::getCommunalInteractor); mFeatureFlags = new FakeFeatureFlags(); mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER); @@ -1229,6 +1232,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mSystemClock, mDispatcher, () -> mDreamViewModel, + () -> mCommunalTransitionViewModel, mSystemPropertiesHelper, () -> mock(WindowManagerLockscreenVisibilityManager.class), mSelectedUserInteractor, @@ -1236,7 +1240,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mock(WindowManagerOcclusionManager.class)); mViewMediator.start(); - mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null); + mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null); } private void captureKeyguardStateControllerCallback() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt index 2b51863117e9..b50d248d6940 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt @@ -15,14 +15,14 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any import com.android.systemui.utils.GlobalWindowManager import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -42,8 +42,7 @@ import org.mockito.MockitoAnnotations class ResourceTrimmerTest : SysuiTestCase() { val kosmos = testKosmos() - private val testDispatcher = UnconfinedTestDispatcher() - private val testScope = TestScope(testDispatcher) + private val testScope = kosmos.testScope private val keyguardRepository = kosmos.fakeKeyguardRepository private val featureFlags = kosmos.fakeFeatureFlagsClassic private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository @@ -63,8 +62,8 @@ class ResourceTrimmerTest : SysuiTestCase() { val withDeps = KeyguardInteractorFactory.create( - repository = keyguardRepository, featureFlags = featureFlags, + repository = keyguardRepository, ) val keyguardInteractor = withDeps.keyguardInteractor resourceTrimmer = @@ -74,7 +73,7 @@ class ResourceTrimmerTest : SysuiTestCase() { kosmos.keyguardTransitionInteractor, globalWindowManager, testScope.backgroundScope, - testDispatcher, + kosmos.testDispatcher, featureFlags ) resourceTrimmer.start() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt index d75cbec8c542..d52e911d31f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt @@ -21,7 +21,10 @@ import androidx.test.filters.SmallTest import com.android.keyguard.ClockEventController import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.FakeFeatureFlagsClassic +import com.android.systemui.flags.Flags import com.android.systemui.keyguard.shared.model.SettingsClockSize +import com.android.systemui.res.R import com.android.systemui.shared.clocks.ClockRegistry import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth @@ -49,6 +52,7 @@ class KeyguardClockRepositoryTest : SysuiTestCase() { private lateinit var fakeSettings: FakeSettings @Mock private lateinit var clockRegistry: ClockRegistry @Mock private lateinit var clockEventController: ClockEventController + private val fakeFeatureFlagsClassic = FakeFeatureFlagsClassic() @Before fun setup() { @@ -63,7 +67,9 @@ class KeyguardClockRepositoryTest : SysuiTestCase() { clockRegistry, clockEventController, dispatcher, - scope.backgroundScope + scope.backgroundScope, + context, + fakeFeatureFlagsClassic, ) } @@ -82,4 +88,12 @@ class KeyguardClockRepositoryTest : SysuiTestCase() { val value = collectLastValue(underTest.selectedClockSize) Truth.assertThat(value()).isEqualTo(SettingsClockSize.DYNAMIC) } + + @Test + fun testShouldForceSmallClock() = + scope.runTest { + overrideResource(R.bool.force_small_clock_on_lockscreen, true) + fakeFeatureFlagsClassic.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true) + Truth.assertThat(underTest.shouldForceSmallClock).isTrue() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt index 9266af452abd..dc7f372b5dfc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt @@ -32,6 +32,7 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository @@ -40,7 +41,6 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR import com.android.systemui.statusbar.policy.KeyguardStateController @@ -87,7 +87,6 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() { @Before fun setup() { mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR) - kosmos.fakeSceneContainerFlags.enabled = false primaryBouncerInteractor = PrimaryBouncerInteractor( @@ -127,7 +126,6 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() { testScope.backgroundScope, mContext, deviceEntryFingerprintAuthRepository, - kosmos.fakeSceneContainerFlags, kosmos.sceneInteractor, primaryBouncerInteractor, alternateBouncerInteractor, @@ -168,15 +166,14 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() { } @Test + @EnableSceneContainer fun updatesShowIndicatorForDeviceEntry_onBouncerSceneActive() = testScope.runTest { - kosmos.fakeSceneContainerFlags.enabled = true underTest = DeviceEntrySideFpsOverlayInteractor( testScope.backgroundScope, mContext, deviceEntryFingerprintAuthRepository, - kosmos.fakeSceneContainerFlags, kosmos.sceneInteractor, primaryBouncerInteractor, alternateBouncerInteractor, @@ -196,15 +193,14 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() { } @Test + @EnableSceneContainer fun updatesShowIndicatorForDeviceEntry_onBouncerSceneInactive() = testScope.runTest { - kosmos.fakeSceneContainerFlags.enabled = true underTest = DeviceEntrySideFpsOverlayInteractor( testScope.backgroundScope, mContext, deviceEntryFingerprintAuthRepository, - kosmos.fakeSceneContainerFlags, kosmos.sceneInteractor, primaryBouncerInteractor, alternateBouncerInteractor, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt index b6b457142a3f..4270236f761e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt @@ -27,16 +27,12 @@ import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRe import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint import com.android.systemui.kosmos.testScope -import com.android.systemui.plugins.clocks.ClockConfig import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.res.R import com.android.systemui.testKosmos -import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent @@ -103,72 +99,6 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { } @Test - @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun composeLockscreenOff_DoesAppliesSplitShadeWeatherClockBlueprint() { - testScope.runTest { - val blueprint by collectLastValue(underTest.blueprint) - whenever(clockController.config) - .thenReturn( - ClockConfig( - id = "DIGITAL_CLOCK_WEATHER", - name = "clock", - description = "clock", - ) - ) - clockRepository.setCurrentClock(clockController) - overrideResource(R.bool.config_use_split_notification_shade, true) - configurationRepository.onConfigurationChange() - runCurrent() - - assertThat(blueprint?.id).isNotEqualTo(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID) - } - } - - @Test - @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun testDoesAppliesSplitShadeWeatherClockBlueprint() { - testScope.runTest { - val blueprint by collectLastValue(underTest.blueprint) - whenever(clockController.config) - .thenReturn( - ClockConfig( - id = "DIGITAL_CLOCK_WEATHER", - name = "clock", - description = "clock", - ) - ) - clockRepository.setCurrentClock(clockController) - overrideResource(R.bool.config_use_split_notification_shade, true) - configurationRepository.onConfigurationChange() - runCurrent() - - assertThat(blueprint?.id).isEqualTo(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID) - } - } - - @Test - @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun testAppliesWeatherClockBlueprint() { - testScope.runTest { - val blueprint by collectLastValue(underTest.blueprint) - whenever(clockController.config) - .thenReturn( - ClockConfig( - id = "DIGITAL_CLOCK_WEATHER", - name = "clock", - description = "clock", - ) - ) - clockRepository.setCurrentClock(clockController) - overrideResource(R.bool.config_use_split_notification_shade, false) - configurationRepository.onConfigurationChange() - runCurrent() - - assertThat(blueprint?.id).isEqualTo(WEATHER_CLOCK_BLUEPRINT_ID) - } - } - - @Test @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) fun testDoesNotApplySplitShadeBlueprint() { testScope.runTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt index 3f05bfae6777..9ccf2121b8d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.keyguard.domain.interactor import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState @@ -227,4 +228,50 @@ class KeyguardSurfaceBehindInteractorTest : SysuiTestCase() { { it == KeyguardSurfaceBehindModel(alpha = 0f) }, ) } + + @Test + fun notificationLaunchFromLockscreen_isAnimatingSurfaceTrue() = + testScope.runTest { + val isAnimatingSurface by collectLastValue(underTest.isAnimatingSurface) + transitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.LOCKSCREEN, + transitionState = TransitionState.STARTED, + ) + ) + transitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.LOCKSCREEN, + transitionState = TransitionState.FINISHED, + ) + ) + kosmos.notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(true) + runCurrent() + assertThat(isAnimatingSurface).isTrue() + } + + @Test + fun notificationLaunchFromGone_isAnimatingSurfaceFalse() = + testScope.runTest { + val isAnimatingSurface by collectLastValue(underTest.isAnimatingSurface) + transitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + transitionState = TransitionState.STARTED, + ) + ) + transitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + transitionState = TransitionState.FINISHED, + ) + ) + kosmos.notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(true) + runCurrent() + assertThat(isAnimatingSurface).isFalse() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 2c0a518350da..085b70e61339 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -27,6 +27,8 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.dock.DockManager +import com.android.systemui.dock.fakeDockManager import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeCommandQueue @@ -108,6 +110,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { private val powerInteractor = kosmos.powerInteractor private val communalInteractor = kosmos.communalInteractor + private val dockManager = kosmos.fakeDockManager @Before fun setUp() { @@ -1230,6 +1233,38 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test + fun occludedToGlanceableHubWhenDocked() = + testScope.runTest { + // GIVEN a device on lockscreen + keyguardRepository.setKeyguardShowing(true) + runCurrent() + + // GIVEN a prior transition has run to OCCLUDED + runTransitionAndSetWakefulness(KeyguardState.GLANCEABLE_HUB, KeyguardState.OCCLUDED) + keyguardRepository.setKeyguardOccluded(true) + runCurrent() + + // GIVEN device is docked + dockManager.setIsDocked(true) + dockManager.setDockEvent(DockManager.STATE_DOCKED) + + // WHEN occlusion ends + keyguardRepository.setKeyguardOccluded(false) + runCurrent() + + // THEN a transition to GLANCEABLE_HUB should occur + assertThat(transitionRepository) + .startedTransition( + ownerName = FromOccludedTransitionInteractor::class.simpleName, + from = KeyguardState.OCCLUDED, + to = KeyguardState.GLANCEABLE_HUB, + animatorAssertion = { it.isNotNull() }, + ) + + coroutineContext.cancelChildren() + } + + @Test fun occludedToAlternateBouncer() = testScope.runTest { // GIVEN a prior transition has run to OCCLUDED @@ -1354,6 +1389,30 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test + fun dreamingToPrimaryBouncer() = + testScope.runTest { + // GIVEN a prior transition has run to DREAMING + keyguardRepository.setDreaming(true) + runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.DREAMING) + runCurrent() + + // WHEN the primary bouncer is set to show + bouncerRepository.setPrimaryShow(true) + runCurrent() + + // THEN a transition to PRIMARY_BOUNCER should occur + assertThat(transitionRepository) + .startedTransition( + ownerName = "FromDreamingTransitionInteractor", + from = KeyguardState.DREAMING, + to = KeyguardState.PRIMARY_BOUNCER, + animatorAssertion = { it.isNotNull() }, + ) + + coroutineContext.cancelChildren() + } + + @Test fun dreamingToAod() = testScope.runTest { // GIVEN a prior transition has run to DREAMING diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt index 6d605a564022..b1a8dd1d3fdc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt @@ -281,6 +281,14 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // Oh no, we're still surfaceBehindAnimating=true, but no longer transitioning to GONE. transitionRepository.sendTransitionStep( TransitionStep( + transitionState = TransitionState.CANCELED, + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + ) + ) + runCurrent() + transitionRepository.sendTransitionStep( + TransitionStep( transitionState = TransitionState.STARTED, from = KeyguardState.LOCKSCREEN, to = KeyguardState.AOD, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt index 66aa572dbc48..5e3a142dc348 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt @@ -113,7 +113,8 @@ class KeyguardClockViewBinderTest : SysuiTestCase() { id = "WEATHER_CLOCK", name = "", description = "", - useAlternateSmartspaceAODTransition = true + useAlternateSmartspaceAODTransition = true, + useCustomClockScene = true ) whenever(clock.config).thenReturn(clockConfig) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt index b5f668cef08c..4f2b690f9fcd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt @@ -38,7 +38,6 @@ import com.android.systemui.shade.NotificationPanelView import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope @@ -86,7 +85,6 @@ class DefaultDeviceEntrySectionTest : SysuiTestCase() { { mock(DeviceEntryBackgroundViewModel::class.java) }, { falsingManager }, { mock(VibratorHelper::class.java) }, - mock(CoroutineDispatcher::class.java), ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt index 143c4dacb6be..1396b20a800d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt @@ -57,11 +57,18 @@ class AlternateBouncerWindowViewModelTest : SysuiTestCase() { stepFromAlternateBouncer(0f, TransitionState.STARTED), stepFromAlternateBouncer(.4f), stepFromAlternateBouncer(.6f), - stepFromAlternateBouncer(1f), ), testScope, ) assertThat(alternateBouncerWindowRequired).isTrue() + + transitionRepository.sendTransitionSteps( + listOf( + stepFromAlternateBouncer(1.0f, TransitionState.FINISHED), + ), + testScope, + ) + assertThat(alternateBouncerWindowRequired).isFalse() } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt index 7b5dd1fc6c7a..01754c4b5598 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,191 +12,235 @@ * 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.systemui.keyguard.ui.viewmodel -import android.provider.Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags import androidx.test.filters.SmallTest -import com.android.keyguard.ClockEventController -import com.android.keyguard.KeyguardClockSwitch.LARGE -import com.android.keyguard.KeyguardClockSwitch.SMALL +import com.android.keyguard.KeyguardClockSwitch +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.keyguard.data.repository.KeyguardClockRepository -import com.android.systemui.keyguard.data.repository.KeyguardClockRepositoryImpl -import com.android.systemui.keyguard.data.repository.KeyguardRepository -import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory -import com.android.systemui.keyguard.shared.ComposeLockscreen +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository +import com.android.systemui.keyguard.data.repository.keyguardClockRepository +import com.android.systemui.keyguard.data.repository.keyguardRepository +import com.android.systemui.keyguard.shared.model.SettingsClockSize +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.plugins.clocks.ClockFaceConfig import com.android.systemui.plugins.clocks.ClockFaceController import com.android.systemui.res.R -import com.android.systemui.shade.domain.interactor.ShadeInteractor +import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.shared.model.ShadeMode -import com.android.systemui.shared.clocks.ClockRegistry -import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor +import com.android.systemui.testKosmos import com.android.systemui.util.Utils import com.android.systemui.util.mockito.whenever -import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth.assertThat import kotlin.test.Test -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestCoroutineScheduler import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.mockito.Mock -import org.mockito.MockitoAnnotations +import org.mockito.Mockito.mock @SmallTest @RunWith(JUnit4::class) +@DisableSceneContainer class KeyguardClockViewModelTest : SysuiTestCase() { - private lateinit var scheduler: TestCoroutineScheduler - private lateinit var dispatcher: CoroutineDispatcher - private lateinit var scope: TestScope + private lateinit var kosmos: Kosmos private lateinit var underTest: KeyguardClockViewModel - private lateinit var keyguardInteractor: KeyguardInteractor - private lateinit var keyguardRepository: KeyguardRepository - private lateinit var keyguardClockInteractor: KeyguardClockInteractor - private lateinit var keyguardClockRepository: KeyguardClockRepository - private lateinit var fakeSettings: FakeSettings - private val shadeMode = MutableStateFlow<ShadeMode>(ShadeMode.Single) - @Mock private lateinit var clockRegistry: ClockRegistry - @Mock private lateinit var clock: ClockController - @Mock private lateinit var largeClock: ClockFaceController - @Mock private lateinit var clockFaceConfig: ClockFaceConfig - @Mock private lateinit var eventController: ClockEventController - @Mock private lateinit var notifsKeyguardInteractor: NotificationsKeyguardInteractor - @Mock private lateinit var areNotificationsFullyHidden: Flow<Boolean> - @Mock private lateinit var shadeInteractor: ShadeInteractor + private lateinit var testScope: TestScope + private lateinit var clockController: ClockController + private lateinit var config: ClockFaceConfig @Before fun setup() { - MockitoAnnotations.initMocks(this) - KeyguardInteractorFactory.create().let { - keyguardInteractor = it.keyguardInteractor - keyguardRepository = it.repository - } - fakeSettings = FakeSettings() - scheduler = TestCoroutineScheduler() - dispatcher = StandardTestDispatcher(scheduler) - scope = TestScope(dispatcher) - setupMockClock() - keyguardClockRepository = - KeyguardClockRepositoryImpl( - fakeSettings, - clockRegistry, - eventController, - dispatcher, - scope.backgroundScope - ) - keyguardClockInteractor = KeyguardClockInteractor(keyguardClockRepository) - whenever(notifsKeyguardInteractor.areNotificationsFullyHidden) - .thenReturn(areNotificationsFullyHidden) - whenever(shadeInteractor.shadeMode).thenReturn(shadeMode) - underTest = - KeyguardClockViewModel( - keyguardInteractor, - keyguardClockInteractor, - scope.backgroundScope, - notifsKeyguardInteractor, - shadeInteractor, - ) + kosmos = testKosmos() + testScope = kosmos.testScope + underTest = kosmos.keyguardClockViewModel + + clockController = mock(ClockController::class.java) + val largeClock = mock(ClockFaceController::class.java) + config = mock(ClockFaceConfig::class.java) + + whenever(clockController.largeClock).thenReturn(largeClock) + whenever(largeClock.config).thenReturn(config) } @Test - fun testClockSize_alwaysSmallClock() = - scope.runTest { - // When use double line clock is disabled, - // should always return small - fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 0) - keyguardClockRepository.setClockSize(LARGE) - val value = collectLastValue(underTest.clockSize) - assertThat(value()).isEqualTo(SMALL) + fun currentClockLayout_splitShadeOn_clockCentered_largeClock() = + testScope.runTest { + with(kosmos) { + shadeRepository.setShadeMode(ShadeMode.Split) + keyguardRepository.setClockShouldBeCentered(true) + keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + } + val currentClockLayout by collectLastValue(underTest.currentClockLayout) + assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.LARGE_CLOCK) + } + + @Test + fun currentClockLayout_splitShadeOn_clockNotCentered_largeClock_splitShadeLargeClock() = + testScope.runTest { + with(kosmos) { + shadeRepository.setShadeMode(ShadeMode.Split) + keyguardRepository.setClockShouldBeCentered(false) + keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + } + val currentClockLayout by collectLastValue(underTest.currentClockLayout) + assertThat(currentClockLayout) + .isEqualTo(KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_LARGE_CLOCK) + } + + @Test + fun currentClockLayout_splitShadeOn_clockNotCentered_smallClock_splitShadeSmallClock() = + testScope.runTest { + with(kosmos) { + shadeRepository.setShadeMode(ShadeMode.Split) + keyguardRepository.setClockShouldBeCentered(false) + keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL) + } + val currentClockLayout by collectLastValue(underTest.currentClockLayout) + assertThat(currentClockLayout) + .isEqualTo(KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_SMALL_CLOCK) + } + + @Test + fun currentClockLayout_singleShade_smallClock_smallClock() = + testScope.runTest { + with(kosmos) { + shadeRepository.setShadeMode(ShadeMode.Single) + keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL) + } + val currentClockLayout by collectLastValue(underTest.currentClockLayout) + assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.SMALL_CLOCK) + } + + @Test + fun currentClockLayout_singleShade_largeClock_largeClock() = + testScope.runTest { + with(kosmos) { + shadeRepository.setShadeMode(ShadeMode.Single) + keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + } + val currentClockLayout by collectLastValue(underTest.currentClockLayout) + assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.LARGE_CLOCK) + } + + @Test + fun hasCustomPositionUpdatedAnimation_withConfigTrue_isTrue() = + testScope.runTest { + with(kosmos) { + keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + whenever(config.hasCustomPositionUpdatedAnimation).thenReturn(true) + fakeKeyguardClockRepository.setCurrentClock(clockController) + } + + val hasCustomPositionUpdatedAnimation by + collectLastValue(underTest.hasCustomPositionUpdatedAnimation) + assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(true) + } + + @Test + fun hasCustomPositionUpdatedAnimation_withConfigFalse_isFalse() = + testScope.runTest { + with(kosmos) { + keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + + whenever(config.hasCustomPositionUpdatedAnimation).thenReturn(false) + fakeKeyguardClockRepository.setCurrentClock(clockController) + } + + val hasCustomPositionUpdatedAnimation by + collectLastValue(underTest.hasCustomPositionUpdatedAnimation) + assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(false) + } + + @Test + fun testClockSize_alwaysSmallClockSize() = + testScope.runTest { + kosmos.fakeKeyguardClockRepository.setSelectedClockSize(SettingsClockSize.SMALL) + kosmos.keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + + val value by collectLastValue(underTest.clockSize) + assertThat(value).isEqualTo(KeyguardClockSwitch.SMALL) } @Test fun testClockSize_dynamicClockSize() = - scope.runTest { - fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1) - keyguardClockRepository.setClockSize(SMALL) - var value = collectLastValue(underTest.clockSize) - assertThat(value()).isEqualTo(SMALL) - - keyguardClockRepository.setClockSize(LARGE) - value = collectLastValue(underTest.clockSize) - assertThat(value()).isEqualTo(LARGE) + testScope.runTest { + kosmos.keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL) + kosmos.fakeKeyguardClockRepository.setSelectedClockSize(SettingsClockSize.DYNAMIC) + val value by collectLastValue(underTest.clockSize) + assertThat(value).isEqualTo(KeyguardClockSwitch.SMALL) + + kosmos.keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + assertThat(value).isEqualTo(KeyguardClockSwitch.LARGE) } @Test fun isLargeClockVisible_whenLargeClockSize_isTrue() = - scope.runTest { - fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1) - keyguardClockRepository.setClockSize(LARGE) - var value = collectLastValue(underTest.isLargeClockVisible) - assertThat(value()).isEqualTo(true) + testScope.runTest { + kosmos.keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) + val value by collectLastValue(underTest.isLargeClockVisible) + assertThat(value).isEqualTo(true) } @Test fun isLargeClockVisible_whenSmallClockSize_isFalse() = - scope.runTest { - fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1) - keyguardClockRepository.setClockSize(SMALL) - var value = collectLastValue(underTest.isLargeClockVisible) - assertThat(value()).isEqualTo(false) + testScope.runTest { + kosmos.keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL) + val value by collectLastValue(underTest.isLargeClockVisible) + assertThat(value).isEqualTo(false) } @Test - fun testSmallClockTop_splitshade() = - scope.runTest { - shadeMode.value = ShadeMode.Split - if (!ComposeLockscreen.isEnabled) { - assertThat(underTest.getSmallClockTopMargin(context)) - .isEqualTo( - context.resources.getDimensionPixelSize( - R.dimen.keyguard_split_shade_top_margin - ) - ) - } else { - assertThat(underTest.getSmallClockTopMargin(context)) - .isEqualTo( - context.resources.getDimensionPixelSize( - R.dimen.keyguard_split_shade_top_margin - ) - Utils.getStatusBarHeaderHeightKeyguard(context) - ) - } + @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + fun testSmallClockTop_splitShade_composeLockscreenOn() = + testScope.runTest { + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + assertThat(underTest.getSmallClockTopMargin(context)) + .isEqualTo( + context.resources.getDimensionPixelSize( + R.dimen.keyguard_split_shade_top_margin + ) - Utils.getStatusBarHeaderHeightKeyguard(context) + ) } @Test - fun testSmallClockTop_nonSplitshade() = - scope.runTest { - if (!ComposeLockscreen.isEnabled) { - assertThat(underTest.getSmallClockTopMargin(context)) - .isEqualTo( - context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + - Utils.getStatusBarHeaderHeightKeyguard(context) - ) - } else { - assertThat(underTest.getSmallClockTopMargin(context)) - .isEqualTo( - context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) - ) - } + @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + fun testSmallClockTop_splitShade_composeLockscreenOff() = + testScope.runTest { + kosmos.shadeRepository.setShadeMode(ShadeMode.Split) + assertThat(underTest.getSmallClockTopMargin(context)) + .isEqualTo( + context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) + ) } - private fun setupMockClock() { - whenever(clock.largeClock).thenReturn(largeClock) - whenever(largeClock.config).thenReturn(clockFaceConfig) - whenever(clockFaceConfig.hasCustomWeatherDataDisplay).thenReturn(false) - whenever(clockRegistry.createCurrentClock()).thenReturn(clock) - } + @Test + @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + fun testSmallClockTop_nonSplitShade_composeLockscreenOn() = + testScope.runTest { + assertThat(underTest.getSmallClockTopMargin(context)) + .isEqualTo( + context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + ) + } + + @Test + @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + fun testSmallClockTop_nonSplitShade_composeLockscreenOff() = + testScope.runTest { + assertThat(underTest.getSmallClockTopMargin(context)) + .isEqualTo( + context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + + Utils.getStatusBarHeaderHeightKeyguard(context) + ) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelWithKosmosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelWithKosmosTest.kt deleted file mode 100644 index d12980a74a18..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelWithKosmosTest.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.keyguard.ui.viewmodel - -import androidx.test.filters.SmallTest -import com.android.keyguard.KeyguardClockSwitch -import com.android.systemui.SysuiTestCase -import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository -import com.android.systemui.keyguard.data.repository.keyguardClockRepository -import com.android.systemui.keyguard.data.repository.keyguardRepository -import com.android.systemui.kosmos.testScope -import com.android.systemui.plugins.clocks.ClockController -import com.android.systemui.plugins.clocks.ClockFaceConfig -import com.android.systemui.plugins.clocks.ClockFaceController -import com.android.systemui.shade.data.repository.shadeRepository -import com.android.systemui.shade.shared.model.ShadeMode -import com.android.systemui.testKosmos -import com.android.systemui.util.mockito.whenever -import com.google.common.truth.Truth.assertThat -import kotlin.test.Test -import kotlinx.coroutines.test.runTest -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.mockito.Mockito.mock - -@SmallTest -@RunWith(JUnit4::class) -class KeyguardClockViewModelWithKosmosTest : SysuiTestCase() { - private val kosmos = testKosmos() - private val underTest = kosmos.keyguardClockViewModel - private val testScope = kosmos.testScope - - @Test - fun currentClockLayout_splitShadeOn_clockCentered_largeClock() = - testScope.runTest { - with(kosmos) { - shadeRepository.setShadeMode(ShadeMode.Split) - keyguardRepository.setClockShouldBeCentered(true) - keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) - } - val currentClockLayout by collectLastValue(underTest.currentClockLayout) - assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.LARGE_CLOCK) - } - - @Test - fun currentClockLayout_splitShadeOn_clockNotCentered_largeClock_splitShadeLargeClock() = - testScope.runTest { - with(kosmos) { - shadeRepository.setShadeMode(ShadeMode.Split) - keyguardRepository.setClockShouldBeCentered(false) - keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) - } - val currentClockLayout by collectLastValue(underTest.currentClockLayout) - assertThat(currentClockLayout) - .isEqualTo(KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_LARGE_CLOCK) - } - - @Test - fun currentClockLayout_splitShadeOn_clockNotCentered_smallClock_splitShadeSmallClock() = - testScope.runTest { - with(kosmos) { - shadeRepository.setShadeMode(ShadeMode.Split) - keyguardRepository.setClockShouldBeCentered(false) - keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL) - } - val currentClockLayout by collectLastValue(underTest.currentClockLayout) - assertThat(currentClockLayout) - .isEqualTo(KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_SMALL_CLOCK) - } - - @Test - fun currentClockLayout_singleShade_smallClock_smallClock() = - testScope.runTest { - with(kosmos) { - shadeRepository.setShadeMode(ShadeMode.Single) - keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL) - } - val currentClockLayout by collectLastValue(underTest.currentClockLayout) - assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.SMALL_CLOCK) - } - - @Test - fun currentClockLayout_singleShade_largeClock_largeClock() = - testScope.runTest { - with(kosmos) { - shadeRepository.setShadeMode(ShadeMode.Single) - keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) - } - val currentClockLayout by collectLastValue(underTest.currentClockLayout) - assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.LARGE_CLOCK) - } - - @Test - fun hasCustomPositionUpdatedAnimation_withConfigTrue_isTrue() = - testScope.runTest { - with(kosmos) { - keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) - fakeKeyguardClockRepository.setCurrentClock( - buildClockController(hasCustomPositionUpdatedAnimation = true) - ) - } - - val hasCustomPositionUpdatedAnimation by - collectLastValue(underTest.hasCustomPositionUpdatedAnimation) - assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(true) - } - - @Test - fun hasCustomPositionUpdatedAnimation_withConfigFalse_isFalse() = - testScope.runTest { - with(kosmos) { - keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE) - fakeKeyguardClockRepository.setCurrentClock( - buildClockController(hasCustomPositionUpdatedAnimation = false) - ) - } - - val hasCustomPositionUpdatedAnimation by - collectLastValue(underTest.hasCustomPositionUpdatedAnimation) - assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(false) - } - - private fun buildClockController( - hasCustomPositionUpdatedAnimation: Boolean = false - ): ClockController { - val clockController = mock(ClockController::class.java) - val largeClock = mock(ClockFaceController::class.java) - val config = mock(ClockFaceConfig::class.java) - - whenever(clockController.largeClock).thenReturn(largeClock) - whenever(largeClock.config).thenReturn(config) - whenever(config.hasCustomPositionUpdatedAnimation) - .thenReturn(hasCustomPositionUpdatedAnimation) - - return clockController - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt index b70cc30eb3e1..8f73811199ba 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt @@ -29,7 +29,9 @@ import com.android.systemui.media.controls.MediaTestUtils import com.android.systemui.media.controls.data.repository.MediaFilterRepository import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData +import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel import com.android.systemui.media.controls.ui.controller.MediaPlayerData import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger @@ -53,7 +55,6 @@ import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mock import org.mockito.Mockito.never -import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -76,10 +77,10 @@ private val SMARTSPACE_INSTANCE_ID = InstanceId.fakeInstanceId(456)!! @TestableLooper.RunWithLooper class MediaDataFilterImplTest : SysuiTestCase() { - @Mock private lateinit var listener: MediaDataFilterImpl.Listener + @Mock private lateinit var listener: MediaDataProcessor.Listener @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var broadcastSender: BroadcastSender - @Mock private lateinit var mediaDataManager: MediaDataManager + @Mock private lateinit var mediaDataProcessor: MediaDataProcessor @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var executor: Executor @Mock private lateinit var smartspaceData: SmartspaceMediaData @@ -89,7 +90,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Mock private lateinit var cardAction: SmartspaceAction private lateinit var mediaDataFilter: MediaDataFilterImpl - private lateinit var mediaFilterRepository: MediaFilterRepository + private lateinit var repository: MediaFilterRepository private lateinit var testScope: TestScope private lateinit var dataMain: MediaData private lateinit var dataGuest: MediaData @@ -102,7 +103,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { MediaPlayerData.clear() whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false) testScope = TestScope() - mediaFilterRepository = MediaFilterRepository() + repository = MediaFilterRepository(FakeSystemClock()) mediaDataFilter = MediaDataFilterImpl( context, @@ -113,9 +114,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { clock, logger, mediaFlags, - mediaFilterRepository, + repository, ) - mediaDataFilter.mediaDataManager = mediaDataManager + mediaDataFilter.mediaDataProcessor = mediaDataProcessor mediaDataFilter.addListener(listener) // Start all tests as main user @@ -162,91 +163,136 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnDataLoadedForCurrentUser_callsListener() { - // GIVEN a media for main user - mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + fun onDataLoadedForCurrentUser_updatesLoadedStates() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val mediaDataLoadingModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) - // THEN we should tell the listener - verify(listener).onMediaDataLoaded(eq(dataMain.instanceId), eq(true), eq(0), eq(false)) - } + mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + + verify(listener) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true), eq(0), eq(false)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaDataLoadingModel) + } @Test - fun testOnDataLoadedForGuest_doesNotCallListener() { - // GIVEN a media for guest user - mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) + fun onDataLoadedForGuest_doesNotUpdateLoadedStates() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) - // THEN we should NOT tell the listener - verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean()) - } + mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) + + verify(listener, never()) + .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean()) + assertThat(mediaDataLoadedStates).isNotEqualTo(mediaLoadedStatesModel) + } @Test - fun testOnRemovedForCurrent_callsListener() { - // GIVEN a media was removed for main user - mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) - mediaDataFilter.onMediaDataRemoved(KEY) + fun onRemovedForCurrent_updatesLoadedStates() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val mediaLoadedStatesModel = + mutableListOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) - // THEN we should tell the listener - verify(listener).onMediaDataRemoved(eq(dataMain.instanceId)) - } + // GIVEN a media was removed for main user + mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) + + mediaLoadedStatesModel.remove(MediaDataLoadingModel.Loaded(dataMain.instanceId)) + mediaDataFilter.onMediaDataRemoved(KEY) + + verify(listener).onMediaDataRemoved(eq(KEY)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) + } @Test - fun testOnRemovedForGuest_doesNotCallListener() { - // GIVEN a media was removed for guest user - mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) - mediaDataFilter.onMediaDataRemoved(KEY) + fun onRemovedForGuest_doesNotUpdateLoadedStates() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) - // THEN we should NOT tell the listener - verify(listener, never()).onMediaDataRemoved(eq(dataGuest.instanceId)) - } + // GIVEN a media was removed for guest user + mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) + mediaDataFilter.onMediaDataRemoved(KEY) + + verify(listener, never()).onMediaDataRemoved(eq(KEY)) + assertThat(mediaDataLoadedStates).isEmpty() + } @Test - fun testOnUserSwitched_removesOldUserControls() { - // GIVEN that we have a media loaded for main user - mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + fun onUserSwitched_removesOldUserControls() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) - // and we switch to guest user - setUser(USER_GUEST) + // GIVEN that we have a media loaded for main user + mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) - // THEN we should remove the main user's media - verify(listener).onMediaDataRemoved(eq(dataMain.instanceId)) - } + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) + + // and we switch to guest user + setUser(USER_GUEST) + + // THEN we should remove the main user's media + verify(listener).onMediaDataRemoved(eq(KEY)) + assertThat(mediaDataLoadedStates).isEmpty() + } @Test - fun testOnUserSwitched_addsNewUserControls() { - // GIVEN that we had some media for both users - mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) - mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataGuest) - reset(listener) + fun onUserSwitched_addsNewUserControls() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val guestLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataGuest.instanceId)) + val mainLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) - // and we switch to guest user - setUser(USER_GUEST) + // GIVEN that we had some media for both users + mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataGuest) - // THEN we should add back the guest user media - verify(listener).onMediaDataLoaded(eq(dataGuest.instanceId), eq(true), eq(0), eq(false)) + // and we switch to guest user + setUser(USER_GUEST) - // but not the main user's - verify(listener, never()) - .onMediaDataLoaded(eq(dataMain.instanceId), anyBoolean(), anyInt(), anyBoolean()) - } + // THEN we should add back the guest user media + verify(listener) + .onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true), eq(0), eq(false)) + + // but not the main user's + verify(listener, never()) + .onMediaDataLoaded( + eq(KEY), + any(), + eq(dataMain), + anyBoolean(), + anyInt(), + anyBoolean() + ) + assertThat(mediaDataLoadedStates).isEqualTo(guestLoadedStatesModel) + assertThat(mediaDataLoadedStates).isNotEqualTo(mainLoadedStatesModel) + } @Test - fun testOnProfileChanged_profileUnavailable_loadControls() { - // GIVEN that we had some media for both profiles - mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) - mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataPrivateProfile) - reset(listener) + fun onProfileChanged_profileUnavailable_updateStates() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) - // and we change profile status - setPrivateProfileUnavailable() + // GIVEN that we had some media for both profiles + mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataPrivateProfile) - // THEN we should add the private profile media - verify(listener).onMediaDataRemoved(eq(dataPrivateProfile.instanceId)) - } + // and we change profile status + setPrivateProfileUnavailable() + + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) + // THEN we should remove the private profile media + verify(listener).onMediaDataRemoved(eq(KEY_ALT)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) + } @Test fun hasAnyMedia_mediaSet_returnsTrue() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain) assertThat(hasAnyMedia(selectedUserEntries)).isTrue() @@ -255,7 +301,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasAnyMedia_recommendationSet_returnsFalse() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) assertThat(hasAnyMedia(selectedUserEntries)).isFalse() @@ -264,8 +310,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasAnyMediaOrRecommendation_mediaSet_returnsTrue() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain) assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData)) @@ -275,8 +321,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasAnyMediaOrRecommendation_recommendationSet_returnsTrue() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData)) @@ -286,7 +332,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMedia_inactiveMediaSet_returnsFalse() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) val data = dataMain.copy(active = false) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data) @@ -297,7 +343,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMedia_activeMediaSet_returnsTrue() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) val data = dataMain.copy(active = true) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data) @@ -307,9 +353,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMediaOrRecommendation_inactiveMediaSet_returnsFalse() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) val data = dataMain.copy(active = false) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data) @@ -326,9 +372,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMediaOrRecommendation_activeMediaSet_returnsTrue() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) val data = dataMain.copy(active = true) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data) @@ -345,9 +391,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMediaOrRecommendation_inactiveRecommendationSet_returnsFalse() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) whenever(smartspaceData.isActive).thenReturn(false) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -364,9 +410,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMediaOrRecommendation_invalidRecommendationSet_returnsFalse() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) whenever(smartspaceData.isValid()).thenReturn(false) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -383,9 +429,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { @Test fun hasActiveMediaOrRecommendation_activeAndValidRecommendationSet_returnsTrue() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) whenever(smartspaceData.isActive).thenReturn(true) whenever(smartspaceData.isValid()).thenReturn(true) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -401,10 +447,10 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testHasAnyMediaOrRecommendation_onlyCurrentUser() = + fun hasAnyMediaOrRecommendation_onlyCurrentUser() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData)) .isFalse() @@ -415,11 +461,11 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testHasActiveMediaOrRecommendation_onlyCurrentUser() = + fun hasActiveMediaOrRecommendation_onlyCurrentUser() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -443,10 +489,10 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnNotificationRemoved_doesNotHaveMedia() = + fun onNotificationRemoved_doesNotHaveMedia() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain) mediaDataFilter.onMediaDataRemoved(KEY) @@ -456,23 +502,27 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnSwipeToDismiss_setsTimedOut() { + fun onSwipeToDismiss_setsTimedOut() { mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) mediaDataFilter.onSwipeToDismiss() - verify(mediaDataManager).setInactive(eq(KEY), eq(true), eq(true)) + verify(mediaDataProcessor).setInactive(eq(KEY), eq(true), eq(true)) } @Test - fun testOnSmartspaceMediaDataLoaded_noMedia_activeValidRec_prioritizesSmartspace() = + fun onSmartspaceMediaDataLoaded_noMedia_activeValidRec_prioritizesSmartspace() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = + SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY, isPrioritized = true) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(true)) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -482,23 +532,26 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isTrue() assertThat(hasActiveMedia(selectedUserEntries)).isFalse() + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test - fun testOnSmartspaceMediaDataLoaded_noMedia_inactiveRec_showsNothing() = + fun onSmartspaceMediaDataLoaded_noMedia_inactiveRec_showsNothing() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) whenever(smartspaceData.isActive).thenReturn(false) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean()) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean()) + assertThat(recommendationsLoadingState).isEqualTo(SmartspaceMediaLoadingModel.Unknown) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -508,22 +561,29 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isFalse() assertThat(hasActiveMedia(selectedUserEntries)).isFalse() + verify(listener, never()) + .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test - fun testOnSmartspaceMediaDataLoaded_noRecentMedia_activeValidRec_prioritizesSmartspace() = + fun onSmartspaceMediaDataLoaded_noRecentMedia_activeValidRec_prioritizesSmartspace() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = + SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY, isPrioritized = true) val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataOld) clock.advanceTime(MediaDataFilterImpl.SMARTSPACE_MAX_AGE + 100) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(true)) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -533,16 +593,20 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isTrue() assertThat(hasActiveMedia(selectedUserEntries)).isFalse() + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test - fun testOnSmartspaceMediaDataLoaded_noRecentMedia_inactiveRec_showsNothing() = + fun onSmartspaceMediaDataLoaded_noRecentMedia_inactiveRec_showsNothing() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) whenever(smartspaceData.isActive).thenReturn(false) val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) @@ -550,7 +614,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { clock.advanceTime(MediaDataFilterImpl.SMARTSPACE_MAX_AGE + 100) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean()) + assertThat(recommendationsLoadingState).isEqualTo(SmartspaceMediaLoadingModel.Unknown) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -560,32 +624,37 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isFalse() assertThat(hasActiveMedia(selectedUserEntries)).isFalse() + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test - fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_inactiveRec_showsNothing() = + fun onSmartspaceMediaDataLoaded_hasRecentMedia_inactiveRec_showsNothing() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) whenever(smartspaceData.isActive).thenReturn(false) // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) verify(listener) - .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) - reset(listener) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - // THEN we should tell listeners to treat the media as not active instead - verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean()) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean()) + // THEN we should treat the media as not active instead + assertThat(recommendationsLoadingState).isEqualTo(SmartspaceMediaLoadingModel.Unknown) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -595,32 +664,39 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isFalse() assertThat(hasActiveMedia(selectedUserEntries)).isFalse() + verify(listener, never()) + .onMediaDataLoaded(eq(KEY), eq(KEY), any(), anyBoolean(), anyInt(), anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test - fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_activeInvalidRec_usesMedia() = + fun onSmartspaceMediaDataLoaded_hasRecentMedia_activeInvalidRec_usesMedia() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) whenever(smartspaceData.isValid()).thenReturn(false) // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) verify(listener) - .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) // AND we get a smartspace signal runCurrent() mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - // THEN we should tell listeners to treat the media as active instead + // THEN we should treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) - verify(listener) - .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -629,32 +705,58 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) ) .isTrue() + verify(listener) + .onMediaDataLoaded( + eq(KEY), + eq(KEY), + eq(dataCurrentAndActive), + eq(true), + eq(100), + eq(true) + ) // Smartspace update shouldn't be propagated for the empty rec list. - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean()) + assertThat(recommendationsLoadingState).isEqualTo(SmartspaceMediaLoadingModel.Unknown) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID)) } @Test - fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_activeValidRec_usesBoth() = + fun onSmartspaceMediaDataLoaded_hasRecentMedia_activeValidRec_usesBoth() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) + val mediaDataLoadingModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) + mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaDataLoadingModel) verify(listener) - .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) // AND we get a smartspace signal runCurrent() mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - // THEN we should tell listeners to treat the media as active instead + // THEN we should treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener) - .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true)) + .onMediaDataLoaded( + eq(KEY), + eq(KEY), + eq(dataCurrentAndActive), + eq(true), + eq(100), + eq(true) + ) + assertThat(mediaDataLoadedStates).isEqualTo(mediaDataLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -664,22 +766,28 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isTrue() // Smartspace update should also be propagated but not prioritized. - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false)) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID)) } @Test - fun testOnSmartspaceMediaDataRemoved_usedSmartspace_clearsSmartspace() = + fun onSmartspaceMediaDataRemoved_usedSmartspace_clearsSmartspace() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Removed(SMARTSPACE_KEY) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -692,26 +800,42 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnSmartspaceMediaDataRemoved_usedMediaAndSmartspace_clearsBoth() = + fun onSmartspaceMediaDataRemoved_usedMediaAndSmartspace_clearsBoth() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Removed(SMARTSPACE_KEY) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) verify(listener) - .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) runCurrent() mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener) - .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true)) + .onMediaDataLoaded( + eq(KEY), + eq(KEY), + eq(dataCurrentAndActive), + eq(true), + eq(100), + eq(true) + ) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -724,17 +848,22 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnSmartspaceLoaded_persistentEnabled_isInactive_notifiesListeners() = + fun onSmartspaceLoaded_persistentEnabled_isInactive() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true) whenever(smartspaceData.isActive).thenReturn(false) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false)) + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -748,11 +877,16 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() = + fun onSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true) whenever(smartspaceData.isActive).thenReturn(false) @@ -760,16 +894,20 @@ class MediaDataFilterImplTest : SysuiTestCase() { // If there is media that was recently played but inactive val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + verify(listener) - .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) - reset(listener) // And an inactive recommendation is loaded mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // Smartspace is loaded but the media stays inactive - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false)) - verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean()) + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(listener, never()) + .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean()) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -783,7 +921,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { } @Test - fun testOnSwipeToDismiss_persistentEnabled_recommendationSetInactive() { + fun onSwipeToDismiss_persistentEnabled_recommendationSetInactive() { whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true) val data = @@ -796,22 +934,29 @@ class MediaDataFilterImplTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, data) mediaDataFilter.onSwipeToDismiss() - verify(mediaDataManager).setRecommendationInactive(eq(SMARTSPACE_KEY)) - verify(mediaDataManager, never()) + verify(mediaDataProcessor).setRecommendationInactive(eq(SMARTSPACE_KEY)) + verify(mediaDataProcessor, never()) .dismissSmartspaceRecommendation(eq(SMARTSPACE_KEY), anyLong()) } @Test - fun testSmartspaceLoaded_shouldTriggerResume_doesTrigger() = + fun smartspaceLoaded_shouldTriggerResume_doesTrigger() = testScope.runTest { - val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries) - val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData) - val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId) + val selectedUserEntries by collectLastValue(repository.selectedUserEntries) + val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData) + val reactivatedKey by collectLastValue(repository.reactivatedId) + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + verify(listener) - .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) // AND we get a smartspace signal with extra to trigger resume runCurrent() @@ -819,10 +964,18 @@ class MediaDataFilterImplTest : SysuiTestCase() { whenever(cardAction.extras).thenReturn(extras) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - // THEN we should tell listeners to treat the media as active instead + // THEN we should treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener) - .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true)) + .onMediaDataLoaded( + eq(KEY), + eq(KEY), + eq(dataCurrentAndActive), + eq(true), + eq(100), + eq(true) + ) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -831,27 +984,42 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) ) .isTrue() - // And send the smartspace data, but not prioritized - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false)) + // And update the smartspace data state, but not prioritized + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) } @Test - fun testSmartspaceLoaded_notShouldTriggerResume_doesNotTrigger() { - // WHEN we have media that was recently played, but not currently active - val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) - mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) - verify(listener).onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false)) + fun smartspaceLoaded_notShouldTriggerResume_doesNotTrigger() = + testScope.runTest { + val mediaDataLoadedStates by collectLastValue(repository.mediaDataLoadedStates) + val recommendationsLoadingState by + collectLastValue(repository.recommendationsLoadingState) + val recommendationsLoadingModel = SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) + val mediaLoadedStatesModel = listOf(MediaDataLoadingModel.Loaded(dataMain.instanceId)) - // AND we get a smartspace signal with extra to not trigger resume - val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) } - whenever(cardAction.extras).thenReturn(extras) - mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) + // WHEN we have media that was recently played, but not currently active + val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) + mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) - // THEN listeners are not updated to show media - verify(listener, never()).onMediaDataLoaded(any(), eq(true), eq(100), eq(true)) - // But the smartspace update is still propagated - verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false)) - } + verify(listener) + .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStatesModel) + + // AND we get a smartspace signal with extra to not trigger resume + val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) } + whenever(cardAction.extras).thenReturn(extras) + mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) + + // THEN listeners are not updated to show media + verify(listener, never()) + .onMediaDataLoaded(eq(KEY), eq(KEY), any(), eq(true), eq(100), eq(true)) + // But the smartspace update is still propagated + verify(listener) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel) + } private fun hasActiveMediaOrRecommendation( entries: Map<InstanceId, MediaData>?, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt index 5c275b454681..ffb50c1ee3ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt @@ -210,7 +210,7 @@ class MediaDataProcessorTest : SysuiTestCase() { ) testDispatcher = UnconfinedTestDispatcher() testScope = TestScope(testDispatcher) - mediaFilterRepository = MediaFilterRepository() + mediaFilterRepository = MediaFilterRepository(clock) mediaDataRepository = MediaDataRepository(mediaFlags, dumpManager) mediaDataProcessor = MediaDataProcessor( diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt index a73bb2cdf79a..e5d3082bb245 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt @@ -16,29 +16,54 @@ package com.android.systemui.media.controls.ui.controller +import android.animation.AnimatorSet +import android.content.Context import android.content.res.Configuration import android.content.res.Configuration.ORIENTATION_LANDSCAPE +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.RippleDrawable import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View +import android.view.ViewGroup +import android.view.animation.Interpolator +import android.widget.FrameLayout +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.SeekBar +import android.widget.TextView import androidx.constraintlayout.widget.ConstraintSet +import androidx.lifecycle.LiveData import androidx.test.filters.SmallTest +import com.android.internal.widget.CachingIconView import com.android.systemui.SysuiTestCase +import com.android.systemui.media.controls.ui.view.GutsViewHolder import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.controls.ui.view.MediaViewHolder import com.android.systemui.media.controls.ui.view.RecommendationViewHolder +import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.res.R +import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView +import com.android.systemui.surfaceeffects.ripple.MultiRippleView +import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView import com.android.systemui.util.animation.MeasurementInput import com.android.systemui.util.animation.TransitionLayout import com.android.systemui.util.animation.TransitionViewState import com.android.systemui.util.animation.WidgetState +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.mockito.withArgCaptor +import com.android.systemui.util.settings.GlobalSettings +import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat import junit.framework.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.floatThat import org.mockito.Mock +import org.mockito.Mockito import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify @@ -55,6 +80,31 @@ class MediaViewControllerTest : SysuiTestCase() { com.android.systemui.statusbar.phone.ConfigurationControllerImpl(context) private var player = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0) private var recommendation = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0) + private val clock = FakeSystemClock() + private lateinit var mainExecutor: FakeExecutor + private lateinit var seekBar: SeekBar + private lateinit var multiRippleView: MultiRippleView + private lateinit var turbulenceNoiseView: TurbulenceNoiseView + private lateinit var loadingEffectView: LoadingEffectView + private lateinit var settings: ImageButton + private lateinit var cancel: View + private lateinit var cancelText: TextView + private lateinit var dismiss: FrameLayout + private lateinit var dismissText: TextView + private lateinit var titleText: TextView + private lateinit var artistText: TextView + private lateinit var explicitIndicator: CachingIconView + private lateinit var seamless: ViewGroup + private lateinit var seamlessButton: View + private lateinit var seamlessIcon: ImageView + private lateinit var seamlessText: TextView + private lateinit var scrubbingElapsedTimeView: TextView + private lateinit var scrubbingTotalTimeView: TextView + private lateinit var actionPlayPause: ImageButton + private lateinit var actionNext: ImageButton + private lateinit var actionPrev: ImageButton + @Mock private lateinit var seamlessBackground: RippleDrawable + @Mock private lateinit var albumView: ImageView @Mock lateinit var logger: MediaViewLogger @Mock private lateinit var mockViewState: TransitionViewState @Mock private lateinit var mockCopiedState: TransitionViewState @@ -64,6 +114,14 @@ class MediaViewControllerTest : SysuiTestCase() { @Mock private lateinit var mediaSubTitleWidgetState: WidgetState @Mock private lateinit var mediaContainerWidgetState: WidgetState @Mock private lateinit var mediaFlags: MediaFlags + @Mock private lateinit var seekBarViewModel: SeekBarViewModel + @Mock private lateinit var seekBarData: LiveData<SeekBarViewModel.Progress> + @Mock private lateinit var globalSettings: GlobalSettings + @Mock private lateinit var viewHolder: MediaViewHolder + @Mock private lateinit var view: TransitionLayout + @Mock private lateinit var mockAnimator: AnimatorSet + @Mock private lateinit var gutsViewHolder: GutsViewHolder + @Mock private lateinit var gutsText: TextView private val delta = 0.1F @@ -72,14 +130,30 @@ class MediaViewControllerTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) + mainExecutor = FakeExecutor(clock) mediaViewController = - MediaViewController( - context, - configurationController, - mediaHostStatesManager, - logger, - mediaFlags, - ) + object : + MediaViewController( + context, + configurationController, + mediaHostStatesManager, + logger, + seekBarViewModel, + mainExecutor, + mediaFlags, + globalSettings, + ) { + override fun loadAnimator( + context: Context, + animId: Int, + motionInterpolator: Interpolator?, + vararg targets: View? + ): AnimatorSet { + return mockAnimator + } + } + initGutsViewHolderMocks() + initMediaViewHolderMocks() } @Test @@ -299,4 +373,270 @@ class MediaViewControllerTest : SysuiTestCase() { verify(mediaTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta } verify(mediaSubTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta } } + + @Test + fun attachPlayer_seekBarDisabled_seekBarVisibilityIsSetToInvisible() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + getEnabledChangeListener().onEnabledChanged(enabled = true) + getEnabledChangeListener().onEnabledChanged(enabled = false) + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar)) + .isEqualTo(ConstraintSet.INVISIBLE) + } + + @Test + fun attachPlayer_seekBarEnabled_seekBarVisible() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + getEnabledChangeListener().onEnabledChanged(enabled = true) + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar)) + .isEqualTo(ConstraintSet.VISIBLE) + } + + @Test + fun attachPlayer_seekBarStatusUpdate_seekBarVisibilityChanges() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + getEnabledChangeListener().onEnabledChanged(enabled = true) + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar)) + .isEqualTo(ConstraintSet.VISIBLE) + + getEnabledChangeListener().onEnabledChanged(enabled = false) + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar)) + .isEqualTo(ConstraintSet.INVISIBLE) + } + + @Test + fun attachPlayer_notScrubbing_scrubbingViewsGone() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + mediaViewController.canShowScrubbingTime = true + getScrubbingChangeListener().onScrubbingChanged(true) + getScrubbingChangeListener().onScrubbingChanged(false) + mainExecutor.runAllReady() + + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.GONE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.GONE) + } + + @Test + fun setIsScrubbing_noSemanticActions_scrubbingViewsGone() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + mediaViewController.canShowScrubbingTime = false + getScrubbingChangeListener().onScrubbingChanged(true) + mainExecutor.runAllReady() + + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.GONE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.GONE) + } + + @Test + fun setIsScrubbing_noPrevButton_scrubbingTimesNotShown() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + mediaViewController.setUpNextButtonInfo(true) + mediaViewController.setUpPrevButtonInfo(false) + getScrubbingChangeListener().onScrubbingChanged(true) + mainExecutor.runAllReady() + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext)) + .isEqualTo(ConstraintSet.VISIBLE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.GONE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.GONE) + } + + @Test + fun setIsScrubbing_noNextButton_scrubbingTimesNotShown() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + mediaViewController.setUpNextButtonInfo(false) + mediaViewController.setUpPrevButtonInfo(true) + getScrubbingChangeListener().onScrubbingChanged(true) + mainExecutor.runAllReady() + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev)) + .isEqualTo(ConstraintSet.VISIBLE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.GONE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.GONE) + } + + @Test + fun setIsScrubbing_scrubbingViewsShownAndPrevNextHiddenOnlyInExpanded() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + mediaViewController.setUpNextButtonInfo(true) + mediaViewController.setUpPrevButtonInfo(true) + mediaViewController.canShowScrubbingTime = true + getScrubbingChangeListener().onScrubbingChanged(true) + mainExecutor.runAllReady() + + // Only in expanded, we should show the scrubbing times and hide prev+next + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev)) + .isEqualTo(ConstraintSet.GONE) + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext)) + .isEqualTo(ConstraintSet.GONE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.VISIBLE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.VISIBLE) + } + + @Test + fun setIsScrubbing_trueThenFalse_reservePrevAndNextButtons() { + whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true) + + mediaViewController.attachPlayer(viewHolder) + mediaViewController.setUpNextButtonInfo(true, ConstraintSet.INVISIBLE) + mediaViewController.setUpPrevButtonInfo(true, ConstraintSet.INVISIBLE) + mediaViewController.canShowScrubbingTime = true + + getScrubbingChangeListener().onScrubbingChanged(true) + mainExecutor.runAllReady() + + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev)) + .isEqualTo(ConstraintSet.INVISIBLE) + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext)) + .isEqualTo(ConstraintSet.INVISIBLE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.VISIBLE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.VISIBLE) + + getScrubbingChangeListener().onScrubbingChanged(false) + mainExecutor.runAllReady() + + // Only in expanded, we should hide the scrubbing times and show prev+next + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev)) + .isEqualTo(ConstraintSet.VISIBLE) + assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext)) + .isEqualTo(ConstraintSet.VISIBLE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time) + ) + .isEqualTo(ConstraintSet.GONE) + assertThat( + mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time) + ) + .isEqualTo(ConstraintSet.GONE) + } + + private fun initGutsViewHolderMocks() { + settings = ImageButton(context) + cancel = View(context) + cancelText = TextView(context) + dismiss = FrameLayout(context) + dismissText = TextView(context) + whenever(gutsViewHolder.gutsText).thenReturn(gutsText) + whenever(gutsViewHolder.settings).thenReturn(settings) + whenever(gutsViewHolder.cancel).thenReturn(cancel) + whenever(gutsViewHolder.cancelText).thenReturn(cancelText) + whenever(gutsViewHolder.dismiss).thenReturn(dismiss) + whenever(gutsViewHolder.dismissText).thenReturn(dismissText) + } + + private fun initMediaViewHolderMocks() { + titleText = TextView(context) + artistText = TextView(context) + explicitIndicator = CachingIconView(context).also { it.id = R.id.media_explicit_indicator } + seamless = FrameLayout(context) + seamless.foreground = seamlessBackground + seamlessButton = View(context) + seamlessIcon = ImageView(context) + seamlessText = TextView(context) + seekBar = SeekBar(context).also { it.id = R.id.media_progress_bar } + + actionPlayPause = ImageButton(context).also { it.id = R.id.actionPlayPause } + actionPrev = ImageButton(context).also { it.id = R.id.actionPrev } + actionNext = ImageButton(context).also { it.id = R.id.actionNext } + scrubbingElapsedTimeView = + TextView(context).also { it.id = R.id.media_scrubbing_elapsed_time } + scrubbingTotalTimeView = TextView(context).also { it.id = R.id.media_scrubbing_total_time } + + multiRippleView = MultiRippleView(context, null) + turbulenceNoiseView = TurbulenceNoiseView(context, null) + loadingEffectView = LoadingEffectView(context, null) + + whenever(viewHolder.player).thenReturn(view) + whenever(view.context).thenReturn(context) + whenever(viewHolder.albumView).thenReturn(albumView) + whenever(albumView.foreground).thenReturn(Mockito.mock(Drawable::class.java)) + whenever(viewHolder.titleText).thenReturn(titleText) + whenever(viewHolder.artistText).thenReturn(artistText) + whenever(viewHolder.explicitIndicator).thenReturn(explicitIndicator) + whenever(seamlessBackground.getDrawable(0)) + .thenReturn(Mockito.mock(GradientDrawable::class.java)) + whenever(viewHolder.seamless).thenReturn(seamless) + whenever(viewHolder.seamlessButton).thenReturn(seamlessButton) + whenever(viewHolder.seamlessIcon).thenReturn(seamlessIcon) + whenever(viewHolder.seamlessText).thenReturn(seamlessText) + whenever(viewHolder.seekBar).thenReturn(seekBar) + whenever(viewHolder.scrubbingElapsedTimeView).thenReturn(scrubbingElapsedTimeView) + whenever(viewHolder.scrubbingTotalTimeView).thenReturn(scrubbingTotalTimeView) + whenever(viewHolder.gutsViewHolder).thenReturn(gutsViewHolder) + whenever(seekBarViewModel.progress).thenReturn(seekBarData) + + // Action buttons + whenever(viewHolder.actionPlayPause).thenReturn(actionPlayPause) + whenever(viewHolder.getAction(R.id.actionNext)).thenReturn(actionNext) + whenever(viewHolder.getAction(R.id.actionPrev)).thenReturn(actionPrev) + whenever(viewHolder.getAction(R.id.actionPlayPause)).thenReturn(actionPlayPause) + + whenever(viewHolder.multiRippleView).thenReturn(multiRippleView) + whenever(viewHolder.turbulenceNoiseView).thenReturn(turbulenceNoiseView) + whenever(viewHolder.loadingEffectView).thenReturn(loadingEffectView) + } + + private fun getScrubbingChangeListener(): SeekBarViewModel.ScrubbingChangeListener = + withArgCaptor { + verify(seekBarViewModel).setScrubbingChangeListener(capture()) + } + + private fun getEnabledChangeListener(): SeekBarViewModel.EnabledChangeListener = withArgCaptor { + verify(seekBarViewModel).setEnabledChangeListener(capture()) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index ca403e0addec..9bb21f020be8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -123,11 +123,22 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { mMediaControllers.add(mMediaController); when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers); - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mContext, + TEST_PACKAGE, + mContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); // Using a fake package will cause routing operations to fail, so we intercept // scanning-related operations. diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java index c9eb67e070ab..2e6388ae3914 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java @@ -124,11 +124,22 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase { when(mLocalBluetoothLeBroadcast.getBroadcastCode()).thenReturn( BROADCAST_CODE_TEST.getBytes(StandardCharsets.UTF_8)); - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mContext, + TEST_PACKAGE, + mContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputBroadcastDialog = new MediaOutputBroadcastDialog(mContext, false, mBroadcastSender, mMediaOutputController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 980eb5948615..4eb00385f857 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -194,11 +194,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn( mCachedBluetoothDeviceManager); - mMediaOutputController = new MediaOutputController(mSpyContext, mPackageName, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mSpyContext, + mPackageName, + mContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(false); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; @@ -276,11 +287,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void start_withoutPackageName_verifyMediaControllerInit() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mSpyContext, + null, + mContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); mMediaOutputController.start(mCb); @@ -306,11 +328,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void stop_withoutPackageName_verifyMediaControllerDeinit() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mSpyContext, + null, + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); mMediaOutputController.start(mCb); @@ -550,12 +583,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getAppSourceName_packageNameIsNull_returnsNull() { - MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext, - "", - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + MediaOutputController testMediaOutputController = + new MediaOutputController( + mSpyContext, + "", + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); testMediaOutputController.start(mCb); reset(mCb); @@ -573,12 +616,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getNotificationSmallIcon_packageNameIsNull_returnsNull() { - MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext, - "", - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + MediaOutputController testMediaOutputController = + new MediaOutputController( + mSpyContext, + "", + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); testMediaOutputController.start(mCb); reset(mCb); @@ -609,12 +662,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void addDeviceToPlayMedia_callsLocalMediaManager() { - MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext, - null, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + MediaOutputController testMediaOutputController = + new MediaOutputController( + mSpyContext, + null, + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); LocalMediaManager mockLocalMediaManager = mock(LocalMediaManager.class); testMediaOutputController.mLocalMediaManager = mockLocalMediaManager; @@ -625,12 +688,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void removeDeviceFromPlayMedia_callsLocalMediaManager() { - MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext, - null, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + MediaOutputController testMediaOutputController = + new MediaOutputController( + mSpyContext, + null, + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); LocalMediaManager mockLocalMediaManager = mock(LocalMediaManager.class); testMediaOutputController.mLocalMediaManager = mockLocalMediaManager; @@ -894,11 +967,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getNotificationLargeIcon_withoutPackageName_returnsNull() { - mMediaOutputController = new MediaOutputController(mSpyContext, null, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mSpyContext, + null, + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); } @@ -1085,12 +1169,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void setTemporaryAllowListExceptionIfNeeded_packageNameIsNull_NoAction() { - MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext, - null, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + MediaOutputController testMediaOutputController = + new MediaOutputController( + mSpyContext, + null, + mSpyContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java index 83def8e47651..3b6a88af1ee0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java @@ -18,6 +18,7 @@ package com.android.systemui.media.dialog; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -61,7 +62,7 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { mMediaOutputDialogReceiver.onReceive(getContext(), intent); verify(mMockMediaOutputDialogManager, times(1)) - .createAndShow(getContext().getPackageName(), false, null); + .createAndShow(eq(getContext().getPackageName()), eq(false), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -72,7 +73,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { intent.putExtra("Wrong Package Name Key", getContext().getPackageName()); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -82,7 +84,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { Intent intent = new Intent(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -95,7 +98,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName()); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -108,9 +112,10 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName()); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, times(1)) - .createAndShow(getContext().getPackageName(), true, null); + .createAndShow(eq(getContext().getPackageName()), eq(true), any()); } @Test @@ -121,7 +126,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { intent.putExtra("Wrong Package Name Key", getContext().getPackageName()); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -133,7 +139,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -145,7 +152,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName()); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } @@ -155,7 +163,8 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { Intent intent = new Intent("UnKnown Action"); mMediaOutputDialogReceiver.onReceive(getContext(), intent); - verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any()); + verify(mMockMediaOutputDialogManager, never()) + .createAndShow(any(), anyBoolean(), any(), any()); verify(mMockMediaOutputBroadcastDialogManager, never()) .createAndShow(any(), anyBoolean(), any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index 84300da82a30..cdef9644efa9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -137,11 +137,22 @@ public class MediaOutputDialogTest extends SysuiTestCase { Mockito.eq(userHandle))).thenReturn( mMediaControllers); - mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, - mMediaSessionManager, mLocalBluetoothManager, mStarter, - mNotifCollection, mDialogTransitionAnimator, - mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags, mUserTracker); + mMediaOutputController = + new MediaOutputController( + mContext, + TEST_PACKAGE, + mContext.getUser(), + mMediaSessionManager, + mLocalBluetoothManager, + mStarter, + mNotifCollection, + mDialogTransitionAnimator, + mNearbyMediaDevicesManager, + mAudioManager, + mPowerExemptionManager, + mKeyguardManager, + mFlags, + mUserTracker); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputDialog = makeTestDialog(mMediaOutputController); mMediaOutputDialog.show(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt index 8b79fa45b8ba..253607846e0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt @@ -258,6 +258,7 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() { colorBackground = 0, isForegroundTask = isForegroundTask, userType = RecentTask.UserType.STANDARD, + splitBounds = null, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt index dd621129ad9a..6ac86f58517d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt @@ -195,6 +195,7 @@ class ShellRecentTaskListProviderTest : SysuiTestCase() { colorBackground = null, isForegroundTask = false, userType = userType, + splitBounds = null ) private fun createSingleTask( diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt index a84008b0353c..f4c5ccfc8388 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt @@ -18,22 +18,28 @@ package com.android.systemui.mediaprojection.appselector.view import android.app.ActivityOptions import android.app.IActivityTaskManager +import android.graphics.Rect import android.os.Bundle import android.view.View import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX +import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN import com.android.systemui.SysuiTestCase import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler import com.android.systemui.mediaprojection.appselector.data.RecentTask import com.android.systemui.util.mockito.mock +import com.android.wm.shell.splitscreen.SplitScreen +import com.android.wm.shell.util.SplitBounds import com.google.common.truth.Expect import com.google.common.truth.Truth.assertThat +import java.util.Optional import org.junit.Rule import org.junit.Test import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito.any +import org.mockito.Mockito.anyInt import org.mockito.Mockito.verify @SmallTest @@ -46,9 +52,10 @@ class MediaProjectionRecentsViewControllerTest : SysuiTestCase() { private val taskViewSizeProvider = mock<TaskPreviewSizeProvider>() private val activityTaskManager = mock<IActivityTaskManager>() private val resultHandler = mock<MediaProjectionAppSelectorResultHandler>() + private val splitScreen = Optional.of(mock<SplitScreen>()) private val bundleCaptor = ArgumentCaptor.forClass(Bundle::class.java) - private val task = + private val fullScreenTask = RecentTask( taskId = 123, displayId = 456, @@ -58,6 +65,20 @@ class MediaProjectionRecentsViewControllerTest : SysuiTestCase() { colorBackground = null, isForegroundTask = false, userType = RecentTask.UserType.STANDARD, + splitBounds = null + ) + + private val splitScreenTask = + RecentTask( + taskId = 123, + displayId = 456, + userId = 789, + topActivityComponent = null, + baseIntentComponent = null, + colorBackground = null, + isForegroundTask = false, + userType = RecentTask.UserType.STANDARD, + splitBounds = SplitBounds(Rect(), Rect(), 0, 0, 0) ) private val taskView = @@ -70,61 +91,97 @@ class MediaProjectionRecentsViewControllerTest : SysuiTestCase() { tasksAdapterFactory, taskViewSizeProvider, activityTaskManager, - resultHandler + resultHandler, + splitScreen, ) @Test - fun onRecentAppClicked_taskWithSameIdIsStartedFromRecents() { - controller.onRecentAppClicked(task, taskView) + fun onRecentAppClicked_fullScreenTaskWithSameIdIsStartedFromRecents() { + controller.onRecentAppClicked(fullScreenTask, taskView) - verify(activityTaskManager).startActivityFromRecents(eq(task.taskId), any()) + verify(activityTaskManager).startActivityFromRecents(eq(fullScreenTask.taskId), any()) + } + + @Test + fun onRecentAppClicked_splitScreenTaskWithSameIdIsStartedFromRecents() { + mSetFlagsRule.enableFlags(FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN) + controller.onRecentAppClicked(splitScreenTask, taskView) + + verify(splitScreen.get()) + .startTasks( + eq(splitScreenTask.taskId), + any(), + anyInt(), + any(), + anyInt(), + anyInt(), + any(), + any() + ) } @Test fun onRecentAppClicked_launchDisplayIdIsSet() { - controller.onRecentAppClicked(task, taskView) + controller.onRecentAppClicked(fullScreenTask, taskView) - assertThat(getStartedTaskActivityOptions().launchDisplayId).isEqualTo(task.displayId) + assertThat(getStartedTaskActivityOptions(fullScreenTask.taskId).launchDisplayId) + .isEqualTo(fullScreenTask.displayId) } @Test - fun onRecentAppClicked_taskNotInForeground_usesScaleUpAnimation() { - controller.onRecentAppClicked(task, taskView) + fun onRecentAppClicked_fullScreenTaskNotInForeground_usesScaleUpAnimation() { + assertThat(fullScreenTask.isForegroundTask).isFalse() + controller.onRecentAppClicked(fullScreenTask, taskView) - assertThat(getStartedTaskActivityOptions().animationType) + assertThat(getStartedTaskActivityOptions(fullScreenTask.taskId).animationType) .isEqualTo(ActivityOptions.ANIM_SCALE_UP) } @Test - fun onRecentAppClicked_taskInForeground_flagOff_usesScaleUpAnimation() { + fun onRecentAppClicked_fullScreenTaskInForeground_flagOff_usesScaleUpAnimation() { mSetFlagsRule.disableFlags(FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX) - controller.onRecentAppClicked(task, taskView) + controller.onRecentAppClicked(fullScreenTask, taskView) - assertThat(getStartedTaskActivityOptions().animationType) + assertThat(getStartedTaskActivityOptions(fullScreenTask.taskId).animationType) .isEqualTo(ActivityOptions.ANIM_SCALE_UP) } @Test - fun onRecentAppClicked_taskInForeground_flagOn_usesDefaultAnimation() { + fun onRecentAppClicked_fullScreenTaskInForeground_flagOn_usesDefaultAnimation() { mSetFlagsRule.enableFlags(FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX) - val foregroundTask = task.copy(isForegroundTask = true) + assertForegroundTaskUsesDefaultCloseAnimation(fullScreenTask) + } + @Test + fun onRecentAppClicked_splitScreenTaskInForeground_flagOn_usesDefaultAnimation() { + mSetFlagsRule.enableFlags( + FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX, + FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN + ) + assertForegroundTaskUsesDefaultCloseAnimation(splitScreenTask) + } + + private fun assertForegroundTaskUsesDefaultCloseAnimation(task: RecentTask) { + val foregroundTask = task.copy(isForegroundTask = true) controller.onRecentAppClicked(foregroundTask, taskView) expect - .that(getStartedTaskActivityOptions().animationType) + .that(getStartedTaskActivityOptions(foregroundTask.taskId).animationType) .isEqualTo(ActivityOptions.ANIM_CUSTOM) - expect.that(getStartedTaskActivityOptions().overrideTaskTransition).isTrue() expect - .that(getStartedTaskActivityOptions().customExitResId) + .that(getStartedTaskActivityOptions(foregroundTask.taskId).overrideTaskTransition) + .isTrue() + expect + .that(getStartedTaskActivityOptions(foregroundTask.taskId).customExitResId) .isEqualTo(com.android.internal.R.anim.resolver_close_anim) - expect.that(getStartedTaskActivityOptions().customEnterResId).isEqualTo(0) + expect + .that(getStartedTaskActivityOptions(foregroundTask.taskId).customEnterResId) + .isEqualTo(0) } - private fun getStartedTaskActivityOptions(): ActivityOptions { - verify(activityTaskManager) - .startActivityFromRecents(eq(task.taskId), bundleCaptor.capture()) + private fun getStartedTaskActivityOptions(taskId: Int): ActivityOptions { + verify(activityTaskManager).startActivityFromRecents(eq(taskId), bundleCaptor.capture()) return ActivityOptions.fromBundle(bundleCaptor.value) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt new file mode 100644 index 000000000000..e044eeca8303 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.mediaprojection.permission + +import android.app.AlertDialog +import android.media.projection.MediaProjectionConfig +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.WindowManager +import android.widget.Spinner +import android.widget.TextView +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.FeatureFlagsClassic +import com.android.systemui.flags.Flags +import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger +import com.android.systemui.res.R +import com.android.systemui.statusbar.phone.AlertDialogWithDelegate +import com.android.systemui.statusbar.phone.SystemUIDialog +import com.android.systemui.util.mockito.mock +import junit.framework.Assert.assertEquals +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.`when` as whenever + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() { + + private lateinit var dialog: AlertDialog + + private val flags = mock<FeatureFlagsClassic>() + private val onStartRecordingClicked = mock<Runnable>() + private val mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>() + + private val mediaProjectionConfig: MediaProjectionConfig = + MediaProjectionConfig.createConfigForDefaultDisplay() + private val appName: String = "testApp" + private val hostUid: Int = 12345 + + private val resIdSingleApp = R.string.screen_share_permission_dialog_option_single_app + private val resIdFullScreen = R.string.screen_share_permission_dialog_option_entire_screen + private val resIdSingleAppDisabled = + R.string.media_projection_entry_app_permission_dialog_single_app_disabled + + @Before + fun setUp() { + whenever(flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)).thenReturn(true) + } + + @After + fun teardown() { + if (::dialog.isInitialized) { + dialog.dismiss() + } + } + + @Test + fun showDialog_forceShowPartialScreenShareFalse() { + // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and + // overrideDisableSingleAppOption = false + val overrideDisableSingleAppOption = false + setUpAndShowDialog(overrideDisableSingleAppOption) + + val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner) + val secondOptionText = + spinner.adapter + .getDropDownView(1, null, spinner) + .findViewById<TextView>(android.R.id.text2) + ?.text + + // check that the first option is full screen and enabled + assertEquals(context.getString(resIdFullScreen), spinner.selectedItem) + + // check that the second option is single app and disabled + assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionText) + } + + @Test + fun showDialog_forceShowPartialScreenShareTrue() { + // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and + // overrideDisableSingleAppOption = true + val overrideDisableSingleAppOption = true + setUpAndShowDialog(overrideDisableSingleAppOption) + + val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner) + val secondOptionText = + spinner.adapter + .getDropDownView(1, null, spinner) + .findViewById<TextView>(android.R.id.text1) + ?.text + + // check that the first option is single app and enabled + assertEquals(context.getString(resIdSingleApp), spinner.selectedItem) + + // check that the second option is full screen and enabled + assertEquals(context.getString(resIdFullScreen), secondOptionText) + } + + private fun setUpAndShowDialog(overrideDisableSingleAppOption: Boolean) { + val delegate = + MediaProjectionPermissionDialogDelegate( + context, + mediaProjectionConfig, + {}, + onStartRecordingClicked, + appName, + overrideDisableSingleAppOption, + hostUid, + mediaProjectionMetricsLogger + ) + + dialog = AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate) + SystemUIDialog.applyFlags(dialog) + SystemUIDialog.setDialogSize(dialog) + + dialog.window?.addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS + ) + + delegate.onCreate(dialog, savedInstanceState = null) + dialog.show() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java index a702ddaa579e..224e75514ef6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.res.Configuration; import android.view.IWindowManager; import android.view.accessibility.AccessibilityManager; @@ -55,6 +56,8 @@ import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.FakeConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import dagger.Lazy; @@ -117,6 +120,7 @@ public class NavBarHelperTest extends SysuiTestCase { EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory; @Mock NotificationShadeWindowController mNotificationShadeWindowController; + ConfigurationController mConfigurationController = new FakeConfigurationController(); private AccessibilityManager.AccessibilityServicesStateChangeListener mAccessibilityServicesStateChangeListener; @@ -144,9 +148,8 @@ public class NavBarHelperTest extends SysuiTestCase { mSystemActions, mOverviewProxyService, mAssistManagerLazy, () -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class), mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker, - mDisplayTracker, mNotificationShadeWindowController, mDumpManager, mCommandQueue, - mSynchronousExecutor); - + mDisplayTracker, mNotificationShadeWindowController, mConfigurationController, + mDumpManager, mCommandQueue, mSynchronousExecutor); } @Test @@ -335,6 +338,12 @@ public class NavBarHelperTest extends SysuiTestCase { assertThat(state2.mWindowState).isNotEqualTo(newState); } + @Test + public void configUpdatePropagatesToEdgeBackGestureHandler() { + mConfigurationController.onConfigurationChanged(Configuration.EMPTY); + verify(mEdgeBackGestureHandler, times(1)).onConfigurationChanged(any()); + } + private List<String> createFakeShortcutTargets() { return new ArrayList<>(List.of("a", "b", "c", "d")); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java index d405df7c2cba..354a87a95fda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java @@ -37,11 +37,8 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import android.content.res.Configuration; import android.testing.AndroidTestingRunner; import android.util.SparseArray; @@ -293,23 +290,6 @@ public class NavigationBarControllerImplTest extends SysuiTestCase { } @Test - public void testConfigurationChange_taskbarNotInitialized() { - Configuration configuration = mContext.getResources().getConfiguration(); - mNavigationBarController.mIsLargeScreen = true; - mNavigationBarController.onConfigChanged(configuration); - verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration); - } - - @Test - public void testConfigurationChange_taskbarInitialized() { - Configuration configuration = mContext.getResources().getConfiguration(); - mNavigationBarController.mIsLargeScreen = true; - when(mTaskbarDelegate.isInitialized()).thenReturn(true); - mNavigationBarController.onConfigChanged(configuration); - verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration); - } - - @Test public void testShouldRenderTaskbar_taskbarNotRenderedOnPhone() { mNavigationBarController.mIsLargeScreen = false; mNavigationBarController.mIsPhone = true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index b38d5e326b97..0e7a21517913 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -111,6 +111,7 @@ import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LightBarTransitionsController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.DeviceConfigProxyFake; @@ -275,8 +276,8 @@ public class NavigationBarTest extends SysuiTestCase { mKeyguardStateController, mock(NavigationModeController.class), mEdgeBackGestureHandlerFactory, mock(IWindowManager.class), mock(UserTracker.class), mock(DisplayTracker.class), - mNotificationShadeWindowController, mock(DumpManager.class), - mock(CommandQueue.class), mSynchronousExecutor)); + mNotificationShadeWindowController, mock(ConfigurationController.class), + mock(DumpManager.class), mock(CommandQueue.class), mSynchronousExecutor)); mNavigationBar = createNavBar(mContext); mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal); }); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java index e4a4836bcd46..6956beab418e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java @@ -57,6 +57,7 @@ import androidx.test.filters.SmallTest; import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.flags.FeatureFlagsClassic; import com.android.systemui.media.controls.ui.view.MediaHost; import com.android.systemui.qs.customize.QSCustomizerController; @@ -66,7 +67,6 @@ import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder; import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.res.R; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.settings.FakeDisplayTracker; import com.android.systemui.shade.transition.LargeScreenShadeInterpolator; import com.android.systemui.statusbar.CommandQueue; @@ -115,7 +115,6 @@ public class QSImplTest extends SysuiTestCase { @Mock private FooterActionsViewBinder mFooterActionsViewBinder; @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator; @Mock private FeatureFlagsClassic mFeatureFlags; - @Mock private SceneContainerFlags mSceneContainerFlags; private ViewGroup mQsView; private final CommandQueue mCommandQueue = @@ -127,7 +126,6 @@ public class QSImplTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - when(mSceneContainerFlags.isEnabled()).thenReturn(false); mUnderTest = instantiate(); @@ -496,8 +494,8 @@ public class QSImplTest extends SysuiTestCase { } @Test + @EnableSceneContainer public void testSceneContainerFlagsEnabled_FooterActionsRemoved_controllerNotStarted() { - when(mSceneContainerFlags.isEnabled()).thenReturn(true); clearInvocations( mFooterActionsViewBinder, mFooterActionsViewModel, mFooterActionsViewModelFactory); QSImpl other = instantiate(); @@ -513,9 +511,8 @@ public class QSImplTest extends SysuiTestCase { } @Test + @EnableSceneContainer public void testSceneContainerFlagsEnabled_statusBarStateIsShade() { - when(mSceneContainerFlags.isEnabled()).thenReturn(true); - mUnderTest.onStateChanged(KEYGUARD); assertThat(mUnderTest.getStatusBarState()).isEqualTo(SHADE); @@ -524,9 +521,8 @@ public class QSImplTest extends SysuiTestCase { } @Test + @EnableSceneContainer public void testSceneContainerFlagsEnabled_isKeyguardState_alwaysFalse() { - when(mSceneContainerFlags.isEnabled()).thenReturn(true); - mUnderTest.onStateChanged(KEYGUARD); assertThat(mUnderTest.isKeyguardState()).isFalse(); @@ -559,8 +555,8 @@ public class QSImplTest extends SysuiTestCase { mFooterActionsViewModelFactory, mFooterActionsViewBinder, mLargeScreenShadeInterpolator, - mFeatureFlags, - mSceneContainerFlags); + mFeatureFlags + ); } private void setUpOther() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java index 0101741a9242..542bfaaa8484 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java @@ -16,6 +16,8 @@ package com.android.systemui.qs; +import static com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -33,6 +35,8 @@ import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.content.res.Resources; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.ContextThemeWrapper; @@ -45,13 +49,14 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; +import com.android.systemui.haptics.qs.QSLongPressEffect; +import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.media.controls.ui.view.MediaHost; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.res.R; -import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; import com.android.systemui.util.animation.DisappearParameters; @@ -66,11 +71,14 @@ import java.io.StringWriter; import java.util.Collections; import java.util.List; +import javax.inject.Provider; + @RunWith(AndroidTestingRunner.class) @RunWithLooper @SmallTest public class QSPanelControllerBaseTest extends SysuiTestCase { + private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); @Mock private QSPanel mQSPanel; @Mock @@ -101,8 +109,8 @@ public class QSPanelControllerBaseTest extends SysuiTestCase { Configuration mConfiguration; @Mock Runnable mHorizontalLayoutListener; - @Mock - VibratorHelper mVibratorHelper; + private TestableLongPressEffectProvider mLongPressEffectProvider = + new TestableLongPressEffectProvider(); private QSPanelControllerBase<QSPanel> mController; @@ -114,7 +122,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase { DumpManager dumpManager) { super(view, host, qsCustomizerController, true, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager, new ResourcesSplitShadeStateController(), - mVibratorHelper); + mLongPressEffectProvider); } @Override @@ -123,6 +131,17 @@ public class QSPanelControllerBaseTest extends SysuiTestCase { } } + private class TestableLongPressEffectProvider implements Provider<QSLongPressEffect> { + + private int mEffectsProvided = 0; + + @Override + public QSLongPressEffect get() { + mEffectsProvided++; + return mKosmos.getQsLongPressEffect(); + } + } + @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); @@ -421,6 +440,27 @@ public class QSPanelControllerBaseTest extends SysuiTestCase { } @Test + @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) + public void setTiles_longPressEffectEnabled_nonNullLongPressEffectsAreProvided() { + mLongPressEffectProvider.mEffectsProvided = 0; + when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile)); + mController.setTiles(); + + // There is one non-null effect provided for each tile in the host + assertThat(mLongPressEffectProvider.mEffectsProvided).isEqualTo(2); + } + + @Test + @DisableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) + public void setTiles_longPressEffectDisabled_noLongPressEffectsAreProvided() { + mLongPressEffectProvider.mEffectsProvided = 0; + when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile)); + mController.setTiles(); + + assertThat(mLongPressEffectProvider.mEffectsProvided).isEqualTo(0); + } + + @Test public void setTiles_differentTiles_extraTileRemoved() { when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile)); mController.setTiles(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt index 916e8ddb6e8a..0275643b8489 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt @@ -7,23 +7,23 @@ import android.testing.TestableResources import android.view.ContextThemeWrapper import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.haptics.qs.QSLongPressEffect import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.controls.ui.view.MediaHostState import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.qs.customize.QSCustomizerController import com.android.systemui.qs.logging.QSLogger -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags +import com.android.systemui.res.R import com.android.systemui.settings.brightness.BrightnessController import com.android.systemui.settings.brightness.BrightnessSliderController -import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController import com.android.systemui.tuner.TunerService import com.google.common.truth.Truth.assertThat +import javax.inject.Provider import org.junit.After import org.junit.Before import org.junit.Test @@ -62,9 +62,7 @@ class QSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager @Mock private lateinit var configuration: Configuration @Mock private lateinit var pagedTileLayout: PagedTileLayout - @Mock private lateinit var vibratorHelper: VibratorHelper - - private val sceneContainerFlags = FakeSceneContainerFlags() + @Mock private lateinit var longPressEffectProvider: Provider<QSLongPressEffect> private lateinit var controller: QSPanelController private val testableResources: TestableResources = mContext.orCreateTestableResources @@ -102,8 +100,7 @@ class QSPanelControllerTest : SysuiTestCase() { falsingManager, statusBarKeyguardViewManager, ResourcesSplitShadeStateController(), - sceneContainerFlags, - vibratorHelper, + longPressEffectProvider, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt index 71a9a8b3318f..1eb0a51bcaf6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt @@ -22,15 +22,15 @@ import android.view.ContextThemeWrapper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger import com.android.internal.logging.testing.UiEventLoggerFake -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.haptics.qs.QSLongPressEffect import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.controls.ui.view.MediaHostState import com.android.systemui.plugins.qs.QSTile import com.android.systemui.qs.customize.QSCustomizerController import com.android.systemui.qs.logging.QSLogger -import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController import com.android.systemui.util.leak.RotationUtils import org.junit.After @@ -45,6 +45,7 @@ import org.mockito.Mockito.reset import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import javax.inject.Provider import org.mockito.Mockito.`when` as whenever @SmallTest @@ -60,7 +61,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var tile: QSTile @Mock private lateinit var tileLayout: TileLayout @Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener> - @Mock private lateinit var vibratorHelper: VibratorHelper + @Mock private lateinit var longPressEffectProvider: Provider<QSLongPressEffect> private val uiEventLogger = UiEventLoggerFake() private val dumpManager = DumpManager() @@ -92,7 +93,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() { uiEventLogger, qsLogger, dumpManager, - vibratorHelper, + longPressEffectProvider, ) controller.init() @@ -161,7 +162,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() { uiEventLogger: UiEventLoggerFake, qsLogger: QSLogger, dumpManager: DumpManager, - vibratorHelper: VibratorHelper, + longPressEffectProvider: Provider<QSLongPressEffect>, ) : QuickQSPanelController( view, @@ -175,7 +176,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() { qsLogger, dumpManager, ResourcesSplitShadeStateController(), - vibratorHelper, + longPressEffectProvider, ) { private var rotation = RotationUtils.ROTATION_NONE diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index 8acde3637576..4915e555dcc5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -20,15 +20,14 @@ import android.content.Context import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -43,8 +42,6 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var context: Context - private val sceneContainerFlags = FakeSceneContainerFlags() - private lateinit var controller: QuickStatusBarHeaderController @Before @@ -55,9 +52,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { `when`(view.context).thenReturn(context) controller = QuickStatusBarHeaderController( - view, - quickQSPanelController, - sceneContainerFlags, + view, + quickQSPanelController, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt index 2b1ac915f430..512ca5315530 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt @@ -18,7 +18,6 @@ package com.android.systemui.qs.tileimpl import android.content.Context import android.graphics.drawable.Drawable -import android.platform.test.annotations.EnableFlags import android.service.quicksettings.Tile import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -28,10 +27,12 @@ import android.view.View import android.view.accessibility.AccessibilityNodeInfo import android.widget.TextView import androidx.test.filters.SmallTest -import com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS import com.android.systemui.res.R import com.android.systemui.SysuiTestCase +import com.android.systemui.haptics.qs.QSLongPressEffect +import com.android.systemui.haptics.qs.qsLongPressEffect import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -50,13 +51,14 @@ class QSTileViewImplTest : SysuiTestCase() { private lateinit var tileView: FakeTileView private lateinit var customDrawableView: View private lateinit var chevronView: View + private val kosmos = testKosmos() @Before fun setUp() { MockitoAnnotations.initMocks(this) context.ensureTestableResources() - tileView = FakeTileView(context, false) + tileView = FakeTileView(context, false, kosmos.qsLongPressEffect) customDrawableView = tileView.requireViewById(R.id.customDrawable) chevronView = tileView.requireViewById(R.id.chevron) } @@ -383,7 +385,6 @@ class QSTileViewImplTest : SysuiTestCase() { } @Test - @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) fun onStateChange_longPressEffectActive_withInvalidDuration_doesNotCreateEffect() { val state = QSTile.State() // A state that handles longPress @@ -393,12 +394,11 @@ class QSTileViewImplTest : SysuiTestCase() { // WHEN the state changes tileView.changeState(state) - // THEN the long-press effect is not created - assertThat(tileView.hasLongPressEffect).isFalse() + // THEN the long-press effect is not initialized + assertThat(tileView.isLongPressEffectInitialized).isFalse() } @Test - @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) fun onStateChange_longPressEffectActive_withValidDuration_createsEffect() { // GIVEN a test state that handles long-press and a valid long-press effect duration val state = QSTile.State() @@ -406,12 +406,11 @@ class QSTileViewImplTest : SysuiTestCase() { // WHEN the state changes tileView.changeState(state) - // THEN the long-press effect created - assertThat(tileView.hasLongPressEffect).isTrue() + // THEN the long-press effect is initialized + assertThat(tileView.isLongPressEffectInitialized).isTrue() } @Test - @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) fun onStateChange_fromLongPress_to_noLongPress_unBoundsTile() { // GIVEN a state that no longer handles long-press val state = QSTile.State() @@ -421,11 +420,10 @@ class QSTileViewImplTest : SysuiTestCase() { tileView.changeState(state) // THEN the view binder no longer binds the view to the long-press effect - assertThat(tileView.isLongPressEffectBound).isFalse() + assertThat(tileView.longPressEffectHandle).isNull() } @Test - @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) fun onStateChange_fromNoLongPress_to_longPress_bindsTile() { // GIVEN that the tile has changed to a state that does not handle long-press val state = QSTile.State() @@ -437,15 +435,53 @@ class QSTileViewImplTest : SysuiTestCase() { tileView.changeState(state) // THEN the view is bounded to the long-press effect - assertThat(tileView.isLongPressEffectBound).isTrue() + assertThat(tileView.longPressEffectHandle).isNotNull() + } + + @Test + fun onStateChange_withoutLongPressEffect_fromLongPress_to_noLongPress_neverBindsEffect() { + // GIVEN a tile where the long-press effect is null + tileView = FakeTileView(context, false, null) + + // GIVEN a state that no longer handles long-press + val state = QSTile.State() + state.handlesLongClick = false + + // WHEN the state changes + tileView.changeState(state) + + // THEN the view binder does not bind the view and no effect is initialized + assertThat(tileView.longPressEffectHandle).isNull() + assertThat(tileView.isLongPressEffectInitialized).isFalse() + } + + @Test + fun onStateChange_withoutLongPressEffect_fromNoLongPress_to_longPress_neverBindsEffect() { + // GIVEN a tile where the long-press effect is null + tileView = FakeTileView(context, false, null) + + // GIVEN that the tile has changed to a state that does not handle long-press + val state = QSTile.State() + state.handlesLongClick = false + tileView.changeState(state) + + // WHEN the state changes back to handling long-press + state.handlesLongClick = true + tileView.changeState(state) + + // THEN the view binder does not bind the view and no effect is initialized + assertThat(tileView.longPressEffectHandle).isNull() + assertThat(tileView.isLongPressEffectInitialized).isFalse() } class FakeTileView( context: Context, - collapsed: Boolean + collapsed: Boolean, + longPressEffect: QSLongPressEffect?, ) : QSTileViewImpl( ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings), - collapsed + collapsed, + longPressEffect, ) { var constantLongPressEffectDuration = 500 diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt index 1313227c7f3d..387f27d048ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt @@ -42,7 +42,6 @@ import com.android.systemui.model.sceneContainerPlugin import com.android.systemui.navigationbar.NavigationBarController import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.settings.UserTracker import com.android.systemui.shade.ShadeViewController @@ -249,7 +248,6 @@ class OverviewProxyServiceTest : SysuiTestCase() { sysuiUnlockAnimationController, inWindowLauncherUnlockAnimationManager, assistUtils, - FakeSceneContainerFlags(), dumpManager, unfoldTransitionProgressForwarder, broadcastDispatcher diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt index 5e7d8fb5df02..91f39126c67c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat +import kotlin.test.Ignore import kotlin.test.Test import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestCoroutineScheduler @@ -55,6 +56,7 @@ class ActionExecutorTest : SysuiTestCase() { private lateinit var actionExecutor: ActionExecutor + @Ignore // Fixed with newer mockito version (in main) @Test fun startSharedTransition_callsLaunchIntent() = runTest { actionExecutor = createActionExecutor() diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt index bde821b79469..853e50a12ea5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt @@ -16,8 +16,6 @@ package com.android.systemui.screenshot -import android.app.Notification -import android.app.PendingIntent import android.content.Intent import android.net.Uri import android.os.Process @@ -27,8 +25,6 @@ import android.view.accessibility.AccessibilityManager import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase -import com.android.systemui.clipboardoverlay.EditTextActivity -import com.android.systemui.res.R import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture @@ -41,10 +37,7 @@ import org.junit.Assert.assertNotNull import org.junit.Before import org.junit.runner.RunWith import org.mockito.Mockito.verifyNoMoreInteractions -import org.mockito.kotlin.any -import org.mockito.kotlin.never import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever @RunWith(AndroidTestingRunner::class) @SmallTest @@ -52,7 +45,6 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() { private val actionExecutor = mock<ActionExecutor>() private val accessibilityManager = mock<AccessibilityManager>() private val uiEventLogger = mock<UiEventLogger>() - private val smartActionsProvider = mock<SmartActionsProvider>() private val request = ScreenshotData.forTesting() private val validResult = ScreenshotSavedResult(Uri.EMPTY, Process.myUserHandle(), 0) @@ -119,42 +111,10 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() { assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_CHOOSER) } - @Test - fun quickShareTapped_wrapsAndSendsIntent() = runTest { - val quickShare = - Notification.Action( - R.drawable.ic_screenshot_edit, - "TestQuickShare", - PendingIntent.getActivity( - context, - 0, - Intent(context, EditTextActivity::class.java), - PendingIntent.FLAG_MUTABLE - ) - ) - whenever(smartActionsProvider.requestQuickShare(any(), any(), any())).then { - (it.getArgument(2) as ((Notification.Action) -> Unit)).invoke(quickShare) - } - whenever(smartActionsProvider.wrapIntent(any(), any(), any(), any())).thenAnswer { - (it.getArgument(0) as Notification.Action).actionIntent - } - actionsProvider = createActionsProvider() - - viewModel.actions.value[2].onClicked?.invoke() - verify(uiEventLogger, never()) - .log(eq(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED), any(), any()) - verify(smartActionsProvider, never()).wrapIntent(any(), any(), any(), any()) - actionsProvider.setCompletedScreenshot(validResult) - verify(smartActionsProvider) - .wrapIntent(eq(quickShare), eq(validResult.uri), eq(validResult.subject), eq("testid")) - verify(uiEventLogger).log(eq(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED), eq(0), eq("")) - } - private fun createActionsProvider(): ScreenshotActionsProvider { return DefaultScreenshotActionsProvider( context, viewModel, - smartActionsProvider, uiEventLogger, request, "testid", diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt index 587da2d5d677..b051df21389e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt @@ -18,11 +18,6 @@ package com.android.systemui.screenshot import android.app.ActivityTaskManager.RootTaskInfo import android.app.IActivityTaskManager -import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME -import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD -import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED -import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN -import android.app.WindowConfiguration.WINDOWING_MODE_PINNED import android.content.ComponentName import android.content.Context import android.graphics.Rect @@ -31,6 +26,12 @@ import android.os.UserManager import android.testing.AndroidTestingRunner import com.android.systemui.SysuiTestCase import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo +import com.android.systemui.screenshot.policy.ActivityType.Home +import com.android.systemui.screenshot.policy.ActivityType.Undefined +import com.android.systemui.screenshot.policy.WindowingMode.FullScreen +import com.android.systemui.screenshot.policy.WindowingMode.PictureInPicture +import com.android.systemui.screenshot.policy.newChildTask +import com.android.systemui.screenshot.policy.newRootTaskInfo import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat @@ -58,20 +59,19 @@ class ScreenshotPolicyImplTest : SysuiTestCase() { ), Rect(0, 0, 1080, 2400), UserHandle.of(MANAGED_PROFILE_USER), - 65)) + 65 + ) + ) } @Test fun findPrimaryContent_ignoresPipTask() = runBlocking { - val policy = fakeTasksPolicyImpl( - mContext, - shadeExpanded = false, - tasks = listOf( - pipTask, - fullScreenWorkProfileTask, - launcherTask, - emptyTask) - ) + val policy = + fakeTasksPolicyImpl( + mContext, + shadeExpanded = false, + tasks = listOf(pipTask, fullScreenWorkProfileTask, launcherTask, emptyTask) + ) val info = policy.findPrimaryContent(DISPLAY_ID) assertThat(info).isEqualTo(fullScreenWorkProfileTask.toDisplayContentInfo()) @@ -79,14 +79,12 @@ class ScreenshotPolicyImplTest : SysuiTestCase() { @Test fun findPrimaryContent_shadeExpanded_ignoresTopTask() = runBlocking { - val policy = fakeTasksPolicyImpl( - mContext, - shadeExpanded = true, - tasks = listOf( - fullScreenWorkProfileTask, - launcherTask, - emptyTask) - ) + val policy = + fakeTasksPolicyImpl( + mContext, + shadeExpanded = true, + tasks = listOf(fullScreenWorkProfileTask, launcherTask, emptyTask) + ) val info = policy.findPrimaryContent(DISPLAY_ID) assertThat(info).isEqualTo(policy.systemUiContent) @@ -94,11 +92,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() { @Test fun findPrimaryContent_emptyTaskList() = runBlocking { - val policy = fakeTasksPolicyImpl( - mContext, - shadeExpanded = false, - tasks = listOf() - ) + val policy = fakeTasksPolicyImpl(mContext, shadeExpanded = false, tasks = listOf()) val info = policy.findPrimaryContent(DISPLAY_ID) assertThat(info).isEqualTo(policy.systemUiContent) @@ -106,14 +100,12 @@ class ScreenshotPolicyImplTest : SysuiTestCase() { @Test fun findPrimaryContent_workProfileNotOnTop() = runBlocking { - val policy = fakeTasksPolicyImpl( - mContext, - shadeExpanded = false, - tasks = listOf( - launcherTask, - fullScreenWorkProfileTask, - emptyTask) - ) + val policy = + fakeTasksPolicyImpl( + mContext, + shadeExpanded = false, + tasks = listOf(launcherTask, fullScreenWorkProfileTask, emptyTask) + ) val info = policy.findPrimaryContent(DISPLAY_ID) assertThat(info).isEqualTo(launcherTask.toDisplayContentInfo()) @@ -129,102 +121,80 @@ class ScreenshotPolicyImplTest : SysuiTestCase() { val dispatcher = Dispatchers.Unconfined val displayTracker = FakeDisplayTracker(context) - return object : ScreenshotPolicyImpl(context, userManager, atmService, dispatcher, - displayTracker) { + return object : + ScreenshotPolicyImpl(context, userManager, atmService, dispatcher, displayTracker) { override suspend fun isManagedProfile(userId: Int) = (userId == MANAGED_PROFILE_USER) override suspend fun getAllRootTaskInfosOnDisplay(displayId: Int) = tasks override suspend fun isNotificationShadeExpanded() = shadeExpanded } } - private val pipTask = RootTaskInfo().apply { - configuration.windowConfiguration.apply { - windowingMode = WINDOWING_MODE_PINNED - setBounds(Rect(628, 1885, 1038, 2295)) - activityType = ACTIVITY_TYPE_STANDARD + private val pipTask = + newRootTaskInfo( + taskId = 66, + userId = PRIMARY_USER, + displayId = DISPLAY_ID, + bounds = Rect(628, 1885, 1038, 2295), + windowingMode = PictureInPicture, + topActivity = ComponentName.unflattenFromString(YOUTUBE_PIP_ACTIVITY), + ) { + listOf(newChildTask(taskId = 66, userId = 0, name = YOUTUBE_HOME_ACTIVITY)) } - displayId = DISPLAY_ID - userId = PRIMARY_USER - taskId = 66 - visible = true - isVisible = true - isRunning = true - numActivities = 1 - topActivity = ComponentName( - "com.google.android.youtube", - "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity" - ) - childTaskIds = intArrayOf(66) - childTaskNames = arrayOf("com.google.android.youtube/" + - "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity") - childTaskUserIds = intArrayOf(0) - childTaskBounds = arrayOf(Rect(628, 1885, 1038, 2295)) - } - private val fullScreenWorkProfileTask = RootTaskInfo().apply { - configuration.windowConfiguration.apply { - windowingMode = WINDOWING_MODE_FULLSCREEN - setBounds(Rect(0, 0, 1080, 2400)) - activityType = ACTIVITY_TYPE_STANDARD + private val fullScreenWorkProfileTask = + newRootTaskInfo( + taskId = 65, + userId = MANAGED_PROFILE_USER, + displayId = DISPLAY_ID, + bounds = Rect(0, 0, 1080, 2400), + windowingMode = FullScreen, + topActivity = ComponentName.unflattenFromString(FILES_HOME_ACTIVITY), + ) { + listOf( + newChildTask(taskId = 65, userId = MANAGED_PROFILE_USER, name = FILES_HOME_ACTIVITY) + ) } - displayId = DISPLAY_ID - userId = MANAGED_PROFILE_USER - taskId = 65 - visible = true - isVisible = true - isRunning = true - numActivities = 1 - topActivity = ComponentName( - "com.google.android.apps.nbu.files", - "com.google.android.apps.nbu.files.home.HomeActivity" - ) - childTaskIds = intArrayOf(65) - childTaskNames = arrayOf("com.google.android.apps.nbu.files/" + - "com.google.android.apps.nbu.files.home.HomeActivity") - childTaskUserIds = intArrayOf(MANAGED_PROFILE_USER) - childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400)) - } - - private val launcherTask = RootTaskInfo().apply { - configuration.windowConfiguration.apply { - windowingMode = WINDOWING_MODE_FULLSCREEN - setBounds(Rect(0, 0, 1080, 2400)) - activityType = ACTIVITY_TYPE_HOME + private val launcherTask = + newRootTaskInfo( + taskId = 1, + userId = PRIMARY_USER, + displayId = DISPLAY_ID, + activityType = Home, + windowingMode = FullScreen, + bounds = Rect(0, 0, 1080, 2400), + topActivity = ComponentName.unflattenFromString(LAUNCHER_ACTIVITY), + ) { + listOf(newChildTask(taskId = 1, userId = 0, name = LAUNCHER_ACTIVITY)) } - displayId = DISPLAY_ID - taskId = 1 - userId = PRIMARY_USER - visible = true - isVisible = true - isRunning = true - numActivities = 1 - topActivity = ComponentName( - "com.google.android.apps.nexuslauncher", - "com.google.android.apps.nexuslauncher.NexusLauncherActivity", - ) - childTaskIds = intArrayOf(1) - childTaskNames = arrayOf("com.google.android.apps.nexuslauncher/" + - "com.google.android.apps.nexuslauncher.NexusLauncherActivity") - childTaskUserIds = intArrayOf(0) - childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400)) - } - private val emptyTask = RootTaskInfo().apply { - configuration.windowConfiguration.apply { - windowingMode = WINDOWING_MODE_FULLSCREEN - setBounds(Rect(0, 0, 1080, 2400)) - activityType = ACTIVITY_TYPE_UNDEFINED + private val emptyTask = + newRootTaskInfo( + taskId = 2, + userId = PRIMARY_USER, + displayId = DISPLAY_ID, + visible = false, + running = false, + numActivities = 0, + activityType = Undefined, + bounds = Rect(0, 0, 1080, 2400), + ) { + listOf( + newChildTask(taskId = 3, name = ""), + newChildTask(taskId = 4, name = ""), + ) } - displayId = DISPLAY_ID - taskId = 2 - userId = PRIMARY_USER - visible = false - isVisible = false - isRunning = false - numActivities = 0 - childTaskIds = intArrayOf(3, 4) - childTaskNames = arrayOf("", "") - childTaskUserIds = intArrayOf(0, 0) - childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400), Rect(0, 2400, 1080, 4800)) - } } + +const val YOUTUBE_HOME_ACTIVITY = + "com.google.android.youtube/" + "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity" + +const val FILES_HOME_ACTIVITY = + "com.google.android.apps.nbu.files/" + "com.google.android.apps.nbu.files.home.HomeActivity" + +const val YOUTUBE_PIP_ACTIVITY = + "com.google.android.youtube/" + + "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity" + +const val LAUNCHER_ACTIVITY = + "com.google.android.apps.nexuslauncher/" + + "com.google.android.apps.nexuslauncher.NexusLauncherActivity" diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt new file mode 100644 index 000000000000..6c35b233ffec --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.screenshot.policy + +import android.app.ActivityTaskManager.RootTaskInfo +import android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT +import android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM +import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME +import android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS +import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD +import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED +import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM +import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN +import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW +import android.app.WindowConfiguration.WINDOWING_MODE_PINNED +import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED +import android.content.ComponentName +import android.graphics.Rect +import android.os.UserHandle +import android.view.Display +import com.android.systemui.screenshot.data.model.ChildTaskModel +import com.android.systemui.screenshot.policy.ActivityType.Standard +import com.android.systemui.screenshot.policy.WindowingMode.FullScreen + +/** An enum mapping to [android.app.WindowConfiguration] constants via [toInt]. */ +enum class ActivityType(private val intValue: Int) { + Undefined(ACTIVITY_TYPE_UNDEFINED), + Standard(ACTIVITY_TYPE_STANDARD), + Home(ACTIVITY_TYPE_HOME), + Recents(ACTIVITY_TYPE_RECENTS), + Assistant(ACTIVITY_TYPE_ASSISTANT), + Dream(ACTIVITY_TYPE_DREAM); + + /** Returns the [android.app.WindowConfiguration] int constant for the type. */ + fun toInt() = intValue +} + +/** An enum mapping to [android.app.WindowConfiguration] constants via [toInt]. */ +enum class WindowingMode(private val intValue: Int) { + Undefined(WINDOWING_MODE_UNDEFINED), + FullScreen(WINDOWING_MODE_FULLSCREEN), + PictureInPicture(WINDOWING_MODE_PINNED), + Freeform(WINDOWING_MODE_FREEFORM), + MultiWindow(WINDOWING_MODE_MULTI_WINDOW); + + /** Returns the [android.app.WindowConfiguration] int constant for the mode. */ + fun toInt() = intValue +} + +/** + * Constructs a child task for a [RootTaskInfo], copying [RootTaskInfo.bounds] and + * [RootTaskInfo.userId] from the parent by default. + */ +fun RootTaskInfo.newChildTask( + taskId: Int, + name: String, + bounds: Rect? = null, + userId: Int? = null +): ChildTaskModel { + return ChildTaskModel(taskId, name, bounds ?: this.bounds, userId ?: this.userId) +} + +/** Constructs a new [RootTaskInfo]. */ +fun newRootTaskInfo( + taskId: Int, + userId: Int = UserHandle.USER_SYSTEM, + displayId: Int = Display.DEFAULT_DISPLAY, + visible: Boolean = true, + running: Boolean = true, + activityType: ActivityType = Standard, + windowingMode: WindowingMode = FullScreen, + bounds: Rect? = null, + topActivity: ComponentName? = null, + topActivityType: ActivityType = Standard, + numActivities: Int? = null, + childTaskListBuilder: RootTaskInfo.() -> List<ChildTaskModel>, +): RootTaskInfo { + return RootTaskInfo().apply { + configuration.windowConfiguration.apply { + setWindowingMode(windowingMode.toInt()) + setActivityType(activityType.toInt()) + setBounds(bounds) + } + this.bounds = bounds + this.displayId = displayId + this.userId = userId + this.taskId = taskId + this.visible = visible + this.isVisible = visible + this.isRunning = running + this.topActivity = topActivity + this.topActivityType = topActivityType.toInt() + // NOTE: topActivityInfo is _not_ populated by this code + + val childTasks = childTaskListBuilder(this) + this.numActivities = numActivities ?: childTasks.size + + childTaskNames = childTasks.map { it.name }.toTypedArray() + childTaskIds = childTasks.map { it.id }.toIntArray() + childTaskBounds = childTasks.map { it.bounds }.toTypedArray() + childTaskUserIds = childTasks.map { it.userId }.toIntArray() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java index dfe72cf11dcb..0a8e470f8a7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java @@ -398,7 +398,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { mFakeKeyguardRepository = keyguardInteractorDeps.getRepository(); mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(mFakeKeyguardRepository); mFakeKeyguardClockRepository = new FakeKeyguardClockRepository(); - mKeyguardClockInteractor = new KeyguardClockInteractor(mFakeKeyguardClockRepository); + mKeyguardClockInteractor = mKosmos.getKeyguardClockInteractor(); mKeyguardInteractor = keyguardInteractorDeps.getKeyguardInteractor(); mShadeRepository = new FakeShadeRepository(); mShadeAnimationInteractor = new ShadeAnimationInteractorLegacyImpl( @@ -410,6 +410,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { mock(DeviceEntryUdfpsInteractor.class); when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false)); + when(mKeyguardTransitionInteractor.isInTransitionToState(any())).thenReturn(emptyFlow()); + mShadeInteractor = new ShadeInteractorImpl( mTestScope.getBackgroundScope(), mKosmos.getDeviceProvisioningInteractor(), @@ -539,7 +541,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class)); // Dreaming->Lockscreen - when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition()) + when(mKeyguardTransitionInteractor.transition(any(), any())) .thenReturn(emptyFlow()); when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); @@ -547,46 +549,28 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { .thenReturn(emptyFlow()); // Occluded->Lockscreen - when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition()) - .thenReturn(emptyFlow()); when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); when(mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY()) .thenReturn(emptyFlow()); // Lockscreen->Dreaming - when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition()) - .thenReturn(emptyFlow()); when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt())) .thenReturn(emptyFlow()); // Gone->Dreaming - when(mKeyguardTransitionInteractor.getGoneToDreamingTransition()) - .thenReturn(emptyFlow()); when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt())) .thenReturn(emptyFlow()); // Gone->Dreaming lockscreen hosted - when(mKeyguardTransitionInteractor.getGoneToDreamingLockscreenHostedTransition()) - .thenReturn(emptyFlow()); when(mGoneToDreamingLockscreenHostedTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); - // Dreaming lockscreen hosted->Lockscreen - when(mKeyguardTransitionInteractor.getDreamingLockscreenHostedToLockscreenTransition()) - .thenReturn(emptyFlow()); - - // Lockscreen->Dreaming lockscreen hosted - when(mKeyguardTransitionInteractor.getLockscreenToDreamingLockscreenHostedTransition()) - .thenReturn(emptyFlow()); - // Lockscreen->Occluded - when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition()) - .thenReturn(emptyFlow()); when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); when(mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index cf7c6f4e2174..b89ccefddf6b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -75,8 +75,6 @@ import com.android.systemui.res.R; import com.android.systemui.scene.FakeWindowRootViewComponent; import com.android.systemui.scene.data.repository.SceneContainerRepository; import com.android.systemui.scene.domain.interactor.SceneInteractor; -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.scene.shared.logger.SceneLogger; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.data.repository.FakeShadeRepository; @@ -136,7 +134,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { @Mock private ShadeWindowLogger mShadeWindowLogger; @Mock private SelectedUserInteractor mSelectedUserInteractor; @Mock private UserTracker mUserTracker; - @Mock private SceneContainerFlags mSceneContainerFlags; @Mock private LargeScreenHeaderHelper mLargeScreenHeaderHelper; @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters; @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener; @@ -185,14 +182,12 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mKosmos.getDeviceUnlockedInteractor()); FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository(); - FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags(); KeyguardTransitionInteractor keyguardTransitionInteractor = mKosmos.getKeyguardTransitionInteractor(); KeyguardInteractor keyguardInteractor = new KeyguardInteractor( keyguardRepository, new FakeCommandQueue(), powerInteractor, - sceneContainerFlags, new FakeKeyguardBouncerRepository(), new ConfigurationInteractor(configurationRepository), shadeRepository, @@ -256,7 +251,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, - mSceneContainerFlags, () -> communalInteractor) { @Override protected boolean isDebuggable() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index 2c0a15dd4e5a..b04503b8e031 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -43,6 +43,8 @@ import com.android.systemui.flags.Flags.TRACKPAD_GESTURE_FEATURES import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler import com.android.systemui.keyguard.KeyguardUnlockAnimationController import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING +import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.res.R import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler @@ -160,7 +162,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { .thenReturn(keyguardBouncerComponent) whenever(keyguardBouncerComponent.securityContainerController) .thenReturn(keyguardSecurityContainerController) - whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition) + whenever(keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING)) .thenReturn(emptyFlow<TransitionStep>()) featureFlagsClassic = FakeFeatureFlagsClassic() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt index 98a815cabe83..ba8eb6f4ba36 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt @@ -36,6 +36,8 @@ import com.android.systemui.flags.Flags import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler import com.android.systemui.keyguard.KeyguardUnlockAnimationController import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING +import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.res.R import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor @@ -149,7 +151,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { whenever(statusBarStateController.isDozing).thenReturn(false) mDependency.injectTestDependency(ShadeController::class.java, shadeController) whenever(dockManager.isDocked).thenReturn(false) - whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition) + whenever(keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING)) .thenReturn(emptyFlow()) val featureFlags = FakeFeatureFlags() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java index 20d877e3e2c5..77ad17a9e918 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java @@ -62,7 +62,6 @@ import com.android.systemui.qs.QSFragmentLegacy; import com.android.systemui.res.R; import com.android.systemui.scene.data.repository.SceneContainerRepository; import com.android.systemui.scene.domain.interactor.SceneInteractor; -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; import com.android.systemui.scene.shared.logger.SceneLogger; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shade.data.repository.FakeShadeRepository; @@ -208,14 +207,12 @@ public class QuickSettingsControllerImplBaseTest extends SysuiTestCase { mock(SceneLogger.class), mKosmos.getDeviceUnlockedInteractor()); - FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags(); KeyguardTransitionInteractor keyguardTransitionInteractor = mKosmos.getKeyguardTransitionInteractor(); KeyguardInteractor keyguardInteractor = new KeyguardInteractor( mKeyguardRepository, new FakeCommandQueue(), powerInteractor, - sceneContainerFlags, new FakeKeyguardBouncerRepository(), new ConfigurationInteractor(configurationRepository), mShadeRepository, diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt index 433c95ab5791..6bdd3ef5cebe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt @@ -33,7 +33,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository @@ -95,7 +94,6 @@ class ShadeControllerImplTest : SysuiTestCase() { headsUpManager, PowerInteractorFactory.create().powerInteractor, ActiveNotificationsInteractor(activeNotificationsRepository, testDispatcher), - kosmos.sceneContainerFlags, kosmos::sceneInteractor, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt index f2abb909e004..7c33648e08a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt @@ -1,15 +1,14 @@ package com.android.systemui.shade.transition -import android.platform.test.annotations.DisableFlags import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest -import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.dump.DumpManager +import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.SceneInteractor @@ -70,7 +69,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { } @Test - @DisableFlags(Flags.FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun onPanelExpansionChanged_setsFractionEqualToEventFraction() { underTest.onPanelExpansionChanged(DEFAULT_EXPANSION_EVENT) @@ -78,7 +77,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { } @Test - @DisableFlags(Flags.FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun onPanelStateChanged_forwardsToScrimTransitionController() { startLegacyPanelExpansion() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt index 56fc0c74dafa..a05a23bb8bb1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt @@ -21,7 +21,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.ViewIdToTranslate -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test @@ -34,21 +34,19 @@ import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() { - private val progressProvider = TestUnfoldTransitionProvider() + private val progressProvider = FakeUnfoldTransitionProvider() - @Mock - private lateinit var parent: ViewGroup + @Mock private lateinit var parent: ViewGroup - @Mock - private lateinit var shouldBeAnimated: () -> Boolean + @Mock private lateinit var shouldBeAnimated: () -> Boolean private lateinit var animator: UnfoldConstantTranslateAnimator private val viewsIdToRegister get() = setOf( - ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated), - ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated) + ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated), + ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated) ) @Before @@ -122,11 +120,12 @@ class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() { progressProvider.onTransitionStarted() progressProvider.onTransitionProgress(0f) - val rtlMultiplier = if (layoutDirection == View.LAYOUT_DIRECTION_LTR) { - 1 - } else { - -1 - } + val rtlMultiplier = + if (layoutDirection == View.LAYOUT_DIRECTION_LTR) { + 1 + } else { + -1 + } list.forEach { (view, direction) -> assertEquals( (-MAX_TRANSLATION * direction * rtlMultiplier).toInt(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt index de6108632153..be5af885c895 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt @@ -19,12 +19,10 @@ package com.android.systemui.statusbar import android.animation.ObjectAnimator -import android.platform.test.annotations.DisableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake -import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel @@ -35,6 +33,7 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor +import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.jank.interactionJankMonitor @@ -56,7 +55,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.power.data.repository.FakePowerRepository import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.LargeScreenHeaderHelper import com.android.systemui.shade.data.repository.FakeShadeRepository @@ -88,8 +86,8 @@ import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito import org.mockito.Mockito.mock import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations +import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidTestingRunner::class) @@ -136,7 +134,6 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { val keyguardTransitionRepository = FakeKeyguardTransitionRepository() val featureFlags = FakeFeatureFlagsClassic() val shadeRepository = FakeShadeRepository() - val sceneContainerFlags = FakeSceneContainerFlags() val configurationRepository = FakeConfigurationRepository() val keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor fromLockscreenTransitionInteractor = kosmos.fromLockscreenTransitionInteractor @@ -147,7 +144,6 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { keyguardRepository, FakeCommandQueue(), powerInteractor, - sceneContainerFlags, FakeKeyguardBouncerRepository(), ConfigurationInteractor(configurationRepository), shadeRepository, @@ -187,7 +183,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun testChangeState_logged() { TestableLooper.get(this).runWithLooper { underTest.state = StatusBarState.KEYGUARD @@ -214,7 +210,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun testSetState_appliesState_sameStateButDifferentUpcomingState() { underTest.state = StatusBarState.SHADE underTest.setUpcomingState(StatusBarState.KEYGUARD) @@ -227,7 +223,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun testSetState_appliesState_differentStateEqualToUpcomingState() { underTest.state = StatusBarState.SHADE underTest.setUpcomingState(StatusBarState.KEYGUARD) @@ -239,7 +235,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) + @DisableSceneContainer fun testSetState_doesNotApplyState_currentAndUpcomingStatesSame() { underTest.state = StatusBarState.SHADE underTest.setUpcomingState(StatusBarState.SHADE) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt index 4eb7daa1eac7..894e02e80997 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt @@ -188,6 +188,9 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() = testComponent.runTest { + val animationsEnabled by collectLastValue(underTest.areContainerChangesAnimated) + assertThat(animationsEnabled).isTrue() + powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -201,8 +204,6 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { ) ) whenever(dozeParams.shouldControlScreenOff()).thenReturn(true) - val animationsEnabled by collectLastValue(underTest.areContainerChangesAnimated) - runCurrent() assertThat(animationsEnabled).isTrue() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt index 35b84939b05d..78b76151e7e6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt @@ -195,6 +195,9 @@ class NotificationIconContainerStatusBarViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() = testComponent.runTest { + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + assertThat(animationsEnabled).isTrue() + powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -208,7 +211,7 @@ class NotificationIconContainerStatusBarViewModelTest : SysuiTestCase() { ) ) whenever(dozeParams.shouldControlScreenOff()).thenReturn(true) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() assertThat(animationsEnabled).isTrue() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt index 54108642385f..edab9d9f7fdf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt @@ -50,7 +50,8 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro systemClock, uiEventLogger, userTracker, - avalancheProvider + avalancheProvider, + systemSettings ) } @@ -82,7 +83,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowConversationFromAfterEvent() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_HIGH @@ -97,7 +98,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_suppressConversationFromBeforeEvent() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldNotHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_DEFAULT @@ -112,7 +113,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowHighPriorityConversation() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_HIGH @@ -125,7 +126,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowCall() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_HIGH @@ -138,7 +139,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowCategoryReminder() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_HIGH @@ -151,7 +152,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowCategoryEvent() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_HIGH @@ -164,7 +165,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowFsi() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { assertFsiNotSuppressed() } } @@ -173,7 +174,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro fun testAvalancheFilter_duringAvalanche_allowColorized() { avalancheProvider.startTime = whenAgo(10) - withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) { + withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) { ensurePeekState() assertShouldHeadsUp(buildEntry { importance = NotificationManager.IMPORTANCE_HIGH diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt index 24f670831193..3b979a7c1386 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt @@ -77,6 +77,8 @@ import com.android.systemui.util.FakeEventLog import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.settings.FakeGlobalSettings +import com.android.systemui.util.settings.FakeSettings +import com.android.systemui.util.settings.SystemSettings import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.utils.leaks.FakeBatteryController import com.android.systemui.utils.leaks.FakeKeyguardStateController @@ -126,6 +128,7 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { protected val uiEventLogger = UiEventLoggerFake() protected val userTracker = FakeUserTracker() protected val avalancheProvider: AvalancheProvider = mock() + lateinit var systemSettings: SystemSettings protected abstract val provider: VisualInterruptionDecisionProvider @@ -153,6 +156,7 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { deviceProvisionedController.currentUser = userId userTracker.set(listOf(user), /* currentUserIndex = */ 0) + systemSettings = FakeSettings() provider.start() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt index 620ad9c19bfa..60aaa646fced 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt @@ -30,6 +30,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.EventLog import com.android.systemui.util.settings.GlobalSettings +import com.android.systemui.util.settings.SystemSettings import com.android.systemui.util.time.SystemClock object VisualInterruptionDecisionProviderTestUtil { @@ -51,7 +52,8 @@ object VisualInterruptionDecisionProviderTestUtil { systemClock: SystemClock, uiEventLogger: UiEventLogger, userTracker: UserTracker, - avalancheProvider: AvalancheProvider + avalancheProvider: AvalancheProvider, + systemSettings: SystemSettings ): VisualInterruptionDecisionProvider { return if (VisualInterruptionRefactor.isEnabled) { VisualInterruptionDecisionProviderImpl( @@ -70,7 +72,8 @@ object VisualInterruptionDecisionProviderTestUtil { systemClock, uiEventLogger, userTracker, - avalancheProvider + avalancheProvider, + systemSettings ) } else { NotificationInterruptStateProviderWrapper( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java index 69e0db9c5e7a..bb68ec540bac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java @@ -138,7 +138,6 @@ public class NotificationLoggerTest extends SysuiTestCase { mHeadsUpManager, mPowerInteractor, mActiveNotificationsInteractor, - mKosmos.getFakeSceneContainerFlags(), () -> mKosmos.getSceneInteractor()); mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 06a4d0820386..01492f629fe8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -398,7 +398,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { } @Test - public void testAboveShelfChangedListenerCalledHeadsUpGoingAway() throws Exception { + public void testAboveShelfChangedListenerCalledHeadsUpAnimatingAway() throws Exception { ExpandableNotificationRow row = mNotificationTestHelper.createRow(); AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class); row.setAboveShelfChangedListener(listener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index fe0d9d06c8f4..9e2856d65a71 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -23,7 +23,6 @@ import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; -import static com.android.systemui.concurrency.FakeExecutorKosmosKt.getFakeExecutor; import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; import static junit.framework.Assert.assertNotNull; @@ -97,7 +96,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.kotlin.JavaAdapter; -import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.wmshell.BubblesManager; import org.junit.Before; @@ -182,7 +180,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase { mHeadsUpManager, PowerInteractorFactory.create().getPowerInteractor(), mActiveNotificationsInteractor, - mKosmos.getFakeSceneContainerFlags(), () -> mKosmos.getSceneInteractor() ); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt index 65a960b5ff6c..1b85dfa5a087 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt @@ -45,6 +45,7 @@ import com.android.internal.logging.testing.UiEventLoggerFake import com.android.internal.statusbar.statusBarService import com.android.systemui.SysuiTestCase import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.kosmos.testScope import com.android.systemui.people.widget.PeopleSpaceWidgetManager @@ -55,7 +56,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractorFactory.creat import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.UserContextProvider import com.android.systemui.shade.shadeControllerSceneImpl @@ -93,6 +93,7 @@ import org.mockito.invocation.InvocationOnMock @SmallTest @RunWith(AndroidTestingRunner::class) @RunWithLooper +@EnableSceneContainer class NotificationGutsManagerWithScenesTest : SysuiTestCase() { private val testNotificationChannel = NotificationChannel( @@ -143,8 +144,6 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - val sceneContainerFlags = kosmos.fakeSceneContainerFlags - sceneContainerFlags.enabled = true allowTestableLooperAsMainThread() helper = NotificationTestHelper(mContext, mDependency) Mockito.`when`(accessibilityManager.isTouchExplorationEnabled).thenReturn(false) @@ -156,9 +155,9 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() { headsUpManager, create().powerInteractor, activeNotificationsInteractor, - sceneContainerFlags, - { sceneInteractor }, - ) + ) { + sceneInteractor + } gutsManager = NotificationGutsManager( mContext, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index abb9432425bc..1e058cac8001 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -20,7 +20,6 @@ import static android.view.View.GONE; import static android.view.WindowInsets.Type.ime; import static com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION; -import static com.android.systemui.Flags.FLAG_SCENE_CONTAINER; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.RUBBER_BAND_FACTOR_NORMAL; @@ -72,6 +71,7 @@ import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.ExpandHelper; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.DisableSceneContainer; import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.flags.FeatureFlags; @@ -227,7 +227,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test + @DisableSceneContainer // TODO(b/312473478): address disabled test public void testUpdateStackHeight_qsExpansionZero() { final float expansionFraction = 0.2f; final float overExpansion = 50f; @@ -726,7 +726,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address lack of QS Header + @DisableSceneContainer // TODO(b/312473478): address lack of QS Header public void testInsideQSHeader_noOffset() { ViewGroup qsHeader = mock(ViewGroup.class); Rect boundsOnScreen = new Rect(0, 0, 1000, 1000); @@ -743,7 +743,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address lack of QS Header + @DisableSceneContainer // TODO(b/312473478): address lack of QS Header public void testInsideQSHeader_Offset() { ViewGroup qsHeader = mock(ViewGroup.class); Rect boundsOnScreen = new Rect(100, 100, 1000, 1000); @@ -763,14 +763,14 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test + @DisableSceneContainer // TODO(b/312473478): address disabled test public void setFractionToShade_recomputesStackHeight() { mStackScroller.setFractionToShade(1f); verify(mNotificationStackSizeCalculator).computeHeight(any(), anyInt(), anyFloat()); } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test + @DisableSceneContainer // TODO(b/312473478): address disabled test public void testSetOwnScrollY_shadeNotClosing_scrollYChanges() { // Given: shade is not closing, scrollY is 0 mAmbientState.setScrollY(0); @@ -869,7 +869,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test + @DisableSceneContainer // TODO(b/312473478): address disabled test public void testSplitShade_hasTopOverscroll() { mTestableResources .addOverride(R.bool.config_use_split_notification_shade, /* value= */ true); @@ -942,7 +942,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test + @DisableSceneContainer // TODO(b/312473478): address disabled test public void testSetMaxDisplayedNotifications_notifiesListeners() { ExpandableView.OnHeightChangedListener listener = mock(ExpandableView.OnHeightChangedListener.class); @@ -957,7 +957,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_SCENE_CONTAINER) + @DisableSceneContainer public void testDispatchTouchEvent_sceneContainerDisabled() { MotionEvent event = MotionEvent.obtain( SystemClock.uptimeMillis(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt index 4bfd7e3bef83..df82df842c65 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt @@ -31,7 +31,7 @@ import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.ScreenPowerState.SCREEN_ON import com.android.systemui.power.shared.model.WakefulnessState.STARTING_TO_SLEEP import com.android.systemui.statusbar.policy.FakeConfigurationController -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractorImpl import com.android.systemui.util.animation.data.repository.FakeAnimationStatusRepository @@ -59,7 +59,7 @@ open class HideNotificationsInteractorTest : SysuiTestCase() { private val animationStatus = FakeAnimationStatusRepository() private val configurationController = FakeConfigurationController() - private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider() + private val unfoldTransitionProgressProvider = FakeUnfoldTransitionProvider() private val powerRepository = FakePowerRepository() private val powerInteractor = PowerInteractor( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 50f81ff13825..e9ec3236a06c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -131,6 +131,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { private SelectedUserInteractor mSelectedUserInteractor; @Mock private BiometricUnlockInteractor mBiometricUnlockInteractor; + @Mock + private KeyguardTransitionInteractor mKeyguardTransitionInteractor; private final FakeSystemClock mSystemClock = new FakeSystemClock(); private BiometricUnlockController mBiometricUnlockController; @@ -167,7 +169,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { () -> mSelectedUserInteractor, mBiometricUnlockInteractor, mock(JavaAdapter.class), - mock(KeyguardTransitionInteractor.class) + mKeyguardTransitionInteractor ); biometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); biometricUnlockController.addListener(mBiometricUnlockEventsListener); @@ -374,6 +376,24 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { } @Test + public void onBiometricAuthenticated_whenFaceOnAlternateBouncer_dismissBouncer() { + when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); + when(mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()).thenReturn(false); + when(mKeyguardTransitionInteractor.getCurrentState()) + .thenReturn(KeyguardState.ALTERNATE_BOUNCER); + // the value of isStrongBiometric doesn't matter here since we only care about the returned + // value of isUnlockingWithBiometricAllowed() + mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, + BiometricSourceType.FACE, true /* isStrongBiometric */); + + verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); + assertThat(mBiometricUnlockController.getMode()) + .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER); + assertThat(mBiometricUnlockController.getBiometricType()) + .isEqualTo(BiometricSourceType.FACE); + } + + @Test public void onBiometricAuthenticated_whenBypassOnBouncer_dismissBouncer() { reset(mKeyguardBypassController); when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 2f153d8b7003..5c651035262d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -101,6 +102,7 @@ import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.communal.shared.model.CommunalScenes; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.fragments.FragmentService; @@ -120,7 +122,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.res.R; import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor; -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.brightness.BrightnessSliderController; import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor; @@ -181,7 +182,9 @@ import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.MessageRouterImpl; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.settings.FakeGlobalSettings; +import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.settings.GlobalSettings; +import com.android.systemui.util.settings.SystemSettings; import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.time.SystemClock; import com.android.systemui.volume.VolumeComponent; @@ -325,6 +328,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { private ShadeController mShadeController; private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeGlobalSettings mFakeGlobalSettings = new FakeGlobalSettings(); + private final SystemSettings mSystemSettings = new FakeSettings(); private final FakeEventLog mFakeEventLog = new FakeEventLog(); private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock); private final FakeExecutor mUiBgExecutor = new FakeExecutor(mFakeSystemClock); @@ -333,8 +337,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { private final DumpManager mDumpManager = new DumpManager(); private final ScreenLifecycle mScreenLifecycle = new ScreenLifecycle(mDumpManager); - private final FakeSceneContainerFlags mSceneContainerFlags = new FakeSceneContainerFlags(); - private final BrightnessMirrorShowingInteractor mBrightnessMirrorShowingInteractor = mKosmos.getBrightnessMirrorShowingInteractor(); @@ -348,7 +350,9 @@ public class CentralSurfacesImplTest extends SysuiTestCase { // Turn AOD on and toggle feature flag for jank fixes mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true); when(mDozeParameters.getAlwaysOn()).thenReturn(true); - mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR); + if (!com.android.systemui.Flags.sceneContainer()) { + mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR); + } IThermalService thermalService = mock(IThermalService.class); mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService, @@ -375,7 +379,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mFakeSystemClock, mock(UiEventLogger.class), mUserTracker, - mAvalancheProvider); + mAvalancheProvider, + mSystemSettings); mVisualInterruptionDecisionProvider.start(); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); @@ -422,22 +427,25 @@ public class CentralSurfacesImplTest extends SysuiTestCase { ((Runnable) invocation.getArgument(0)).run(); return null; }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); - - mShadeController = spy(new ShadeControllerImpl( - mCommandQueue, - mMainExecutor, - mock(WindowRootViewVisibilityInteractor.class), - mKeyguardStateController, - mStatusBarStateController, - mStatusBarKeyguardViewManager, - mStatusBarWindowController, - mDeviceProvisionedController, - mNotificationShadeWindowController, - 0, - () -> mNotificationPanelViewController, - () -> mAssistManager, - () -> mNotificationGutsManager - )); + if (com.android.systemui.Flags.sceneContainer()) { + mShadeController = spy(mKosmos.getShadeController()); + } else { + mShadeController = spy(new ShadeControllerImpl( + mCommandQueue, + mMainExecutor, + mock(WindowRootViewVisibilityInteractor.class), + mKeyguardStateController, + mStatusBarStateController, + mStatusBarKeyguardViewManager, + mStatusBarWindowController, + mDeviceProvisionedController, + mNotificationShadeWindowController, + 0, + () -> mNotificationPanelViewController, + () -> mAssistManager, + () -> mNotificationGutsManager + )); + } mShadeController.setNotificationShadeWindowViewController( mNotificationShadeWindowViewController); mShadeController.setNotificationPresenter(mNotificationPresenter); @@ -558,7 +566,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mUserTracker, () -> mFingerprintManager, mActivityStarter, - mSceneContainerFlags, mBrightnessMirrorShowingInteractor ); mScreenLifecycle.addObserver(mCentralSurfaces.mScreenObserver); @@ -568,8 +575,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { any(NotificationPanelViewController.class), any(ShadeExpansionStateManager.class), any(BiometricUnlockController.class), - any(ViewGroup.class), - any(KeyguardBypassController.class))) + any(ViewGroup.class))) .thenReturn(mStatusBarKeyguardViewManager); when(mKeyguardViewMediator.getViewMediatorCallback()).thenReturn( @@ -1091,25 +1097,24 @@ public class CentralSurfacesImplTest extends SysuiTestCase { } @Test + @EnableSceneContainer public void brightnesShowingChanged_flagEnabled_ScrimControllerNotified() { - mSceneContainerFlags.setEnabled(true); mCentralSurfaces.registerCallbacks(); mBrightnessMirrorShowingInteractor.setMirrorShowing(true); mTestScope.getTestScheduler().runCurrent(); - verify(mScrimController).transitionTo(ScrimState.BRIGHTNESS_MIRROR); + verify(mScrimController, atLeastOnce()).transitionTo(ScrimState.BRIGHTNESS_MIRROR); mBrightnessMirrorShowingInteractor.setMirrorShowing(false); mTestScope.getTestScheduler().runCurrent(); ArgumentCaptor<ScrimState> captor = ArgumentCaptor.forClass(ScrimState.class); // The default is to call the one with the callback argument - verify(mScrimController).transitionTo(captor.capture(), any()); + verify(mScrimController, atLeastOnce()).transitionTo(captor.capture(), any()); assertThat(captor.getValue()).isNotEqualTo(ScrimState.BRIGHTNESS_MIRROR); } @Test public void brightnesShowingChanged_flagDisabled_ScrimControllerNotified() { - mSceneContainerFlags.setEnabled(false); mCentralSurfaces.registerCallbacks(); mBrightnessMirrorShowingInteractor.setMirrorShowing(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt index 7362e342f321..6150253b917e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt @@ -24,6 +24,8 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.res.R @@ -72,6 +74,7 @@ class KeyguardBypassControllerTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateController @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor @Mock private lateinit var devicePostureController: DevicePostureController @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var packageManager: PackageManager @@ -138,7 +141,8 @@ class KeyguardBypassControllerTest : SysuiTestCase() { private fun initKeyguardBypassController() { keyguardBypassController = KeyguardBypassController( - context, + context.resources, + context.packageManager, testScope.backgroundScope, tunerService, statusBarStateController, @@ -146,7 +150,8 @@ class KeyguardBypassControllerTest : SysuiTestCase() { keyguardStateController, shadeRepository, devicePostureController, - dumpManager + keyguardTransitionInteractor, + dumpManager, ) } @@ -302,4 +307,26 @@ class KeyguardBypassControllerTest : SysuiTestCase() { job.cancel() } } + + @Test + fun canBypass_bypassDisabled() { + context.orCreateTestableResources.addOverride( + R.integer.config_face_unlock_bypass_override, + 2 /* FACE_UNLOCK_BYPASS_NEVER */ + ) + initKeyguardBypassController() + assertThat(keyguardBypassController.canBypass()).isFalse() + } + + @Test + fun canBypass_bypassEnabled_alternateBouncerShowing() { + context.orCreateTestableResources.addOverride( + R.integer.config_face_unlock_bypass_override, + 1 /* FACE_UNLOCK_BYPASS_ALWAYS */ + ) + initKeyguardBypassController() + whenever(keyguardTransitionInteractor.getCurrentState()) + .thenReturn(KeyguardState.ALTERNATE_BOUNCER) + assertThat(keyguardBypassController.canBypass()).isTrue() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java index 05fd63e96089..a6a4f24be4a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java @@ -20,9 +20,9 @@ package com.android.systemui.statusbar.phone; import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO; +import static com.android.systemui.Flags.FLAG_UPDATE_USER_SWITCHER_BACKGROUND; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; -import static com.android.systemui.Flags.FLAG_UPDATE_USER_SWITCHER_BACKGROUND; import static com.google.common.truth.Truth.assertThat; @@ -172,7 +172,6 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { mKeyguardRepository, mCommandQueue, PowerInteractorFactory.create().getPowerInteractor(), - mKosmos.getFakeSceneContainerFlags(), new FakeKeyguardBouncerRepository(), new ConfigurationInteractor(new FakeConfigurationRepository()), new FakeShadeRepository(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index 1463680de7d8..d365663e3621 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -33,7 +33,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.res.R -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.ShadeControllerImpl import com.android.systemui.shade.ShadeLogger @@ -51,6 +50,8 @@ import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.whenever import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat +import java.util.Optional +import javax.inject.Provider import org.junit.Before import org.junit.Test import org.mockito.ArgumentCaptor @@ -61,8 +62,6 @@ import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations -import java.util.Optional -import javax.inject.Provider @SmallTest class PhoneStatusBarViewControllerTest : SysuiTestCase() { @@ -296,7 +295,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { Optional.of(sysuiUnfoldComponent), Optional.of(progressProvider), featureFlags, - FakeSceneContainerFlags(), userChipViewModel, centralSurfacesImpl, statusBarWindowStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 34605fed7d28..f04a5ab2d8f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -76,8 +76,6 @@ import com.android.systemui.bouncer.ui.BouncerView; import com.android.systemui.bouncer.ui.BouncerViewDelegate; import com.android.systemui.dock.DockManager; import com.android.systemui.dreams.DreamOverlayStateController; -import com.android.systemui.flags.FakeFeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; @@ -145,7 +143,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { @Mock private SysUIUnfoldComponent mSysUiUnfoldComponent; @Mock private DreamOverlayStateController mDreamOverlayStateController; @Mock private LatencyTracker mLatencyTracker; - private FakeFeatureFlags mFeatureFlags; @Mock private KeyguardSecurityModel mKeyguardSecurityModel; @Mock private PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor; @Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor; @@ -188,11 +185,10 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { .thenReturn(mKeyguardMessageAreaController); when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate); when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback); - mFeatureFlags = new FakeFeatureFlags(); - mFeatureFlags.set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false); mSetFlagsRule.disableFlags( com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR, - com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR + com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR, + com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT ); when(mNotificationShadeWindowController.getWindowRootView()) @@ -218,7 +214,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { () -> mShadeController, mLatencyTracker, mKeyguardSecurityModel, - mFeatureFlags, mPrimaryBouncerCallbackInteractor, mPrimaryBouncerInteractor, mBouncerView, @@ -246,8 +241,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mShadeLockscreenInteractor, new ShadeExpansionStateManager(), mBiometricUnlockController, - mNotificationContainer, - mBypassController); + mNotificationContainer); mStatusBarKeyguardViewManager.show(null); ArgumentCaptor<PrimaryBouncerExpansionCallback> callbackArgumentCaptor = ArgumentCaptor.forClass(PrimaryBouncerExpansionCallback.class); @@ -728,7 +722,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { () -> mShadeController, mLatencyTracker, mKeyguardSecurityModel, - mFeatureFlags, mPrimaryBouncerCallbackInteractor, mPrimaryBouncerInteractor, mBouncerView, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt index feff046bb708..1ec1765e2e57 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt @@ -8,7 +8,7 @@ import android.view.View import android.view.WindowManager import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.unfold.util.CurrentActivityTypeProvider import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider import com.android.systemui.util.mockito.whenever @@ -23,17 +23,14 @@ import org.mockito.MockitoAnnotations @TestableLooper.RunWithLooper class StatusBarMoveFromCenterAnimationControllerTest : SysuiTestCase() { - @Mock - private lateinit var windowManager: WindowManager + @Mock private lateinit var windowManager: WindowManager - @Mock - private lateinit var display: Display + @Mock private lateinit var display: Display - @Mock - private lateinit var currentActivityTypeProvider: CurrentActivityTypeProvider + @Mock private lateinit var currentActivityTypeProvider: CurrentActivityTypeProvider private val view: View = View(context) - private val progressProvider = TestUnfoldTransitionProvider() + private val progressProvider = FakeUnfoldTransitionProvider() private val scopedProvider = ScopedUnfoldTransitionProgressProvider(progressProvider) private lateinit var controller: StatusBarMoveFromCenterAnimationController diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt index 1e628bd35053..dedd0afb6127 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt @@ -13,68 +13,103 @@ */ package com.android.systemui.statusbar.phone +import android.app.Dialog import android.content.res.Configuration import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import android.view.WindowManager import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.testScope import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.mock -import com.google.common.truth.Truth.assertThat import kotlin.test.Test +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.runner.RunWith import org.mockito.Mockito.verify +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidTestingRunner::class) @RunWithLooper(setAsMainLooper = true) class SystemUIBottomSheetDialogTest : SysuiTestCase() { + private val kosmos = testKosmos() private val configurationController = mock<ConfigurationController>() private val config = mock<Configuration>() + private val delegate = mock<DialogDelegate<Dialog>>() private lateinit var dialog: SystemUIBottomSheetDialog @Before fun setup() { - dialog = SystemUIBottomSheetDialog(mContext, configurationController) + dialog = + with(kosmos) { + SystemUIBottomSheetDialog( + context, + testScope.backgroundScope, + configurationController, + delegate, + TestLayout(), + 0, + ) + } } @Test fun onStart_registersConfigCallback() { - dialog.show() + kosmos.testScope.runTest { + dialog.show() + runCurrent() - verify(configurationController).addCallback(any()) + verify(configurationController).addCallback(any()) + } } @Test fun onStop_unregisterConfigCallback() { - dialog.show() - dialog.dismiss() + kosmos.testScope.runTest { + dialog.show() + runCurrent() + dialog.dismiss() + runCurrent() - verify(configurationController).removeCallback(any()) + verify(configurationController).removeCallback(any()) + } } @Test - fun onConfigurationChanged_calledInSubclass() { - var onConfigChangedCalled = false - val subclass = - object : SystemUIBottomSheetDialog(mContext, configurationController) { - override fun onConfigurationChanged() { - onConfigChangedCalled = true - } - } + fun onConfigurationChanged_calledInDelegate() { + kosmos.testScope.runTest { + dialog.show() + runCurrent() + val captor = argumentCaptor<ConfigurationController.ConfigurationListener>() + verify(configurationController).addCallback(capture(captor)) - subclass.show() + captor.value.onConfigChanged(config) + runCurrent() - val captor = argumentCaptor<ConfigurationController.ConfigurationListener>() - verify(configurationController).addCallback(capture(captor)) - captor.value.onConfigChanged(config) + verify(delegate).onConfigurationChanged(any(), any()) + } + } - assertThat(onConfigChangedCalled).isTrue() + private class TestLayout : SystemUIBottomSheetDialog.WindowLayout { + override fun calculate(): Flow<SystemUIBottomSheetDialog.WindowLayout.Layout> { + return flowOf( + SystemUIBottomSheetDialog.WindowLayout.Layout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT, + ) + ) + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt index 9b6940e14415..598b12ccdc38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt @@ -137,6 +137,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() { wifiRepository, mock(), mock(), + mock(), ) demoRepo = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt index c13e830afac7..3c13906dbd43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod import android.net.ConnectivityManager +import android.os.PersistableBundle import android.telephony.ServiceState import android.telephony.SignalStrength import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET @@ -99,6 +100,9 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { ) ) + // Use a real config, with no overrides + private val systemUiCarrierConfig = SystemUiCarrierConfig(SUB_ID, PersistableBundle()) + private lateinit var mobileRepo: FakeMobileConnectionRepository private lateinit var carrierMergedRepo: FakeMobileConnectionRepository @@ -680,10 +684,6 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { telephonyManager: TelephonyManager, ): MobileConnectionRepositoryImpl { whenever(telephonyManager.subscriptionId).thenReturn(SUB_ID) - val systemUiCarrierConfigMock: SystemUiCarrierConfig = mock() - whenever(systemUiCarrierConfigMock.satelliteConnectionHysteresisSeconds) - .thenReturn(MutableStateFlow(0)) - val realRepo = MobileConnectionRepositoryImpl( SUB_ID, @@ -693,7 +693,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { SEP, connectivityManager, telephonyManager, - systemUiCarrierConfig = systemUiCarrierConfigMock, + systemUiCarrierConfig = systemUiCarrierConfig, fakeBroadcastDispatcher, mobileMappingsProxy = mock(), testDispatcher, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index f761bcfe63d6..9d1411625a8f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -1030,6 +1030,26 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { } @Test + fun inflateSignalStrength_usesCarrierConfig() = + testScope.runTest { + val latest by collectLastValue(underTest.inflateSignalStrength) + + assertThat(latest).isEqualTo(false) + + systemUiCarrierConfig.processNewCarrierConfig( + configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true) + ) + + assertThat(latest).isEqualTo(true) + + systemUiCarrierConfig.processNewCarrierConfig( + configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false) + ) + + assertThat(latest).isEqualTo(false) + } + + @Test fun isAllowedDuringAirplaneMode_alwaysFalse() = testScope.runTest { val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt index 07abd275d1ce..b7a3b300a460 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt @@ -80,6 +80,7 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Assert.assertTrue import org.junit.Before +import org.junit.Ignore import org.junit.Test import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString @@ -229,6 +230,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { wifiRepository, fullConnectionFactory, updateMonitor, + mock(), ) testScope.runCurrent() @@ -529,6 +531,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { } @Test + @Ignore("b/333912012") fun testConnectionCache_clearsInvalidSubscriptions() = testScope.runTest { collectLastValue(underTest.subscriptions) @@ -553,6 +556,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { } @Test + @Ignore("b/333912012") fun testConnectionCache_clearsInvalidSubscriptions_includingCarrierMerged() = testScope.runTest { collectLastValue(underTest.subscriptions) @@ -581,6 +585,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { /** Regression test for b/261706421 */ @Test + @Ignore("b/333912012") fun testConnectionsCache_clearMultipleSubscriptionsAtOnce_doesNotThrow() = testScope.runTest { collectLastValue(underTest.subscriptions) @@ -604,6 +609,54 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { } @Test + fun testConnectionsCache_keepsReposCached() = + testScope.runTest { + // Collect subscriptions to start the job + collectLastValue(underTest.subscriptions) + + whenever(subscriptionManager.completeActiveSubscriptionInfoList) + .thenReturn(listOf(SUB_1)) + getSubscriptionCallback().onSubscriptionsChanged() + + val repo1_1 = underTest.getRepoForSubId(SUB_1_ID) + + // All subscriptions disappear + whenever(subscriptionManager.completeActiveSubscriptionInfoList).thenReturn(listOf()) + getSubscriptionCallback().onSubscriptionsChanged() + + // Sub1 comes back + whenever(subscriptionManager.completeActiveSubscriptionInfoList) + .thenReturn(listOf(SUB_1)) + getSubscriptionCallback().onSubscriptionsChanged() + + val repo1_2 = underTest.getRepoForSubId(SUB_1_ID) + + assertThat(repo1_1).isSameInstanceAs(repo1_2) + } + + @Test + fun testConnectionsCache_doesNotDropReferencesThatHaveBeenRealized() = + testScope.runTest { + // Collect subscriptions to start the job + collectLastValue(underTest.subscriptions) + + whenever(subscriptionManager.completeActiveSubscriptionInfoList) + .thenReturn(listOf(SUB_1)) + getSubscriptionCallback().onSubscriptionsChanged() + + // Client grabs a reference to a repository, but doesn't keep it around + underTest.getRepoForSubId(SUB_1_ID) + + // All subscriptions disappear + whenever(subscriptionManager.completeActiveSubscriptionInfoList).thenReturn(listOf()) + getSubscriptionCallback().onSubscriptionsChanged() + + val repo1 = underTest.getRepoForSubId(SUB_1_ID) + + assertThat(repo1).isNotNull() + } + + @Test fun testConnectionRepository_invalidSubId_doesNotThrow() = testScope.runTest { underTest.getRepoForSubId(SUB_1_ID) @@ -1063,7 +1116,8 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { airplaneModeRepository, wifiRepository, fullConnectionFactory, - updateMonitor + updateMonitor, + mock(), ) val latest by collectLastValue(underTest.defaultDataSubRatConfig) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt index c49fcf88ecaa..dfe80233918a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt @@ -43,15 +43,12 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlin.time.Duration.Companion.seconds -import kotlin.time.DurationUnit import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -181,6 +178,22 @@ class MobileIconInteractorTest : SysuiTestCase() { } @Test + fun inflateSignalStrength_arbitrarilyAddsOneToTheReportedLevel() = + testScope.runTest { + connectionRepository.inflateSignalStrength.value = false + val latest by collectLastValue(underTest.signalLevelIcon) + + connectionRepository.primaryLevel.value = 4 + assertThat(latest!!.level).isEqualTo(4) + + connectionRepository.inflateSignalStrength.value = true + connectionRepository.primaryLevel.value = 4 + + // when INFLATE_SIGNAL_STRENGTH is true, we add 1 to the reported signal level + assertThat(latest!!.level).isEqualTo(5) + } + + @Test fun iconGroup_three_g() = testScope.runTest { connectionRepository.resolvedNetworkType.value = @@ -678,32 +691,6 @@ class MobileIconInteractorTest : SysuiTestCase() { assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java) } - @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) - @Test - fun satBasedIcon_hasHysteresisWhenDisabled() = - testScope.runTest { - val latest by collectLastValue(underTest.signalLevelIcon) - - val hysteresisDuration = 5.seconds - connectionRepository.satelliteConnectionHysteresisSeconds.value = - hysteresisDuration.toInt(DurationUnit.SECONDS) - - connectionRepository.isNonTerrestrial.value = true - - assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java) - - // Disable satellite - connectionRepository.isNonTerrestrial.value = false - - // Satellite icon should still be visible - assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java) - - // Wait for the icon to change - advanceTimeBy(hysteresisDuration) - - assertThat(latest).isInstanceOf(SignalIconModel.Cellular::class.java) - } - private fun createInteractor( overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl() ) = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt index 83d0fe8f9c4b..cec41557f344 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt @@ -54,6 +54,7 @@ import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupReposi import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn @@ -279,6 +280,76 @@ class MobileIconViewModelTest : SysuiTestCase() { } @Test + fun contentDescription_nonInflated_invalidLevelIsNull() = + testScope.runTest { + val latest by collectLastValue(underTest.contentDescription) + + repository.inflateSignalStrength.value = false + repository.setAllLevels(-1) + assertThat(latest).isNull() + + repository.setAllLevels(100) + assertThat(latest).isNull() + } + + @Test + fun contentDescription_inflated_invalidLevelIsNull() = + testScope.runTest { + val latest by collectLastValue(underTest.contentDescription) + + repository.inflateSignalStrength.value = true + repository.numberOfLevels.value = 6 + repository.setAllLevels(-2) + assertThat(latest).isNull() + + repository.setAllLevels(100) + assertThat(latest).isNull() + } + + @Test + fun contentDescription_nonInflated_testABunchOfLevelsForNull() = + testScope.runTest { + val latest by collectLastValue(underTest.contentDescription) + + repository.inflateSignalStrength.value = false + repository.numberOfLevels.value = 5 + + // -1 and 5 are out of the bounds for non-inflated content descriptions + for (i in -1..5) { + repository.setAllLevels(i) + when (i) { + -1, + 5 -> assertWithMessage("Level $i is expected to be null").that(latest).isNull() + else -> + assertWithMessage("Level $i is expected not to be null") + .that(latest) + .isNotNull() + } + } + } + + @Test + fun contentDescription_inflated_testABunchOfLevelsForNull() = + testScope.runTest { + val latest by collectLastValue(underTest.contentDescription) + repository.inflateSignalStrength.value = true + repository.numberOfLevels.value = 6 + // -1 and 6 are out of the bounds for inflated content descriptions + // Note that the interactor adds 1 to the reported level, hence the -2 to 5 range + for (i in -2..5) { + repository.setAllLevels(i) + when (i) { + -2, + 5 -> assertWithMessage("Level $i is expected to be null").that(latest).isNull() + else -> + assertWithMessage("Level $i is not expected to be null") + .that(latest) + .isNotNull() + } + } + } + + @Test fun networkType_dataEnabled_groupIsRepresented() = testScope.runTest { val expected = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt index 42bbe3e6fa1d..c4ab943c09df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt @@ -26,6 +26,10 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobi import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.satellite.data.prod.FakeDeviceBasedSatelliteRepository import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState +import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository +import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.util.mockito.mock @@ -53,6 +57,10 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { private val deviceProvisionedRepository = FakeDeviceProvisioningRepository() private val deviceProvisioningInteractor = DeviceProvisioningInteractor(deviceProvisionedRepository) + private val connectivityRepository = FakeConnectivityRepository() + private val wifiRepository = FakeWifiRepository() + private val wifiInteractor = + WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope) @Before fun setUp() { @@ -61,6 +69,7 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { repo, iconsInteractor, deviceProvisioningInteractor, + wifiInteractor, testScope.backgroundScope, ) } @@ -103,6 +112,7 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { repo, iconsInteractor, deviceProvisioningInteractor, + wifiInteractor, testScope.backgroundScope, ) @@ -150,6 +160,7 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { repo, iconsInteractor, deviceProvisioningInteractor, + wifiInteractor, testScope.backgroundScope, ) @@ -205,6 +216,7 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { repo, iconsInteractor, deviceProvisioningInteractor, + wifiInteractor, testScope.backgroundScope, ) @@ -337,6 +349,7 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { repo, iconsInteractor, deviceProvisioningInteractor, + wifiInteractor, testScope.backgroundScope, ) @@ -353,4 +366,28 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { // THEN the value is still false, because the flag is off assertThat(latest).isFalse() } + + @Test + fun isWifiActive_falseWhenWifiNotActive() = + testScope.runTest { + val latest by collectLastValue(underTest.isWifiActive) + + // WHEN wifi is not active + wifiRepository.setWifiNetwork(WifiNetworkModel.Invalid("test")) + + // THEN the interactor returns false due to the wifi network not being active + assertThat(latest).isFalse() + } + + @Test + fun isWifiActive_trueWhenWifiIsActive() = + testScope.runTest { + val latest by collectLastValue(underTest.isWifiActive) + + // WHEN wifi is active + wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1)) + + // THEN the interactor returns true due to the wifi network being active + assertThat(latest).isTrue() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt index 1d6cd3774449..64f19b6c60ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt @@ -26,6 +26,10 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobi import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.satellite.data.prod.FakeDeviceBasedSatelliteRepository import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor +import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository +import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.util.mockito.mock @@ -44,14 +48,18 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { private lateinit var underTest: DeviceBasedSatelliteViewModel private lateinit var interactor: DeviceBasedSatelliteInteractor private lateinit var airplaneModeRepository: FakeAirplaneModeRepository - private val repo = FakeDeviceBasedSatelliteRepository() + private val testScope = TestScope() + private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) + private val deviceProvisionedRepository = FakeDeviceProvisioningRepository() private val deviceProvisioningInteractor = DeviceProvisioningInteractor(deviceProvisionedRepository) - - private val testScope = TestScope() + private val connectivityRepository = FakeConnectivityRepository() + private val wifiRepository = FakeWifiRepository() + private val wifiInteractor = + WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope) @Before fun setUp() { @@ -63,6 +71,7 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { repo, mobileIconsInteractor, deviceProvisioningInteractor, + wifiInteractor, testScope.backgroundScope, ) @@ -253,4 +262,40 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { // THEN icon is null because the device is not provisioned assertThat(latest).isInstanceOf(Icon::class.java) } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun icon_wifiIsActive() = + testScope.runTest { + val latest by collectLastValue(underTest.icon) + + // GIVEN satellite is allowed + repo.isSatelliteAllowedForCurrentLocation.value = true + + // GIVEN all icons are OOS + val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1) + i1.isInService.value = false + i1.isEmergencyOnly.value = false + + // GIVEN apm is disabled + airplaneModeRepository.setIsAirplaneMode(false) + + // GIVEN device is provisioned + deviceProvisionedRepository.setDeviceProvisioned(true) + + // GIVEN wifi network is active + wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1)) + + // THEN icon is null because the device is connected to wifi + assertThat(latest).isNull() + + // GIVEN device loses wifi connection + wifiRepository.setWifiNetwork(WifiNetworkModel.Invalid("test")) + + // Wait for delay to be completed + advanceTimeBy(10.seconds) + + // THEN icon is set because the device lost wifi connection + assertThat(latest).isInstanceOf(Icon::class.java) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt index ae3425678abd..bdd3d188ad91 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt @@ -30,7 +30,6 @@ import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.data.repository.FakeKeyguardStatusBarRepository @@ -60,7 +59,6 @@ class KeyguardStatusBarViewModelTest : SysuiTestCase() { keyguardRepository, mock<CommandQueue>(), PowerInteractorFactory.create().powerInteractor, - kosmos.fakeSceneContainerFlags, FakeKeyguardBouncerRepository(), ConfigurationInteractor(FakeConfigurationRepository()), FakeShadeRepository(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt index 7a83cfe852d6..6f589418cf1e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt @@ -23,14 +23,8 @@ import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.animation.AnimatorTestRule import com.android.systemui.model.SysUiStateTest -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.EASE_IN -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.EASE_OUT -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.MAIN -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.NOT_PLAYING -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationStateChangedCallback -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.PaintDrawCallback -import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.RenderEffectDrawCallback +import com.android.systemui.surfaceeffects.PaintDrawCallback +import com.android.systemui.surfaceeffects.RenderEffectDrawCallback import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader import com.google.common.truth.Truth.assertThat @@ -50,8 +44,8 @@ class LoadingEffectTest : SysUiStateTest() { var paintFromCallback: Paint? = null val drawCallback = object : PaintDrawCallback { - override fun onDraw(loadingPaint: Paint) { - paintFromCallback = loadingPaint + override fun onDraw(paint: Paint) { + paintFromCallback = paint } } val loadingEffect = @@ -75,8 +69,8 @@ class LoadingEffectTest : SysUiStateTest() { var renderEffectFromCallback: RenderEffect? = null val drawCallback = object : RenderEffectDrawCallback { - override fun onDraw(loadingRenderEffect: RenderEffect) { - renderEffectFromCallback = loadingRenderEffect + override fun onDraw(renderEffect: RenderEffect) { + renderEffectFromCallback = renderEffect } } val loadingEffect = @@ -98,16 +92,19 @@ class LoadingEffectTest : SysUiStateTest() { @Test fun play_animationStateChangesInOrder() { val config = TurbulenceNoiseAnimationConfig() - val states = mutableListOf(NOT_PLAYING) + val states = mutableListOf(LoadingEffect.AnimationState.NOT_PLAYING) val stateChangedCallback = - object : AnimationStateChangedCallback { - override fun onStateChanged(oldState: AnimationState, newState: AnimationState) { + object : LoadingEffect.AnimationStateChangedCallback { + override fun onStateChanged( + oldState: LoadingEffect.AnimationState, + newState: LoadingEffect.AnimationState + ) { states.add(newState) } } val drawCallback = object : PaintDrawCallback { - override fun onDraw(loadingPaint: Paint) {} + override fun onDraw(paint: Paint) {} } val loadingEffect = LoadingEffect( @@ -125,7 +122,14 @@ class LoadingEffectTest : SysUiStateTest() { animatorTestRule.advanceTimeBy(config.easeOutDuration.toLong()) animatorTestRule.advanceTimeBy(500) - assertThat(states).containsExactly(NOT_PLAYING, EASE_IN, MAIN, EASE_OUT, NOT_PLAYING) + assertThat(states) + .containsExactly( + LoadingEffect.AnimationState.NOT_PLAYING, + LoadingEffect.AnimationState.EASE_IN, + LoadingEffect.AnimationState.MAIN, + LoadingEffect.AnimationState.EASE_OUT, + LoadingEffect.AnimationState.NOT_PLAYING + ) } @Test @@ -133,16 +137,22 @@ class LoadingEffectTest : SysUiStateTest() { val config = TurbulenceNoiseAnimationConfig() var numPlay = 0 val stateChangedCallback = - object : AnimationStateChangedCallback { - override fun onStateChanged(oldState: AnimationState, newState: AnimationState) { - if (oldState == NOT_PLAYING && newState == EASE_IN) { + object : LoadingEffect.AnimationStateChangedCallback { + override fun onStateChanged( + oldState: LoadingEffect.AnimationState, + newState: LoadingEffect.AnimationState + ) { + if ( + oldState == LoadingEffect.AnimationState.NOT_PLAYING && + newState == LoadingEffect.AnimationState.EASE_IN + ) { numPlay++ } } } val drawCallback = object : PaintDrawCallback { - override fun onDraw(loadingPaint: Paint) {} + override fun onDraw(paint: Paint) {} } val loadingEffect = LoadingEffect( @@ -172,9 +182,15 @@ class LoadingEffectTest : SysUiStateTest() { } var isFinished = false val stateChangedCallback = - object : AnimationStateChangedCallback { - override fun onStateChanged(oldState: AnimationState, newState: AnimationState) { - if (oldState == EASE_OUT && newState == NOT_PLAYING) { + object : LoadingEffect.AnimationStateChangedCallback { + override fun onStateChanged( + oldState: LoadingEffect.AnimationState, + newState: LoadingEffect.AnimationState + ) { + if ( + oldState == LoadingEffect.AnimationState.EASE_OUT && + newState == LoadingEffect.AnimationState.NOT_PLAYING + ) { isFinished = true } } @@ -205,13 +221,19 @@ class LoadingEffectTest : SysUiStateTest() { val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f) val drawCallback = object : PaintDrawCallback { - override fun onDraw(loadingPaint: Paint) {} + override fun onDraw(paint: Paint) {} } var isFinished = false val stateChangedCallback = - object : AnimationStateChangedCallback { - override fun onStateChanged(oldState: AnimationState, newState: AnimationState) { - if (oldState == MAIN && newState == NOT_PLAYING) { + object : LoadingEffect.AnimationStateChangedCallback { + override fun onStateChanged( + oldState: LoadingEffect.AnimationState, + newState: LoadingEffect.AnimationState + ) { + if ( + oldState == LoadingEffect.AnimationState.MAIN && + newState == LoadingEffect.AnimationState.NOT_PLAYING + ) { isFinished = true } } @@ -242,7 +264,7 @@ class LoadingEffectTest : SysUiStateTest() { ) val drawCallback = object : PaintDrawCallback { - override fun onDraw(loadingPaint: Paint) {} + override fun onDraw(paint: Paint) {} } val loadingEffect = LoadingEffect( diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt index 28adbceda847..383f4a33857d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt @@ -86,7 +86,7 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { private val areAnimationEnabled = MutableStateFlow(true) private val lastWakefulnessEvent = MutableStateFlow(WakefulnessModel()) private val systemClock = FakeSystemClock() - private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider() + private val unfoldTransitionProgressProvider = FakeUnfoldTransitionProvider() private val unfoldTransitionRepository = UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider)) private val unfoldTransitionInteractor = diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt index b9c7e6133669..fd513c9c9235 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt @@ -35,7 +35,7 @@ import org.mockito.Mockito.verify @SmallTest class UnfoldHapticsPlayerTest : SysuiTestCase() { - private val progressProvider = TestUnfoldTransitionProvider() + private val progressProvider = FakeUnfoldTransitionProvider() private val vibrator: Vibrator = mock() private val testFoldProvider = TestFoldProvider() diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt index ba72716997e3..2955384c0bbd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt @@ -27,6 +27,7 @@ import com.android.systemui.keyguard.ScreenLifecycle import com.android.systemui.unfold.util.FoldableDeviceStates import com.android.systemui.unfold.util.FoldableTestUtils import com.android.systemui.util.mockito.any +import java.util.Optional import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -37,45 +38,41 @@ import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations -import java.util.Optional @RunWith(AndroidTestingRunner::class) @SmallTest class UnfoldLatencyTrackerTest : SysuiTestCase() { - @Mock - lateinit var latencyTracker: LatencyTracker + @Mock lateinit var latencyTracker: LatencyTracker - @Mock - lateinit var deviceStateManager: DeviceStateManager + @Mock lateinit var deviceStateManager: DeviceStateManager - @Mock - lateinit var screenLifecycle: ScreenLifecycle + @Mock lateinit var screenLifecycle: ScreenLifecycle - @Captor - private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener> + @Captor private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener> - @Captor - private lateinit var screenLifecycleCaptor: ArgumentCaptor<ScreenLifecycle.Observer> + @Captor private lateinit var screenLifecycleCaptor: ArgumentCaptor<ScreenLifecycle.Observer> private lateinit var deviceStates: FoldableDeviceStates private lateinit var unfoldLatencyTracker: UnfoldLatencyTracker - private val transitionProgressProvider = TestUnfoldTransitionProvider() + private val transitionProgressProvider = FakeUnfoldTransitionProvider() @Before fun setUp() { MockitoAnnotations.initMocks(this) - unfoldLatencyTracker = UnfoldLatencyTracker( - latencyTracker, - deviceStateManager, - Optional.of(transitionProgressProvider), - context.mainExecutor, - context, - context.contentResolver, - screenLifecycle - ).apply { init() } + unfoldLatencyTracker = + UnfoldLatencyTracker( + latencyTracker, + deviceStateManager, + Optional.of(transitionProgressProvider), + context.mainExecutor, + context, + context.contentResolver, + screenLifecycle + ) + .apply { init() } deviceStates = FoldableTestUtils.findDeviceStates(context) verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture()) @@ -107,7 +104,7 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { } @Test - fun unfold_firstFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventNotPropagated() { + fun firstFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventNotPropagated() { setAnimationsEnabled(true) sendFoldEvent(folded = false) @@ -118,7 +115,7 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { } @Test - fun unfold_secondFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() { + fun secondFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() { setAnimationsEnabled(true) sendFoldEvent(folded = true) sendFoldEvent(folded = false) @@ -131,7 +128,7 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { } @Test - fun unfold_unfoldFoldUnfoldAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() { + fun unfoldFoldUnfoldAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() { setAnimationsEnabled(true) sendFoldEvent(folded = false) sendFoldEvent(folded = true) @@ -196,4 +193,4 @@ class UnfoldLatencyTrackerTest : SysuiTestCase() { durationScale.toString() ) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt index 6ec0251d41a5..0c452eb9d461 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt @@ -17,21 +17,18 @@ import org.mockito.junit.MockitoJUnit @SmallTest class UnfoldTransitionWallpaperControllerTest : SysuiTestCase() { - @Mock - private lateinit var wallpaperController: WallpaperController + @Mock private lateinit var wallpaperController: WallpaperController - private val progressProvider = TestUnfoldTransitionProvider() + private val progressProvider = FakeUnfoldTransitionProvider() - @JvmField - @Rule - val mockitoRule = MockitoJUnit.rule() + @JvmField @Rule val mockitoRule = MockitoJUnit.rule() private lateinit var unfoldWallpaperController: UnfoldTransitionWallpaperController @Before fun setup() { - unfoldWallpaperController = UnfoldTransitionWallpaperController(progressProvider, - wallpaperController) + unfoldWallpaperController = + UnfoldTransitionWallpaperController(progressProvider, wallpaperController) unfoldWallpaperController.init() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt index 2bc05fcc8166..e5f619b299a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt @@ -23,7 +23,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.utils.os.FakeHandler import kotlin.test.Test import kotlinx.coroutines.test.runTest @@ -34,7 +34,7 @@ import org.junit.runner.RunWith @RunWithLooper(setAsMainLooper = true) class MainThreadUnfoldTransitionProgressProviderTest : SysuiTestCase() { - private val wrappedProgressProvider = TestUnfoldTransitionProvider() + private val wrappedProgressProvider = FakeUnfoldTransitionProvider() private val fakeHandler = FakeHandler(Looper.getMainLooper()) private val listener = TestUnfoldProgressListener() diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt index d864d53fea32..70ec050afe1d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt @@ -20,7 +20,7 @@ import android.testing.TestableLooper import android.view.Surface import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.unfold.updates.RotationChangeProvider import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener @@ -43,14 +43,14 @@ class NaturalRotationUnfoldProgressProviderTest : SysuiTestCase() { @Mock lateinit var rotationChangeProvider: RotationChangeProvider - private val sourceProvider = TestUnfoldTransitionProvider() + private val sourceProvider = FakeUnfoldTransitionProvider() @Mock lateinit var transitionListener: TransitionProgressListener @Captor private lateinit var rotationListenerCaptor: ArgumentCaptor<RotationListener> lateinit var progressProvider: NaturalRotationUnfoldProgressProvider - private lateinit var testableLooper : TestableLooper + private lateinit var testableLooper: TestableLooper @Before fun setUp() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt index 2f29b3bdd3b5..451bd24dd83f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt @@ -22,7 +22,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.util.mockito.any import org.junit.Before @@ -42,7 +42,7 @@ class ScaleAwareUnfoldProgressProviderTest : SysuiTestCase() { @Mock lateinit var sinkProvider: TransitionProgressListener - private val sourceProvider = TestUnfoldTransitionProvider() + private val sourceProvider = FakeUnfoldTransitionProvider() private lateinit var contentResolver: ContentResolver private lateinit var progressProvider: ScaleAwareTransitionProgressProvider @@ -132,6 +132,6 @@ class ScaleAwareUnfoldProgressProviderTest : SysuiTestCase() { durationScale.toString() ) - animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */false) + animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */ false) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt index 95c934e988e7..4486402f43ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt @@ -23,7 +23,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.unfold.progress.TestUnfoldProgressListener import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds @@ -43,7 +43,7 @@ import org.junit.runner.RunWith @RunWithLooper class ScopedUnfoldTransitionProgressProviderTest : SysuiTestCase() { - private val rootProvider = TestUnfoldTransitionProvider() + private val rootProvider = FakeUnfoldTransitionProvider() private val listener = TestUnfoldProgressListener() private val testScope = TestScope(UnconfinedTestDispatcher()) private val bgThread = diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt index f484ea04bb4f..cd4d7b54916e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt @@ -19,7 +19,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.unfold.FakeUnfoldTransitionProvider import com.android.systemui.unfold.progress.TestUnfoldProgressListener import com.google.common.util.concurrent.MoreExecutors import org.junit.Before @@ -32,7 +32,7 @@ import org.junit.runner.RunWith class UnfoldOnlyProgressProviderTest : SysuiTestCase() { private val listener = TestUnfoldProgressListener() - private val sourceProvider = TestUnfoldTransitionProvider() + private val sourceProvider = FakeUnfoldTransitionProvider() private val foldProvider = TestFoldProvider() diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java index fb82b8fed76c..483dc0c9c974 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java @@ -15,14 +15,14 @@ */ package com.android.systemui.volume; +import static com.google.common.truth.Truth.assertThat; + import android.media.MediaMetadata; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import junit.framework.Assert; - import org.junit.Test; @SmallTest @@ -30,11 +30,59 @@ public class UtilTest extends SysuiTestCase { @Test public void testMediaMetadataToString_null() { - Assert.assertEquals(null, Util.mediaMetadataToString(null)); + assertThat(Util.mediaMetadataToString(null)).isNull(); } @Test public void testMediaMetadataToString_notNull() { - Assert.assertNotNull(Util.mediaMetadataToString(new MediaMetadata.Builder().build())); + assertThat(Util.mediaMetadataToString(new MediaMetadata.Builder().build())).isNotNull(); + } + + @Test + public void translateToRange_translatesStartToStart() { + assertThat( + (int) Util.translateToRange( + /* value= */ 0, + /* valueRangeStart= */ 0, + /* valueRangeEnd= */ 7, + /* targetRangeStart= */ 0, + /* targetRangeEnd= */700) + ).isEqualTo(0); + } + + @Test + public void translateToRange_translatesValueToValue() { + assertThat( + (int) Util.translateToRange( + /* value= */ 4, + /* valueRangeStart= */ 0, + /* valueRangeEnd= */ 7, + /* targetRangeStart= */ 0, + /* targetRangeEnd= */700) + ).isEqualTo(400); + } + + @Test + public void translateToRange_translatesEndToEnd() { + assertThat( + (int) Util.translateToRange( + /* value= */ 7, + /* valueRangeStart= */ 0, + /* valueRangeEnd= */ 7, + /* targetRangeStart= */ 0, + /* targetRangeEnd= */700) + ).isEqualTo(700); + } + + @Test + public void translateToRange_returnsStartForEmptyRange() { + assertThat( + (int) Util.translateToRange( + /* value= */ 7, + /* valueRangeStart= */ 7, + /* valueRangeEnd= */ 7, + /* targetRangeStart= */ 700, + /* targetRangeEnd= */700) + ).isEqualTo(700); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index 11a53f753b2a..3b468aa011ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -65,6 +65,7 @@ import android.widget.ImageButton; import android.widget.SeekBar; import androidx.test.core.view.MotionEventBuilder; +import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.internal.jank.InteractionJankMonitor; @@ -247,6 +248,8 @@ public class VolumeDialogImplTest extends SysuiTestCase { VolumeDialogController.StreamState ss = new VolumeDialogController.StreamState(); ss.name = STREAMS.get(i); ss.level = 1; + ss.levelMin = 0; + ss.levelMax = 25; state.states.append(i, ss); } return state; @@ -293,7 +296,7 @@ public class VolumeDialogImplTest extends SysuiTestCase { mTestableLooper.processAllMessages(); } - @Test + @Test @FlakyTest(bugId = 329099861) @EnableFlags(FLAG_HAPTIC_VOLUME_SLIDER) public void testVolumeChange_withSliderHaptics_deliversOnProgressChangedHapticsEagerly() { // create haptic plugins on the rows with the flag enabled diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index aabd4e9e79be..d9a0c4be04ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -121,8 +121,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.scene.FakeWindowRootViewComponent; import com.android.systemui.scene.data.repository.SceneContainerRepository; import com.android.systemui.scene.domain.interactor.SceneInteractor; -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; -import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.scene.shared.logger.SceneLogger; import com.android.systemui.settings.FakeDisplayTracker; import com.android.systemui.settings.UserTracker; @@ -174,6 +172,7 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor; import com.android.systemui.user.domain.interactor.UserSwitcherInteractor; import com.android.systemui.util.FakeEventLog; import com.android.systemui.util.settings.FakeGlobalSettings; +import com.android.systemui.util.settings.SystemSettings; import com.android.systemui.util.time.SystemClock; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.WindowManagerShellWrapper; @@ -359,8 +358,6 @@ public class BubblesTest extends SysuiTestCase { @Mock private Display mDefaultDisplay; @Mock - private SceneContainerFlags mSceneContainerFlags; - @Mock private LargeScreenHeaderHelper mLargeScreenHeaderHelper; private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); @@ -429,14 +426,12 @@ public class BubblesTest extends SysuiTestCase { mock(SceneLogger.class), mKosmos.getDeviceUnlockedInteractor()); - FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags(); KeyguardTransitionInteractor keyguardTransitionInteractor = mKosmos.getKeyguardTransitionInteractor(); KeyguardInteractor keyguardInteractor = new KeyguardInteractor( keyguardRepository, new FakeCommandQueue(), powerInteractor, - sceneContainerFlags, new FakeKeyguardBouncerRepository(), new ConfigurationInteractor(configurationRepository), shadeRepository, @@ -502,7 +497,6 @@ public class BubblesTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, - mSceneContainerFlags, mKosmos::getCommunalInteractor ); mNotificationShadeWindowController.fetchWindowRootView(); @@ -554,7 +548,8 @@ public class BubblesTest extends SysuiTestCase { mock(SystemClock.class), mock(UiEventLogger.class), mock(UserTracker.class), - mock(AvalancheProvider.class) + mock(AvalancheProvider.class), + mock(SystemSettings.class) ); interruptionDecisionProvider.start(); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt index 7185b7cd0ac6..96c4c45dbb91 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt @@ -18,5 +18,7 @@ package com.android.systemui import android.content.applicationContext import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock -val Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) } +val Kosmos.mockActivityIntentHelper by Kosmos.Fixture { mock<ActivityIntentHelper>() } +var Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt index de7b14d1e102..0682361823ee 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt @@ -31,7 +31,7 @@ import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfig import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor import com.android.systemui.scene.SceneContainerFrameworkModule -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneDataSource import com.android.systemui.scene.shared.model.SceneDataSourceDelegator @@ -104,11 +104,10 @@ interface SysUITestModule { @Provides fun provideBaseShadeInteractor( - sceneContainerFlags: SceneContainerFlags, sceneContainerOn: Provider<ShadeInteractorSceneContainerImpl>, sceneContainerOff: Provider<ShadeInteractorLegacyImpl> ): BaseShadeInteractor { - return if (sceneContainerFlags.isEnabled()) { + return if (SceneContainerFlag.isEnabled) { sceneContainerOn.get() } else { sceneContainerOff.get() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/FakeReduceBrightColorsController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/FakeReduceBrightColorsController.kt new file mode 100644 index 000000000000..8b0affe2d99d --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/FakeReduceBrightColorsController.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility + +import com.android.systemui.qs.ReduceBrightColorsController + +class FakeReduceBrightColorsController : ReduceBrightColorsController { + + private var isEnabled = false + + private val callbacks = LinkedHashSet<ReduceBrightColorsController.Listener>() + + override fun addCallback(listener: ReduceBrightColorsController.Listener) { + callbacks.add(listener) + } + + override fun removeCallback(listener: ReduceBrightColorsController.Listener) { + callbacks.remove(listener) + } + + override fun isReduceBrightColorsActivated(): Boolean { + return isEnabled + } + + override fun setReduceBrightColorsActivated(activated: Boolean) { + if (activated != isEnabled) { + isEnabled = activated + for (callback in callbacks) { + callback.onActivated(activated) + } + } + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/ReduceBrightColorsControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/ReduceBrightColorsControllerKosmos.kt new file mode 100644 index 000000000000..5bbe3bf24b4e --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/ReduceBrightColorsControllerKosmos.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.qs.ReduceBrightColorsController + +var Kosmos.reduceBrightColorsController: ReduceBrightColorsController by + Kosmos.Fixture { fakeReduceBrightColorsController } +val Kosmos.fakeReduceBrightColorsController by Kosmos.Fixture { FakeReduceBrightColorsController() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt index a6dd3cd7d30a..219794f3ad18 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt @@ -32,6 +32,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.currentTime @@ -68,6 +70,8 @@ class FakeAuthenticationRepository( var lockoutStartedReportCount = 0 + private val credentialCheckingMutex = Mutex(locked = false) + override suspend fun getAuthenticationMethod(): AuthenticationMethodModel { return authenticationMethod.value } @@ -124,30 +128,32 @@ class FakeAuthenticationRepository( override suspend fun checkCredential( credential: LockscreenCredential ): AuthenticationResultModel { - val expectedCredential = credentialOverride ?: getExpectedCredential(securityMode) - val isSuccessful = - when { - credential.type != getCurrentCredentialType(securityMode) -> false - credential.type == LockPatternUtils.CREDENTIAL_TYPE_PIN -> - credential.isPin && credential.matches(expectedCredential) - credential.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD -> - credential.isPassword && credential.matches(expectedCredential) - credential.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN -> - credential.isPattern && credential.matches(expectedCredential) - else -> error("Unexpected credential type ${credential.type}!") + return credentialCheckingMutex.withLock { + val expectedCredential = credentialOverride ?: getExpectedCredential(securityMode) + val isSuccessful = + when { + credential.type != getCurrentCredentialType(securityMode) -> false + credential.type == LockPatternUtils.CREDENTIAL_TYPE_PIN -> + credential.isPin && credential.matches(expectedCredential) + credential.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD -> + credential.isPassword && credential.matches(expectedCredential) + credential.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN -> + credential.isPattern && credential.matches(expectedCredential) + else -> error("Unexpected credential type ${credential.type}!") + } + + val failedAttempts = _failedAuthenticationAttempts.value + if (isSuccessful || failedAttempts < MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) { + AuthenticationResultModel( + isSuccessful = isSuccessful, + lockoutDurationMs = 0, + ) + } else { + AuthenticationResultModel( + isSuccessful = false, + lockoutDurationMs = LOCKOUT_DURATION_MS, + ) } - - val failedAttempts = _failedAuthenticationAttempts.value - return if (isSuccessful || failedAttempts < MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) { - AuthenticationResultModel( - isSuccessful = isSuccessful, - lockoutDurationMs = 0, - ) - } else { - AuthenticationResultModel( - isSuccessful = false, - lockoutDurationMs = LOCKOUT_DURATION_MS, - ) } } @@ -155,6 +161,23 @@ class FakeAuthenticationRepository( _isPinEnhancedPrivacyEnabled.value = isEnabled } + /** + * Pauses any future credential checking. The test must call [unpauseCredentialChecking] to + * flush the accumulated credential checks. + */ + suspend fun pauseCredentialChecking() { + credentialCheckingMutex.lock() + } + + /** + * Unpauses future credential checking, if it was paused using [pauseCredentialChecking]. This + * doesn't flush any pending coroutine jobs; the test code may still choose to do that using + * `runCurrent`. + */ + fun unpauseCredentialChecking() { + credentialCheckingMutex.unlock() + } + private fun getExpectedCredential(securityMode: SecurityMode): List<Any> { return when (val credentialType = getCurrentCredentialType(securityMode)) { LockPatternUtils.CREDENTIAL_TYPE_PIN -> credentialOverride ?: DEFAULT_PIN diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt index 9cbe6337befe..2ae6f542ac3e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt @@ -17,6 +17,7 @@ package com.android.systemui.biometrics.ui.viewmodel import android.content.applicationContext +import com.android.systemui.biometrics.domain.interactor.biometricStatusInteractor import com.android.systemui.biometrics.domain.interactor.displayStateInteractor import com.android.systemui.biometrics.domain.interactor.promptSelectorInteractor import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor @@ -30,6 +31,7 @@ val Kosmos.promptViewModel by Fixture { promptSelectorInteractor = promptSelectorInteractor, context = applicationContext, udfpsOverlayInteractor = udfpsOverlayInteractor, + biometricStatusInteractor = biometricStatusInteractor, udfpsUtils = udfpsUtils ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt index 979d8e76f3ee..e9d72664c6b0 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.scene.shared.flag +package com.android.systemui.bluetooth import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock -var Kosmos.fakeSceneContainerFlags by Kosmos.Fixture { FakeSceneContainerFlags() } -val Kosmos.sceneContainerFlags by Kosmos.Fixture<SceneContainerFlags> { fakeSceneContainerFlags } +val Kosmos.mockBroadcastDialogController by Kosmos.Fixture { mock<BroadcastDialogController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt index c06554573bd7..4a02f6ddbebd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.bouncer.domain.interactor +import com.android.internal.logging.uiEventLogger import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.bouncer.data.repository.bouncerRepository import com.android.systemui.classifier.domain.interactor.falsingInteractor @@ -23,7 +24,9 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInt import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.testScope +import com.android.systemui.log.sessionTracker import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.scene.domain.interactor.sceneInteractor val Kosmos.bouncerInteractor by Fixture { BouncerInteractor( @@ -33,5 +36,8 @@ val Kosmos.bouncerInteractor by Fixture { deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor, falsingInteractor = falsingInteractor, powerInteractor = powerInteractor, + uiEventLogger = uiEventLogger, + sessionTracker = sessionTracker, + sceneInteractor = sceneInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt index 5c3e1f410e63..60d97d1b1437 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt @@ -17,8 +17,6 @@ package com.android.systemui.bouncer.shared.flag import com.android.systemui.kosmos.Kosmos -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags -var Kosmos.fakeComposeBouncerFlags by - Kosmos.Fixture { FakeComposeBouncerFlags(fakeSceneContainerFlags) } +var Kosmos.fakeComposeBouncerFlags by Kosmos.Fixture { FakeComposeBouncerFlags() } val Kosmos.composeBouncerFlags by Kosmos.Fixture<ComposeBouncerFlags> { fakeComposeBouncerFlags } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt index c116bbd32f9e..7482c0feb56a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt @@ -16,14 +16,11 @@ package com.android.systemui.bouncer.shared.flag -import com.android.systemui.scene.shared.flag.SceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlag -class FakeComposeBouncerFlags( - private val sceneContainerFlags: SceneContainerFlags, - var composeBouncerEnabled: Boolean = false -) : ComposeBouncerFlags { +class FakeComposeBouncerFlags(var composeBouncerEnabled: Boolean = false) : ComposeBouncerFlags { override fun isComposeBouncerOrSceneContainerEnabled(): Boolean { - return sceneContainerFlags.isEnabled() || composeBouncerEnabled + return SceneContainerFlag.isEnabled || composeBouncerEnabled } @Deprecated( diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt index 0f6c7cf13211..c3dad748064d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt @@ -18,6 +18,7 @@ package com.android.systemui.bouncer.ui.viewmodel +import android.app.admin.devicePolicyManager import android.content.applicationContext import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor @@ -31,7 +32,6 @@ import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.user.domain.interactor.selectedUserInteractor import com.android.systemui.user.ui.viewmodel.userSwitcherViewModel -import com.android.systemui.util.mockito.mock import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.bouncerViewModel by Fixture { @@ -44,12 +44,12 @@ val Kosmos.bouncerViewModel by Fixture { simBouncerInteractor = simBouncerInteractor, authenticationInteractor = authenticationInteractor, selectedUserInteractor = selectedUserInteractor, + devicePolicyManager = devicePolicyManager, + bouncerMessageViewModel = bouncerMessageViewModel, flags = composeBouncerFlags, selectedUser = userSwitcherViewModel.selectedUser, users = userSwitcherViewModel.users, userSwitcherMenu = userSwitcherViewModel.menu, actionButton = bouncerActionButtonInteractor.actionButton, - devicePolicyManager = mock(), - bouncerMessageViewModel = bouncerMessageViewModel, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt index 8866fd31faac..3dd382f6db3e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt @@ -23,6 +23,7 @@ import com.android.systemui.communal.data.repository.communalPrefsRepository import com.android.systemui.communal.data.repository.communalRepository import com.android.systemui.communal.data.repository.communalWidgetRepository import com.android.systemui.communal.widgets.EditWidgetsActivityStarter +import com.android.systemui.dock.fakeDockManager import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository @@ -33,7 +34,6 @@ import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.log.logcatLogBuffer import com.android.systemui.plugins.activityStarter import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.settings.userTracker import com.android.systemui.smartspace.data.repository.smartspaceRepository import com.android.systemui.user.data.repository.fakeUserRepository @@ -45,20 +45,20 @@ val Kosmos.communalInteractor by Fixture { broadcastDispatcher = broadcastDispatcher, communalRepository = communalRepository, widgetRepository = communalWidgetRepository, - mediaRepository = communalMediaRepository, communalPrefsRepository = communalPrefsRepository, + mediaRepository = communalMediaRepository, smartspaceRepository = smartspaceRepository, - appWidgetHost = mock(), keyguardInteractor = keyguardInteractor, + communalSettingsInteractor = communalSettingsInteractor, + appWidgetHost = mock(), editWidgetsActivityStarter = editWidgetsActivityStarter, userTracker = userTracker, activityStarter = activityStarter, userManager = userManager, + dockManager = fakeDockManager, + sceneInteractor = sceneInteractor, logBuffer = logcatLogBuffer("CommunalInteractor"), tableLogBuffer = mock(), - communalSettingsInteractor = communalSettingsInteractor, - sceneInteractor = sceneInteractor, - sceneContainerFlags = fakeSceneContainerFlags, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt index b4773f69f1c5..cd2710ef8757 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt @@ -17,17 +17,21 @@ package com.android.systemui.communal.domain.interactor import com.android.systemui.communal.data.repository.communalSettingsRepository +import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.settings.userTracker import com.android.systemui.user.domain.interactor.selectedUserInteractor import com.android.systemui.util.mockito.mock val Kosmos.communalSettingsInteractor by Fixture { CommunalSettingsInteractor( bgScope = applicationCoroutineScope, + bgExecutor = fakeExecutor, repository = communalSettingsRepository, userInteractor = selectedUserInteractor, + userTracker = userTracker, tableLogBuffer = mock(), ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt index 23967224e43a..e36ddc17e5a8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt @@ -16,6 +16,8 @@ package com.android.systemui.communal.ui.viewmodel +import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.ui.viewmodel.dreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToDreamingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel @@ -27,9 +29,13 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.communalTransitionViewModel by Kosmos.Fixture { CommunalTransitionViewModel( - glanceableHubToLockscreenTransitionViewModel, - lockscreenToGlanceableHubTransitionViewModel, - dreamingToGlanceableHubTransitionViewModel, - glanceableHubToDreamingTransitionViewModel, + glanceableHubToLockscreenTransitionViewModel = + glanceableHubToLockscreenTransitionViewModel, + lockscreenToGlanceableHubTransitionViewModel = + lockscreenToGlanceableHubTransitionViewModel, + dreamToGlanceableHubTransitionViewModel = dreamingToGlanceableHubTransitionViewModel, + glanceableHubToDreamTransitionViewModel = glanceableHubToDreamingTransitionViewModel, + communalInteractor = communalInteractor, + keyguardTransitionInteractor = keyguardTransitionInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt index 0fc0a3c20f70..6c3cf91ec751 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt @@ -23,6 +23,8 @@ import dagger.Module import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import org.mockito.Mockito.`when` as whenever /** Creates a mock display. */ @@ -69,12 +71,20 @@ class FakeDisplayRepository @Inject constructor() : DisplayRepository { override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?> get() = pendingDisplayFlow + val _defaultDisplayOff: MutableStateFlow<Boolean> = MutableStateFlow(false) + override val defaultDisplayOff: Flow<Boolean> + get() = _defaultDisplayOff.asStateFlow() + override val displayAdditionEvent: Flow<Display?> get() = displayAdditionEventFlow private val _displayChangeEvent = MutableSharedFlow<Int>(replay = 1) override val displayChangeEvent: Flow<Int> = _displayChangeEvent suspend fun emitDisplayChangeEvent(displayId: Int) = _displayChangeEvent.emit(displayId) + + fun setDefaultDisplayOff(defaultDisplayOff: Boolean) { + _defaultDisplayOff.value = defaultDisplayOff + } } @Module diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFake.java index 37540621557f..b99310bcbe38 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFake.java @@ -49,6 +49,7 @@ public class DockManagerFake implements DockManager { return mDocked; } + /** Sets the docked state */ public void setIsDocked(boolean docked) { mDocked = docked; } @@ -58,6 +59,7 @@ public class DockManagerFake implements DockManager { return false; } + /** Notifies callbacks of dock state change */ public void setDockEvent(int event) { mCallback.onEvent(event); } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFakeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFakeKosmos.kt index 06275fa226a5..06275fa226a5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFakeKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFakeKosmos.kt diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/BrokenWithSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/BrokenWithSceneContainer.kt new file mode 100644 index 000000000000..29b088b0afc1 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/BrokenWithSceneContainer.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER + +/** + * This is used by [SceneContainerRule] to assert that the test is broken when + * [FLAG_SCENE_CONTAINER] is enabled. + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +annotation class BrokenWithSceneContainer(val bugId: Int) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/DisableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/DisableSceneContainer.kt new file mode 100644 index 000000000000..09f34308bdb9 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/DisableSceneContainer.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import android.platform.test.annotations.DisableFlags +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER + +/** + * This includes @[DisableFlags] to work with [SetFlagsRule] to disable all aconfig flags required + * by that feature. + */ +@DisableFlags( + FLAG_SCENE_CONTAINER, +) +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +annotation class DisableSceneContainer diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt index c1d2ad6e1be3..e83205c5a859 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt @@ -18,12 +18,14 @@ package com.android.systemui.flags import android.platform.test.annotations.EnableFlags import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN +import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR import com.android.systemui.Flags.FLAG_MEDIA_IN_SCENE_CONTAINER import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT import com.android.systemui.Flags.FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR import com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_SYSUI +import com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT import com.android.systemui.Flags.FLAG_SCENE_CONTAINER /** @@ -39,6 +41,8 @@ import com.android.systemui.Flags.FLAG_SCENE_CONTAINER FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR, FLAG_PREDICTIVE_BACK_SYSUI, FLAG_SCENE_CONTAINER, + FLAG_DEVICE_ENTRY_UDFPS_REFACTOR, + FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT, ) @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt index d6f2f77ca67a..45ea36464194 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt @@ -34,8 +34,9 @@ val Kosmos.fakeFeatureFlagsClassic by Kosmos.Fixture { FakeFeatureFlagsClassic().apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) - set(Flags.NSSL_DEBUG_LINES, false) set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false) + set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false) + set(Flags.NSSL_DEBUG_LINES, false) } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt new file mode 100644 index 000000000000..4e24233a6681 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.FlagsParameterization +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER + +/** The name of the one flag to be disabled for OFF parameterization */ +private const val flagNameToDisable = FLAG_SCENE_CONTAINER + +/** Cache of the flags to be enabled for ON parameterization */ +private val flagNamesToEnable = + EnableSceneContainer::class.java.getAnnotation(EnableFlags::class.java)!!.value.toList() + +/** + * Provides one or two copies of this [FlagsParameterization]; one which disabled + * [FLAG_SCENE_CONTAINER] and if none of the dependencies of it are disabled by this, a second copy + * which enables [FLAG_SCENE_CONTAINER] and all the dependencies (just like [EnableSceneContainer]). + */ +fun FlagsParameterization.andSceneContainer(): Sequence<FlagsParameterization> = sequence { + check(flagNameToDisable !in mOverrides) { + "Can't add $flagNameToDisable to FlagsParameterization: $this" + } + yield(FlagsParameterization(mOverrides + mapOf(flagNameToDisable to false))) + if (flagNamesToEnable.all { mOverrides[it] != false }) { + // Can't add the parameterization of enabling SceneContainerFlag to a parameterization that + // explicitly disables one of the prerequisite flags. + yield(FlagsParameterization(mOverrides + flagNamesToEnable.associateWith { true })) + } +} + +/** + * Doubles (roughly; see below) the given list of [FlagsParameterization] for enabling and disabling + * SceneContainerFlag. + * + * The input parameterization may not define [FLAG_SCENE_CONTAINER]. + * + * Any [FlagsParameterization] which disables any flag that is a dependency of + * [FLAG_SCENE_CONTAINER], will not add a state for enabling, and the state will simply be converted + * to one which disables. Just like [EnableSceneContainer], enabling will also enable all the other + * dependencies. For any flag parameterization where a dependency is disabled, an "enabled" + * parameterization is inconsistent, so it will not be added. + */ +fun List<FlagsParameterization>.andSceneContainer(): List<FlagsParameterization> = + flatMap { it.andSceneContainer() }.toList() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt index 775ad14d4ad9..9ec1481355a5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt @@ -18,6 +18,7 @@ package com.android.systemui.flags import com.android.systemui.scene.shared.flag.SceneContainerFlag import org.junit.Assert +import org.junit.AssumptionViolatedException import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement @@ -33,10 +34,7 @@ class SceneContainerRule : TestRule { return object : Statement() { @Throws(Throwable::class) override fun evaluate() { - val hasAnnotation = - description?.testClass?.getAnnotation(EnableSceneContainer::class.java) != - null || description?.getAnnotation(EnableSceneContainer::class.java) != null - if (hasAnnotation) { + if (description.hasAnnotation<EnableSceneContainer>()) { Assert.assertTrue( "SceneContainerFlag.isEnabled is false:" + "\n * Did you forget to add a new aconfig flag dependency in" + @@ -45,8 +43,31 @@ class SceneContainerRule : TestRule { SceneContainerFlag.isEnabled ) } + if ( + description.hasAnnotation<BrokenWithSceneContainer>() && + SceneContainerFlag.isEnabled + ) { + runCatching { base?.evaluate() } + .onFailure { exception -> + if (exception is AssumptionViolatedException) { + throw AssertionError( + "This is marked @BrokenWithSceneContainer, but was skipped.", + exception + ) + } + throw AssumptionViolatedException("Test is still broken", exception) + } + throw AssertionError( + "HOORAY! You fixed a test that was marked @BrokenWithSceneContainer. " + + "Remove the obsolete annotation to fix this failure." + ) + } base?.evaluate() } } } + + inline fun <reified T : Annotation> Description?.hasAnnotation(): Boolean = + this?.testClass?.getAnnotation(T::class.java) != null || + this?.getAnnotation(T::class.java) != null } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt new file mode 100644 index 000000000000..636d509663a2 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.haptics.qs + +import com.android.systemui.haptics.vibratorHelper +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope + +val Kosmos.qsLongPressEffect by + Kosmos.Fixture { QSLongPressEffect(vibratorHelper, keyguardInteractor, testScope) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt index eba5a11cecdb..4f2310f9972d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt @@ -50,14 +50,25 @@ class FakeKeyguardClockRepository @Inject constructor() : KeyguardClockRepositor get() = _previewClock override val clockEventController: ClockEventController get() = mock() + override val shouldForceSmallClock: Boolean + get() = _shouldForceSmallClock + private var _shouldForceSmallClock: Boolean = false override fun setClockSize(@ClockSize size: Int) { _clockSize.value = size } + fun setSelectedClockSize(size: SettingsClockSize) { + selectedClockSize.value = size + } + fun setCurrentClock(clockController: ClockController) { _currentClock.value = clockController } + + fun setShouldForceSmallClock(shouldForceSmallClock: Boolean) { + _shouldForceSmallClock = shouldForceSmallClock + } } @Module diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt index 75489b617120..8954231a9731 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt @@ -17,8 +17,6 @@ package com.android.systemui.keyguard.data.repository import android.os.fakeExecutorHandler -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.shared.model.KeyguardSection import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT @@ -34,8 +32,6 @@ val Kosmos.keyguardBlueprintRepository by setOf( defaultBlueprint, splitShadeBlueprint, - weatherClockBlueprint, - splitShadeWeatherClockBlueprint, ), handler = fakeExecutorHandler, assert = mock<ThreadAssert>(), @@ -50,22 +46,6 @@ private val defaultBlueprint = get() = listOf() } -private val weatherClockBlueprint = - object : KeyguardBlueprint { - override val id: String - get() = WEATHER_CLOCK_BLUEPRINT_ID - override val sections: List<KeyguardSection> - get() = listOf() - } - -private val splitShadeWeatherClockBlueprint = - object : KeyguardBlueprint { - override val id: String - get() = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID - override val sections: List<KeyguardSection> - get() = listOf() - } - private val splitShadeBlueprint = object : KeyguardBlueprint { override val id: String diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt index 12165cdc5658..d52883eb38af 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt @@ -18,6 +18,22 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.keyguard.data.repository.keyguardClockRepository import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor +import com.android.systemui.shade.domain.interactor.shadeInteractor +import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor +import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor val Kosmos.keyguardClockInteractor by - Kosmos.Fixture { KeyguardClockInteractor(keyguardClockRepository) } + Kosmos.Fixture { + KeyguardClockInteractor( + keyguardClockRepository = keyguardClockRepository, + applicationScope = applicationCoroutineScope, + mediaCarouselInteractor = mediaCarouselInteractor, + activeNotificationsInteractor = activeNotificationsInteractor, + shadeInteractor = shadeInteractor, + keyguardInteractor = keyguardInteractor, + keyguardTransitionInteractor = keyguardTransitionInteractor, + headsUpNotificationInteractor = headsUpNotificationInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt new file mode 100644 index 000000000000..2c6d44f10152 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.domain.interactor + +import com.android.systemui.keyguard.data.repository.keyguardRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.keyguardDismissActionInteractor by + Kosmos.Fixture { + KeyguardDismissActionInteractor( + repository = keyguardRepository, + transitionInteractor = keyguardTransitionInteractor, + dismissInteractor = keyguardDismissInteractor, + applicationScope = testScope.backgroundScope, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt new file mode 100644 index 000000000000..f33ca95e488d --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.domain.interactor + +import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.keyguard.data.repository.keyguardRepository +import com.android.systemui.keyguard.data.repository.trustRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.user.domain.interactor.selectedUserInteractor +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.keyguardDismissInteractor by + Kosmos.Fixture { + KeyguardDismissInteractor( + trustRepository = trustRepository, + keyguardRepository = keyguardRepository, + primaryBouncerInteractor = primaryBouncerInteractor, + alternateBouncerInteractor = alternateBouncerInteractor, + powerInteractor = powerInteractor, + selectedUserInteractor = selectedUserInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt index e21c76672c1d..2e751cce7bad 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt @@ -24,12 +24,9 @@ import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.shared.model.KeyguardState -import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.domain.interactor.SceneInteractor -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags -import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor.ConfigurationBasedDimensions @@ -49,7 +46,6 @@ object KeyguardInteractorFactory { @JvmStatic fun create( featureFlags: FakeFeatureFlags = FakeFeatureFlags(), - sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(), repository: FakeKeyguardRepository = FakeKeyguardRepository(), commandQueue: FakeCommandQueue = FakeCommandQueue(), bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(), @@ -88,7 +84,6 @@ object KeyguardInteractorFactory { repository = repository, commandQueue = commandQueue, featureFlags = featureFlags, - sceneContainerFlags = sceneContainerFlags, bouncerRepository = bouncerRepository, configurationRepository = configurationRepository, shadeRepository = shadeRepository, @@ -96,13 +91,12 @@ object KeyguardInteractorFactory { KeyguardInteractor( repository = repository, commandQueue = commandQueue, - sceneContainerFlags = sceneContainerFlags, + powerInteractor = powerInteractor, bouncerRepository = bouncerRepository, configurationInteractor = ConfigurationInteractor(configurationRepository), shadeRepository = shadeRepository, - sceneInteractorProvider = { sceneInteractor }, keyguardTransitionInteractor = keyguardTransitionInteractor, - powerInteractor = powerInteractor, + sceneInteractorProvider = { sceneInteractor }, fromGoneTransitionInteractor = { fromGoneTransitionInteractor }, sharedNotificationContainerInteractor = { sncInteractor }, applicationScope = testScope, @@ -114,7 +108,6 @@ object KeyguardInteractorFactory { val repository: FakeKeyguardRepository, val commandQueue: FakeCommandQueue, val featureFlags: FakeFeatureFlags, - val sceneContainerFlags: SceneContainerFlags, val bouncerRepository: FakeKeyguardBouncerRepository, val configurationRepository: FakeConfigurationRepository, val shadeRepository: FakeShadeRepository, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt index 2a0c01c5c0af..94267189e179 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt @@ -23,7 +23,6 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.statusbar.commandQueue import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor @@ -34,7 +33,6 @@ val Kosmos.keyguardInteractor: KeyguardInteractor by repository = keyguardRepository, commandQueue = commandQueue, powerInteractor = powerInteractor, - sceneContainerFlags = sceneContainerFlags, bouncerRepository = keyguardBouncerRepository, configurationInteractor = configurationInteractor, shadeRepository = shadeRepository, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt index 185deda950c6..6cc1e8eba73d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt @@ -20,13 +20,11 @@ import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope -import com.android.systemui.kosmos.testDispatcher val Kosmos.keyguardTransitionInteractor: KeyguardTransitionInteractor by Kosmos.Fixture { KeyguardTransitionInteractor( scope = applicationCoroutineScope, - mainDispatcher = testDispatcher, repository = keyguardTransitionRepository, keyguardRepository = keyguardRepository, fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor }, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt index f7de5a4c20c7..1a05d21cc30a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt @@ -22,14 +22,10 @@ import com.android.keyguard.logging.keyguardTransitionAnimationLogger import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.kosmos.applicationCoroutineScope -import com.android.systemui.kosmos.testDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.keyguardTransitionAnimationFlow by Fixture { KeyguardTransitionAnimationFlow( - scope = applicationCoroutineScope, - mainDispatcher = testDispatcher, transitionInteractor = keyguardTransitionInteractor, logger = keyguardTransitionAnimationLogger, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt index ffa4133c7269..9774e4aa51a5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt @@ -19,21 +19,19 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor -import com.android.systemui.flags.featureFlagsClassic +import com.android.systemui.keyguard.domain.interactor.keyguardDismissActionInteractor import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.statusbar.sysuiStatusBarStateController -import com.android.systemui.util.mockito.mock import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.bouncerToGoneFlows by Fixture { BouncerToGoneFlows( statusBarStateController = sysuiStatusBarStateController, primaryBouncerInteractor = mockPrimaryBouncerInteractor, - keyguardDismissActionInteractor = mock(), - featureFlags = featureFlagsClassic, + keyguardDismissActionInteractor = { keyguardDismissActionInteractor }, shadeInteractor = shadeInteractor, animationFlow = keyguardTransitionAnimationFlow, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt index 709f86426f94..58b0ff8513f5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt @@ -26,7 +26,6 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.testScope -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -47,7 +46,6 @@ val Kosmos.deviceEntryIconViewModel by Fixture { transitionInteractor = keyguardTransitionInteractor, keyguardInteractor = keyguardInteractor, viewModel = aodToLockscreenTransitionViewModel, - sceneContainerFlags = sceneContainerFlags, keyguardViewController = { statusBarKeyguardViewManager }, deviceEntryInteractor = deviceEntryInteractor, deviceEntrySourceInteractor = deviceEntrySourceInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt index 60dd48aeaf61..a048d3cfffca 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt @@ -17,7 +17,6 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor -import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.shade.domain.interactor.shadeInteractor @@ -26,7 +25,6 @@ import com.android.systemui.statusbar.notification.stack.domain.interactor.notif val Kosmos.keyguardClockViewModel by Kosmos.Fixture { KeyguardClockViewModel( - keyguardInteractor = keyguardInteractor, keyguardClockInteractor = keyguardClockInteractor, applicationScope = applicationCoroutineScope, notifsKeyguardInteractor = notificationsKeyguardInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..3b96912b53c6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModelKosmos.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +var Kosmos.occludedToGoneTransitionViewModel by Fixture { + OccludedToGoneTransitionViewModel( + animationFlow = keyguardTransitionAnimationFlow, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt index e6651a44236f..f86e9b7216ce 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt @@ -20,6 +20,8 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture @@ -30,5 +32,7 @@ var Kosmos.occludedToLockscreenTransitionViewModel by Fixture { deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor, configurationInteractor = configurationInteractor, animationFlow = keyguardTransitionAnimationFlow, + keyguardInteractor = keyguardInteractor, + keyguardTransitionInteractor = keyguardTransitionInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt index 4ecff73f71ed..d6edea29d6f0 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt @@ -19,20 +19,18 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor -import com.android.systemui.flags.featureFlagsClassic +import com.android.systemui.keyguard.domain.interactor.keyguardDismissActionInteractor import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.statusbar.sysuiStatusBarStateController -import com.android.systemui.util.mockito.mock import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.primaryBouncerToGoneTransitionViewModel by Fixture { PrimaryBouncerToGoneTransitionViewModel( statusBarStateController = sysuiStatusBarStateController, primaryBouncerInteractor = mockPrimaryBouncerInteractor, - keyguardDismissActionInteractor = mock(), - featureFlags = featureFlagsClassic, + keyguardDismissActionInteractor = { keyguardDismissActionInteractor }, bouncerToGoneFlows = bouncerToGoneFlows, animationFlow = keyguardTransitionAnimationFlow, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt index afc8f309f6d2..162f278b7a8f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt @@ -33,6 +33,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.globalactions.domain.interactor.globalActionsInteractor +import com.android.systemui.haptics.qs.qsLongPressEffect import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository @@ -47,9 +48,9 @@ import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.sceneContainerConfig -import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags import com.android.systemui.scene.shared.model.sceneDataSource import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor +import com.android.systemui.shade.shadeController import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.statusbar.phone.screenOffAnimationController import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository @@ -69,7 +70,6 @@ class KosmosJavaAdapter( val testDispatcher by lazy { kosmos.testDispatcher } val testScope by lazy { kosmos.testScope } val fakeFeatureFlags by lazy { kosmos.fakeFeatureFlagsClassic } - val fakeSceneContainerFlags by lazy { kosmos.fakeSceneContainerFlags } val fakeExecutor by lazy { kosmos.fakeExecutor } val fakeExecutorHandler by lazy { kosmos.fakeExecutorHandler } val configurationRepository by lazy { kosmos.fakeConfigurationRepository } @@ -108,6 +108,8 @@ class KosmosJavaAdapter( kosmos.sharedNotificationContainerInteractor } val brightnessMirrorShowingInteractor by lazy { kosmos.brightnessMirrorShowingInteractor } + val qsLongPressEffect by lazy { kosmos.qsLongPressEffect } + val shadeController by lazy { kosmos.shadeController } init { kosmos.applicationContext = testCase.context diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/log/SessionTrackerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/SessionTrackerKosmos.kt new file mode 100644 index 000000000000..eac91497dd06 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/SessionTrackerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.log + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +val Kosmos.sessionTracker: SessionTracker by Kosmos.Fixture { sessionTrackerMock } +val Kosmos.sessionTrackerMock: SessionTracker by Kosmos.Fixture { mock() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt index 7ce810eb7818..7dab5c24a52f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt @@ -17,5 +17,6 @@ package com.android.systemui.media.controls.data.repository import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.time.systemClock -val Kosmos.mediaFilterRepository by Kosmos.Fixture { MediaFilterRepository() } +val Kosmos.mediaFilterRepository by Kosmos.Fixture { MediaFilterRepository(systemClock) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt index 29c5bd5dd1d4..81adefa11c9b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt @@ -16,16 +16,30 @@ package com.android.systemui.media.controls.domain.pipeline.interactor +import android.content.applicationContext +import com.android.systemui.activityIntentHelper +import com.android.systemui.bluetooth.mockBroadcastDialogController import com.android.systemui.kosmos.Kosmos import com.android.systemui.media.controls.data.repository.mediaFilterRepository import com.android.systemui.media.controls.domain.pipeline.mediaDataProcessor import com.android.systemui.media.controls.util.mediaInstanceId +import com.android.systemui.media.mediaOutputDialogManager +import com.android.systemui.plugins.activityStarter +import com.android.systemui.statusbar.notificationLockscreenUserManager +import com.android.systemui.statusbar.policy.keyguardStateController val Kosmos.mediaControlInteractor by Kosmos.Fixture { MediaControlInteractor( + applicationContext = applicationContext, instanceId = mediaInstanceId, repository = mediaFilterRepository, mediaDataProcessor = mediaDataProcessor, + keyguardStateController = keyguardStateController, + activityStarter = activityStarter, + activityIntentHelper = activityIntentHelper, + lockscreenUserManager = notificationLockscreenUserManager, + mediaOutputDialogManager = mediaOutputDialogManager, + broadcastDialogController = mockBroadcastDialogController, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt new file mode 100644 index 000000000000..2f3d3c3e0489 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.ui.viewmodel + +import android.content.applicationContext +import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaControlInteractor +import com.android.systemui.media.controls.util.mediaUiEventLogger + +val Kosmos.mediaControlViewModel by + Kosmos.Fixture { + MediaControlViewModel( + applicationContext = applicationContext, + backgroundDispatcher = testDispatcher, + backgroundExecutor = fakeExecutor, + interactor = mediaControlInteractor, + logger = mediaUiEventLogger, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt index 6f652f224975..e88d22a0e0cd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt @@ -18,9 +18,5 @@ package com.android.systemui.media.controls.util import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.kosmos.Kosmos -import com.android.systemui.scene.shared.flag.sceneContainerFlags -val Kosmos.mediaFlags by - Kosmos.Fixture { - MediaFlags(featureFlags = featureFlagsClassic, sceneContainerFlags = sceneContainerFlags) - } +val Kosmos.mediaFlags by Kosmos.Fixture { MediaFlags(featureFlags = featureFlagsClassic) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/reducebrightness/ReduceBrightColorsTileKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/reducebrightness/ReduceBrightColorsTileKosmos.kt new file mode 100644 index 000000000000..339f3bb4b213 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/reducebrightness/ReduceBrightColorsTileKosmos.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.impl.reducebrightness + +import com.android.systemui.accessibility.qs.QSAccessibilityModule +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.qs.qsEventLogger + +val Kosmos.qsReduceBrightColorsTileConfig by + Kosmos.Fixture { QSAccessibilityModule.provideReduceBrightColorsTileConfig(qsEventLogger) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt deleted file mode 100644 index bae5257a98bd..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2023 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.systemui.scene.shared.flag - -import dagger.Binds -import dagger.Module -import dagger.Provides - -class FakeSceneContainerFlags( - var enabled: Boolean = false, -) : SceneContainerFlags { - - override fun isEnabled(): Boolean { - return enabled - } - - override fun requirementDescription(): String { - return "" - } -} - -@Module(includes = [FakeSceneContainerFlagsModule.Bindings::class]) -class FakeSceneContainerFlagsModule( - @get:Provides val sceneContainerFlags: FakeSceneContainerFlags = FakeSceneContainerFlags(), -) { - @Module - interface Bindings { - @Binds fun bindFake(fake: FakeSceneContainerFlags): SceneContainerFlags - } -} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt index 07e2d6b0334c..543d5b6f8857 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt @@ -23,7 +23,6 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.shade.ShadeModule import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.statusbar.disableflags.data.repository.disableFlagsRepository @@ -36,7 +35,6 @@ import com.android.systemui.user.domain.interactor.userSwitcherInteractor var Kosmos.baseShadeInteractor: BaseShadeInteractor by Kosmos.Fixture { ShadeModule.provideBaseShadeInteractor( - sceneContainerFlags = sceneContainerFlags, sceneContainerOn = { shadeInteractorSceneContainerImpl }, sceneContainerOff = { shadeInteractorLegacyImpl }, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt new file mode 100644 index 000000000000..8d653f7212aa --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 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.systemui.shade.ui.viewmodel + +import android.content.applicationContext +import com.android.systemui.broadcast.broadcastDispatcher +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.plugins.activityStarter +import com.android.systemui.shade.domain.interactor.privacyChipInteractor +import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor +import com.android.systemui.shade.domain.interactor.shadeInteractor +import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.mobileIconsInteractor +import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.mobileIconsViewModel + +val Kosmos.shadeHeaderViewModel: ShadeHeaderViewModel by + Kosmos.Fixture { + ShadeHeaderViewModel( + applicationScope = applicationCoroutineScope, + context = applicationContext, + activityStarter = activityStarter, + shadeInteractor = shadeInteractor, + mobileIconsInteractor = mobileIconsInteractor, + mobileIconsViewModel = mobileIconsViewModel, + privacyChipInteractor = privacyChipInteractor, + clockInteractor = shadeHeaderClockInteractor, + broadcastDispatcher = broadcastDispatcher, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt index 165c9429c917..dc1b9feea88f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt @@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.MutableStateFlow val Kosmos.headsUpNotificationRepository by Fixture { FakeHeadsUpNotificationRepository() } class FakeHeadsUpNotificationRepository : HeadsUpRepository { - override val headsUpAnimatingAway: MutableStateFlow<Boolean> = MutableStateFlow(false) + override val isHeadsUpAnimatingAway: MutableStateFlow<Boolean> = MutableStateFlow(false) override val topHeadsUpRow: Flow<HeadsUpRowRepository?> = MutableStateFlow(null) override val activeHeadsUpRows: MutableStateFlow<Set<HeadsUpRowRepository>> = MutableStateFlow(emptySet()) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt index b2492110f849..f0eea386ecdb 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt @@ -21,7 +21,6 @@ import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor @@ -30,7 +29,6 @@ val Kosmos.notificationsPlaceholderViewModel by Fixture { dumpManager = dumpManager, interactor = notificationStackAppearanceInteractor, shadeInteractor = shadeInteractor, - flags = sceneContainerFlags, featureFlags = featureFlagsClassic, keyguardInteractor = keyguardInteractor, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt index d2de835ad954..45b28b1d8842 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt @@ -36,6 +36,7 @@ import com.android.systemui.keyguard.ui.viewmodel.lockscreenToGoneTransitionView import com.android.systemui.keyguard.ui.viewmodel.lockscreenToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.lockscreenToPrimaryBouncerTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.occludedToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.occludedToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.occludedToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.primaryBouncerToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.primaryBouncerToLockscreenTransitionViewModel @@ -74,6 +75,7 @@ val Kosmos.sharedNotificationContainerViewModel by Fixture { lockscreenToPrimaryBouncerTransitionViewModel = lockscreenToPrimaryBouncerTransitionViewModel, occludedToAodTransitionViewModel = occludedToAodTransitionViewModel, + occludedToGoneTransitionViewModel = occludedToGoneTransitionViewModel, occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel, primaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel, primaryBouncerToLockscreenTransitionViewModel = diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt index cf800d04f816..9c3f510c8585 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt @@ -24,7 +24,6 @@ import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.data.repository.windowRootViewVisibilityRepository import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.shared.flag.sceneContainerFlags import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor import com.android.systemui.statusbar.policy.headsUpManager @@ -36,7 +35,7 @@ val Kosmos.windowRootViewVisibilityInteractor by Fixture { headsUpManager = headsUpManager, powerInteractor = powerInteractor, activeNotificationsInteractor = activeNotificationsInteractor, - sceneInteractorProvider = { sceneInteractor }, - sceneContainerFlags = sceneContainerFlags, - ) + ) { + sceneInteractor + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt index 638925d0a705..74b2da49d43f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt new file mode 100644 index 000000000000..386c7c52b152 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.airplane.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository +import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository +import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository + +val Kosmos.airplaneModeInteractor: AirplaneModeInteractor by + Kosmos.Fixture { + AirplaneModeInteractor( + FakeAirplaneModeRepository(), + FakeConnectivityRepository(), + FakeMobileConnectionsRepository(), + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt index 2d5a3612ff6a..eb2d6c0f5405 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt @@ -31,6 +31,7 @@ class FakeMobileConnectionRepository( override val tableLogBuffer: TableLogBuffer, ) : MobileConnectionRepository { override val carrierId = MutableStateFlow(UNKNOWN_CARRIER_ID) + override val inflateSignalStrength: MutableStateFlow<Boolean> = MutableStateFlow(false) override val isEmergencyOnly = MutableStateFlow(false) override val isRoaming = MutableStateFlow(false) override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null) @@ -63,8 +64,6 @@ class FakeMobileConnectionRepository( override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false) - override val satelliteConnectionHysteresisSeconds = MutableStateFlow(0) - private var isInEcmMode: Boolean = false override suspend fun isInEcmMode(): Boolean = isInEcmMode diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorKosmos.kt new file mode 100644 index 000000000000..eb6265affb1c --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorKosmos.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.mobile.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy +import com.android.systemui.util.mockito.mock + +val Kosmos.mobileIconsInteractor: MobileIconsInteractor by + Kosmos.Fixture { fakeMobileIconsInteractor } +val Kosmos.fakeMobileIconsInteractor: FakeMobileIconsInteractor by + Kosmos.Fixture { FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelKosmos.kt new file mode 100644 index 000000000000..c5f65578a8bb --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelKosmos.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel + +import com.android.systemui.flags.featureFlagsClassic +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.airplaneModeInteractor +import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.mobileIconsInteractor +import com.android.systemui.util.mockito.mock + +val Kosmos.mobileIconsViewModel: MobileIconsViewModel by + Kosmos.Fixture { + MobileIconsViewModel( + logger = mock(), + verboseLogger = mock(), + interactor = mobileIconsInteractor, + airplaneModeInteractor = airplaneModeInteractor, + constants = mock(), + flags = featureFlagsClassic, + scope = applicationCoroutineScope, + ) + } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt index 28d632d9fcea..331e2fad19cb 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/truth/TruthUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/TruthUtils.kt new file mode 100644 index 000000000000..64fed689d7a9 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/TruthUtils.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.truth + +import com.google.common.truth.MapSubject +import com.google.common.truth.Ordered + +fun MapSubject.containsEntriesExactly(entry: Pair<*, *>, vararg entries: Pair<*, *>): Ordered = + containsExactly( + entry.first, + entry.second, + *entries + .asSequence() + .flatMap { (key, value) -> sequenceOf(key, value) } + .toList() + .toTypedArray() + ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/TestUnfoldTransitionProvider.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FakeUnfoldTransitionProvider.kt index 56c624565971..94f0c44a51b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/TestUnfoldTransitionProvider.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FakeUnfoldTransitionProvider.kt @@ -2,7 +2,7 @@ package com.android.systemui.unfold import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener -class TestUnfoldTransitionProvider : UnfoldTransitionProgressProvider, TransitionProgressListener { +class FakeUnfoldTransitionProvider : UnfoldTransitionProgressProvider, TransitionProgressListener { private val listeners = mutableListOf<TransitionProgressListener>() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt index 7c54a5707bf4..a0f5b58c1cd0 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt @@ -18,6 +18,8 @@ package com.android.systemui.unfold import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.util.mockito.mock -var Kosmos.unfoldTransitionProgressProvider by Fixture { mock<UnfoldTransitionProgressProvider>() } +val Kosmos.fakeUnfoldTransitionProgressProvider by Fixture { FakeUnfoldTransitionProvider() } + +val Kosmos.unfoldTransitionProgressProvider by + Fixture<UnfoldTransitionProgressProvider> { fakeUnfoldTransitionProgressProvider } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt index d3410737a432..348a02e1da04 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt @@ -24,6 +24,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.volume.panel.dagger.factory.KosmosVolumePanelComponentFactory import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria import com.android.systemui.volume.panel.domain.TestComponentAvailabilityCriteria +import com.android.systemui.volume.panel.domain.VolumePanelStartable import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractorImpl import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey @@ -44,6 +45,8 @@ val Kosmos.componentsFactory: ComponentsFactory by var Kosmos.componentsLayoutManager: ComponentsLayoutManager by Kosmos.Fixture() var Kosmos.enabledComponents: Collection<VolumePanelComponentKey> by Kosmos.Fixture { componentByKey.keys } +var Kosmos.volumePanelStartables: Set<VolumePanelStartable> by + Kosmos.Fixture { emptySet<VolumePanelStartable>() } val Kosmos.unavailableCriteria: Provider<ComponentAvailabilityCriteria> by Kosmos.Fixture { Provider { TestComponentAvailabilityCriteria(false) } } val Kosmos.availableCriteria: Provider<ComponentAvailabilityCriteria> by diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt index b66d7f974eca..d4a72b437fd8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt @@ -24,8 +24,9 @@ class FakeAncSliceRepository : AncSliceRepository { private val sliceByWidth = mutableMapOf<Int, MutableStateFlow<Slice?>>() - override fun ancSlice(width: Int): Flow<Slice?> = - sliceByWidth.getOrPut(width) { MutableStateFlow(null) } + override fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> { + return sliceByWidth.getOrPut(width) { MutableStateFlow(null) } + } fun putSlice(width: Int, slice: Slice?) { sliceByWidth.getOrPut(width) { MutableStateFlow(null) }.value = slice diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt index 49041ed0d652..e5f5d4e389f1 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt @@ -22,10 +22,12 @@ import com.android.systemui.volume.panel.componentsFactory import com.android.systemui.volume.panel.componentsInteractor import com.android.systemui.volume.panel.componentsLayoutManager import com.android.systemui.volume.panel.dagger.VolumePanelComponent +import com.android.systemui.volume.panel.domain.VolumePanelStartable import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor import com.android.systemui.volume.panel.ui.composable.ComponentsFactory import com.android.systemui.volume.panel.ui.layout.ComponentsLayoutManager import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel +import com.android.systemui.volume.panel.volumePanelStartables import kotlinx.coroutines.CoroutineScope class KosmosVolumePanelComponentFactory(private val kosmos: Kosmos) : VolumePanelComponentFactory { @@ -41,5 +43,8 @@ class KosmosVolumePanelComponentFactory(private val kosmos: Kosmos) : VolumePane override fun componentsLayoutManager(): ComponentsLayoutManager = kosmos.componentsLayoutManager + + override fun volumePanelStartables(): Set<VolumePanelStartable> = + kosmos.volumePanelStartables } } diff --git a/packages/SystemUI/utils/Android.bp b/packages/SystemUI/utils/Android.bp new file mode 100644 index 000000000000..1ef381617c20 --- /dev/null +++ b/packages/SystemUI/utils/Android.bp @@ -0,0 +1,32 @@ +// +// Copyright (C) 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_", + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + +java_library { + name: "SystemUI-shared-utils", + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], + static_libs: [ + "kotlin-stdlib", + "kotlinx_coroutines", + ], +} diff --git a/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/FlowConflated.kt b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/FlowConflated.kt new file mode 100644 index 000000000000..ed97c600adec --- /dev/null +++ b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/FlowConflated.kt @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalTypeInference::class) + +package com.android.systemui.utils.coroutines.flow + +import kotlin.experimental.ExperimentalTypeInference +import kotlinx.coroutines.channels.ProducerScope +import kotlinx.coroutines.channels.SendChannel +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.produceIn +import kotlinx.coroutines.suspendCancellableCoroutine + +/** + * Creates an instance of a _cold_ [Flow] with elements that are sent to a [SendChannel] provided to + * the builder's [block] of code via [ProducerScope]. It allows elements to be produced by code that + * is running in a different context or concurrently. + * + * The resulting flow is _cold_, which means that [block] is called every time a terminal operator + * is applied to the resulting flow. + * + * This builder ensures thread-safety and context preservation, thus the provided [ProducerScope] + * can be used from any context, e.g. from a callback-based API. The resulting flow completes as + * soon as the code in the [block] completes. [awaitClose] should be used to keep the flow running, + * otherwise the channel will be closed immediately when block completes. [awaitClose] argument is + * called either when a flow consumer cancels the flow collection or when a callback-based API + * invokes [SendChannel.close] manually and is typically used to cleanup the resources after the + * completion, e.g. unregister a callback. Using [awaitClose] is mandatory in order to prevent + * memory leaks when the flow collection is cancelled, otherwise the callback may keep running even + * when the flow collector is already completed. To avoid such leaks, this method throws + * [IllegalStateException] if block returns, but the channel is not closed yet. + * + * A [conflated][conflate] channel is used. Use the [buffer] operator on the resulting flow to + * specify a user-defined value and to control what happens when data is produced faster than + * consumed, i.e. to control the back-pressure behavior. + * + * Adjacent applications of [callbackFlow], [flowOn], [buffer], and [produceIn] are always fused so + * that only one properly configured channel is used for execution. + * + * Example of usage that converts a multi-shot callback API to a flow. For single-shot callbacks use + * [suspendCancellableCoroutine]. + * + * ``` + * fun flowFrom(api: CallbackBasedApi): Flow<T> = callbackFlow { + * val callback = object : Callback { // Implementation of some callback interface + * override fun onNextValue(value: T) { + * // To avoid blocking you can configure channel capacity using + * // either buffer(Channel.CONFLATED) or buffer(Channel.UNLIMITED) to avoid overfill + * trySendBlocking(value) + * .onFailure { throwable -> + * // Downstream has been cancelled or failed, can log here + * } + * } + * override fun onApiError(cause: Throwable) { + * cancel(CancellationException("API Error", cause)) + * } + * override fun onCompleted() = channel.close() + * } + * api.register(callback) + * /* + * * Suspends until either 'onCompleted'/'onApiError' from the callback is invoked + * * or flow collector is cancelled (e.g. by 'take(1)' or because a collector's coroutine was cancelled). + * * In both cases, callback will be properly unregistered. + * */ + * awaitClose { api.unregister(callback) } + * } + * ``` + * > The callback `register`/`unregister` methods provided by an external API must be thread-safe, + * > because `awaitClose` block can be called at any time due to asynchronous nature of + * > cancellation, even concurrently with the call of the callback. + * + * This builder is to be preferred over [callbackFlow], due to the latter's default configuration of + * using an internal buffer, negatively impacting system health. + * + * @see callbackFlow + */ +fun <T> conflatedCallbackFlow( + @BuilderInference block: suspend ProducerScope<T>.() -> Unit, +): Flow<T> = callbackFlow(block).conflate() + +/** + * Creates an instance of a _cold_ [Flow] with elements that are sent to a [SendChannel] provided to + * the builder's [block] of code via [ProducerScope]. It allows elements to be produced by code that + * is running in a different context or concurrently. The resulting flow is _cold_, which means that + * [block] is called every time a terminal operator is applied to the resulting flow. + * + * This builder ensures thread-safety and context preservation, thus the provided [ProducerScope] + * can be used concurrently from different contexts. The resulting flow completes as soon as the + * code in the [block] and all its children completes. Use [awaitClose] as the last statement to + * keep it running. A more detailed example is provided in the documentation of [callbackFlow]. + * + * A [conflated][conflate] channel is used. Use the [buffer] operator on the resulting flow to + * specify a user-defined value and to control what happens when data is produced faster than + * consumed, i.e. to control the back-pressure behavior. + * + * Adjacent applications of [channelFlow], [flowOn], [buffer], and [produceIn] are always fused so + * that only one properly configured channel is used for execution. + * + * Examples of usage: + * ``` + * fun <T> Flow<T>.merge(other: Flow<T>): Flow<T> = channelFlow { + * // collect from one coroutine and send it + * launch { + * collect { send(it) } + * } + * // collect and send from this coroutine, too, concurrently + * other.collect { send(it) } + * } + * + * fun <T> contextualFlow(): Flow<T> = channelFlow { + * // send from one coroutine + * launch(Dispatchers.IO) { + * send(computeIoValue()) + * } + * // send from another coroutine, concurrently + * launch(Dispatchers.Default) { + * send(computeCpuValue()) + * } + * } + * ``` + * + * This builder is to be preferred over [channelFlow], due to the latter's default configuration of + * using an internal buffer, negatively impacting system health. + * + * @see channelFlow + */ +fun <T> conflatedChannelFlow( + @BuilderInference block: suspend ProducerScope<T>.() -> Unit, +): Flow<T> = channelFlow(block).conflate() diff --git a/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/LatestConflated.kt b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/LatestConflated.kt new file mode 100644 index 000000000000..5f8c66078483 --- /dev/null +++ b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/LatestConflated.kt @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalTypeInference::class) + +package com.android.systemui.utils.coroutines.flow + +import kotlin.experimental.ExperimentalTypeInference +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.transformLatest + +/** + * Returns a flow that emits elements from the original flow transformed by [transform] function. + * When the original flow emits a new value, computation of the [transform] block for previous value + * is cancelled. + * + * For example, the following flow: + * ``` + * flow { + * emit("a") + * delay(100) + * emit("b") + * }.mapLatest { value -> + * println("Started computing $value") + * delay(200) + * "Computed $value" + * } + * ``` + * + * will print "Started computing a" and "Started computing b", but the resulting flow will contain + * only "Computed b" value. + * + * This operator is [conflated][conflate] by default, and as such should be preferred over usage of + * [mapLatest], due to the latter's default configuration of using an internal buffer, negatively + * impacting system health. + * + * @see mapLatest + */ +fun <T, R> Flow<T>.mapLatestConflated(@BuilderInference transform: suspend (T) -> R): Flow<R> = + mapLatest(transform).conflate() + +/** + * Returns a flow that switches to a new flow produced by [transform] function every time the + * original flow emits a value. When the original flow emits a new value, the previous flow produced + * by `transform` block is cancelled. + * + * For example, the following flow: + * ``` + * flow { + * emit("a") + * delay(100) + * emit("b") + * }.flatMapLatest { value -> + * flow { + * emit(value) + * delay(200) + * emit(value + "_last") + * } + * } + * ``` + * + * produces `a b b_last` + * + * This operator is [conflated][conflate] by default, and as such should be preferred over usage of + * [flatMapLatest], due to the latter's default configuration of using an internal buffer, + * negatively impacting system health. + * + * @see flatMapLatest + */ +fun <T, R> Flow<T>.flatMapLatestConflated( + @BuilderInference transform: suspend (T) -> Flow<R>, +): Flow<R> = flatMapLatest(transform).conflate() + +/** + * Returns a flow that produces element by [transform] function every time the original flow emits a + * value. When the original flow emits a new value, the previous `transform` block is cancelled, + * thus the name `transformLatest`. + * + * For example, the following flow: + * ``` + * flow { + * emit("a") + * delay(100) + * emit("b") + * }.transformLatest { value -> + * emit(value) + * delay(200) + * emit(value + "_last") + * } + * ``` + * + * produces `a b b_last`. + * + * This operator is [conflated][conflate] by default, and as such should be preferred over usage of + * [transformLatest], due to the latter's default configuration of using an internal buffer, + * negatively impacting system health. + * + * @see transformLatest + */ +fun <T, R> Flow<T>.transformLatestConflated( + @BuilderInference transform: suspend FlowCollector<R>.(T) -> Unit, +): Flow<R> = transformLatest(transform).conflate() diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java index 23e269a67283..cbbce1a74e94 100644 --- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java +++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java @@ -19,6 +19,7 @@ package com.android.wallpaperbackup; import static android.app.WallpaperManager.FLAG_LOCK; import static android.app.WallpaperManager.FLAG_SYSTEM; import static android.app.WallpaperManager.ORIENTATION_UNKNOWN; +import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_INELIGIBLE; import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_METADATA; @@ -39,6 +40,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; +import android.graphics.BitmapFactory; import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManager; @@ -109,22 +111,16 @@ public class WallpaperBackupAgent extends BackupAgent { static final String LOCK_WALLPAPER_STAGE = "wallpaper-lock-stage"; @VisibleForTesting static final String WALLPAPER_INFO_STAGE = "wallpaper-info-stage"; - @VisibleForTesting static final String WALLPAPER_BACKUP_DEVICE_INFO_STAGE = "wallpaper-backup-device-info-stage"; - static final String EMPTY_SENTINEL = "empty"; static final String QUOTA_SENTINEL = "quota"; - // Shared preferences constants. static final String PREFS_NAME = "wbprefs.xml"; static final String SYSTEM_GENERATION = "system_gen"; static final String LOCK_GENERATION = "lock_gen"; - /** - * An approximate area threshold to compare device dimension similarity - */ - static final int AREA_THRESHOLD = 50; // TODO (b/327637867): determine appropriate threshold + static final float DEFAULT_ACCEPTABLE_PARALLAX = 0.2f; // If this file exists, it means we exceeded our quota last time private File mQuotaFile; @@ -336,7 +332,6 @@ public class WallpaperBackupAgent extends BackupAgent { mEventLogger.onSystemImageWallpaperBackupFailed(error); } - private void backupLockWallpaperFileIfItExists(SharedPreferences sharedPrefs, boolean lockChanged, int lockGeneration, FullBackupDataOutput data) throws IOException { final File lockImageStage = new File(getFilesDir(), LOCK_WALLPAPER_STAGE); @@ -409,6 +404,16 @@ public class WallpaperBackupAgent extends BackupAgent { } } + private static String readText(TypedXmlPullParser parser) + throws IOException, XmlPullParserException { + String result = ""; + if (parser.next() == XmlPullParser.TEXT) { + result = parser.getText(); + parser.nextTag(); + } + return result; + } + @VisibleForTesting // fullBackupFile is final, so we intercept backups here in tests. protected void backupFile(File file, FullBackupDataOutput data) { @@ -438,18 +443,10 @@ public class WallpaperBackupAgent extends BackupAgent { boolean lockImageStageExists = lockImageStage.exists(); try { - // Parse the device dimensions of the source device and compare with target to - // to identify whether we need to skip the remainder of the restore process + // Parse the device dimensions of the source device Pair<Point, Point> sourceDeviceDimensions = parseDeviceDimensions( deviceDimensionsStage); - Point targetDeviceDimensions = getScreenDimensions(); - if (sourceDeviceDimensions != null && targetDeviceDimensions != null - && isSourceDeviceSignificantlySmallerThanTarget(sourceDeviceDimensions.first, - targetDeviceDimensions)) { - Slog.d(TAG, "The source device is significantly smaller than target"); - } - // First parse the live component name so that we know for logging if we care about // logging errors with the image restore. ComponentName wpService = parseWallpaperComponent(infoStage, "wp"); @@ -466,9 +463,10 @@ public class WallpaperBackupAgent extends BackupAgent { // to back up the original image on the source device, or there was no user-supplied // wallpaper image present. if (lockImageStageExists) { - restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK); + restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK, + sourceDeviceDimensions); } - restoreFromStage(imageStage, infoStage, "wp", sysWhich); + restoreFromStage(imageStage, infoStage, "wp", sysWhich, sourceDeviceDimensions); // And reset to the wallpaper service we should be using if (mLockHasLiveComponent) { @@ -543,16 +541,6 @@ public class WallpaperBackupAgent extends BackupAgent { } } - private static String readText(TypedXmlPullParser parser) - throws IOException, XmlPullParserException { - String result = ""; - if (parser.next() == XmlPullParser.TEXT) { - result = parser.getText(); - parser.nextTag(); - } - return result; - } - @VisibleForTesting void updateWallpaperComponent(ComponentName wpService, int which) throws IOException { @@ -578,10 +566,13 @@ public class WallpaperBackupAgent extends BackupAgent { } } - private void restoreFromStage(File stage, File info, String hintTag, int which) + private void restoreFromStage(File stage, File info, String hintTag, int which, + Pair<Point, Point> sourceDeviceDimensions) throws IOException { if (stage.exists()) { if (multiCrop()) { + // TODO(b/332937943): implement offset adjustment by manually adjusting crop to + // adhere to device aspect ratio SparseArray<Rect> cropHints = parseCropHints(info, hintTag); if (cropHints != null) { Slog.i(TAG, "Got restored wallpaper; applying which=" + which @@ -601,7 +592,6 @@ public class WallpaperBackupAgent extends BackupAgent { } return; } - // Parse the restored info file to find the crop hint. Note that this currently // relies on a priori knowledge of the wallpaper info file schema. Rect cropHint = parseCropHint(info, hintTag); @@ -609,8 +599,33 @@ public class WallpaperBackupAgent extends BackupAgent { Slog.i(TAG, "Got restored wallpaper; applying which=" + which + "; cropHint = " + cropHint); try (FileInputStream in = new FileInputStream(stage)) { - mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint, true, - which); + + if (sourceDeviceDimensions != null && sourceDeviceDimensions.first != null) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + ParcelFileDescriptor pdf = ParcelFileDescriptor.open(stage, MODE_READ_ONLY); + BitmapFactory.decodeFileDescriptor(pdf.getFileDescriptor(), + null, options); + Point bitmapSize = new Point(options.outWidth, options.outHeight); + Point sourceDeviceSize = new Point(sourceDeviceDimensions.first.x, + sourceDeviceDimensions.first.y); + Point targetDeviceDimensions = getScreenDimensions(); + + // TODO: for now we handle only the case where the target device has smaller + // aspect ratio than the source device i.e. the target device is more narrow + // than the source device + if (isTargetMoreNarrowThanSource(targetDeviceDimensions, + sourceDeviceSize)) { + Rect adjustedCrop = findNewCropfromOldCrop(cropHint, + sourceDeviceDimensions.first, true, targetDeviceDimensions, + bitmapSize, true); + + cropHint.set(adjustedCrop); + } + } + + mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint, + true, which); // And log the success if ((which & FLAG_SYSTEM) > 0) { @@ -629,6 +644,209 @@ public class WallpaperBackupAgent extends BackupAgent { } } + /** + * This method computes the crop of the stored wallpaper to preserve its center point as the + * user had set it in the previous device. + * + * The algorithm involves first computing the original crop of the user (without parallax). Then + * manually adjusting the user's original crop to respect the current device's aspect ratio + * (thereby preserving the center point). Then finally, adding any leftover image real-estate + * (i.e. space left over on the horizontal axis) to add parallax effect. Parallax is only added + * if was present in the old device's settings. + * + */ + private Rect findNewCropfromOldCrop(Rect oldCrop, Point oldDisplaySize, boolean oldRtl, + Point newDisplaySize, Point bitmapSize, boolean newRtl) { + Rect cropWithoutParallax = withoutParallax(oldCrop, oldDisplaySize, oldRtl, bitmapSize); + oldCrop = oldCrop.isEmpty() ? new Rect(0, 0, bitmapSize.x, bitmapSize.y) : oldCrop; + float oldParallaxAmount = ((float) oldCrop.width() / cropWithoutParallax.width()) - 1; + + Rect newCropWithSameCenterWithoutParallax = sameCenter(newDisplaySize, bitmapSize, + cropWithoutParallax); + + Rect newCrop = newCropWithSameCenterWithoutParallax; + + // calculate the amount of left-over space there is in the image after adjusting the crop + // from the above operation i.e. in a rtl configuration, this is the remaining space in the + // image after subtracting the new crop's right edge coordinate from the image itself, and + // for ltr, its just the new crop's left edge coordinate (as it's the distance from the + // beginning of the image) + int widthAvailableForParallaxOnTheNewDevice = + (newRtl) ? newCrop.left : bitmapSize.x - newCrop.right; + + // calculate relatively how much this available space is as a fraction of the total cropped + // image + float availableParallaxAmount = + (float) widthAvailableForParallaxOnTheNewDevice / newCrop.width(); + + float minAcceptableParallax = Math.min(DEFAULT_ACCEPTABLE_PARALLAX, oldParallaxAmount); + + if (DEBUG) { + Slog.d(TAG, "- cropWithoutParallax: " + cropWithoutParallax); + Slog.d(TAG, "- oldParallaxAmount: " + oldParallaxAmount); + Slog.d(TAG, "- newCropWithSameCenterWithoutParallax: " + + newCropWithSameCenterWithoutParallax); + Slog.d(TAG, "- widthAvailableForParallaxOnTheNewDevice: " + + widthAvailableForParallaxOnTheNewDevice); + Slog.d(TAG, "- availableParallaxAmount: " + availableParallaxAmount); + Slog.d(TAG, "- minAcceptableParallax: " + minAcceptableParallax); + Slog.d(TAG, "- oldCrop: " + oldCrop); + Slog.d(TAG, "- oldDisplaySize: " + oldDisplaySize); + Slog.d(TAG, "- oldRtl: " + oldRtl); + Slog.d(TAG, "- newDisplaySize: " + newDisplaySize); + Slog.d(TAG, "- bitmapSize: " + bitmapSize); + Slog.d(TAG, "- newRtl: " + newRtl); + } + if (availableParallaxAmount >= minAcceptableParallax) { + // but in any case, don't put more parallax than the amount of the old device + float parallaxToAdd = Math.min(availableParallaxAmount, oldParallaxAmount); + + int widthToAddForParallax = (int) (newCrop.width() * parallaxToAdd); + if (DEBUG) { + Slog.d(TAG, "- parallaxToAdd: " + parallaxToAdd); + Slog.d(TAG, "- widthToAddForParallax: " + widthToAddForParallax); + } + if (newRtl) { + newCrop.left -= widthToAddForParallax; + } else { + newCrop.right += widthToAddForParallax; + } + } + return newCrop; + } + + /** + * This method computes the original crop of the user without parallax. + * + * NOTE: When the user sets the wallpaper with a specific crop, there may additional image added + * to the crop to support parallax. In order to determine the user's actual crop the parallax + * must be removed if it exists. + */ + Rect withoutParallax(Rect crop, Point displaySize, boolean rtl, Point bitmapSize) { + // in the case an image's crop is not set, we assume the image itself is cropped + if (crop.isEmpty()) { + crop = new Rect(0, 0, bitmapSize.x, bitmapSize.y); + } + + if (DEBUG) { + Slog.w(TAG, "- crop: " + crop); + } + + Rect adjustedCrop = new Rect(crop); + float suggestedDisplayRatio = (float) displaySize.x / displaySize.y; + + // here we calculate the width of the wallpaper image such that it has the same aspect ratio + // as the given display i.e. the width of the image on a single page of the device without + // parallax (i.e. displaySize will correspond to the display the crop was originally set on) + int wallpaperWidthWithoutParallax = (int) (0.5f + (float) displaySize.x * crop.height() + / displaySize.y); + // subtracting wallpaperWidthWithoutParallax from the wallpaper crop gives the amount of + // parallax added + int widthToRemove = Math.max(0, crop.width() - wallpaperWidthWithoutParallax); + + if (DEBUG) { + Slog.d(TAG, "- adjustedCrop: " + adjustedCrop); + Slog.d(TAG, "- suggestedDisplayRatio: " + suggestedDisplayRatio); + Slog.d(TAG, "- wallpaperWidthWithoutParallax: " + wallpaperWidthWithoutParallax); + Slog.d(TAG, "- widthToRemove: " + widthToRemove); + } + if (rtl) { + adjustedCrop.left += widthToRemove; + } else { + adjustedCrop.right -= widthToRemove; + } + + if (DEBUG) { + Slog.d(TAG, "- adjustedCrop: " + crop); + } + return adjustedCrop; + } + + /** + * This method computes a new crop based on the given crop in order to preserve the center point + * of the given crop on the provided displaySize. This is only for the case where the device + * displaySize has a smaller aspect ratio than the cropped image. + * + * NOTE: If the width to height ratio is less in the device display than cropped image + * this means the aspect ratios are off and there will be distortions in the image + * if the image is applied to the current display (i.e. the image will be skewed -> + * pixels in the image will not align correctly with the same pixels in the image that are + * above them) + */ + Rect sameCenter(Point displaySize, Point bitmapSize, Rect crop) { + + // in the case an image's crop is not set, we assume the image itself is cropped + if (crop.isEmpty()) { + crop = new Rect(0, 0, bitmapSize.x, bitmapSize.y); + } + + float screenRatio = (float) displaySize.x / displaySize.y; + float cropRatio = (float) crop.width() / crop.height(); + + Rect adjustedCrop = new Rect(crop); + + if (screenRatio < cropRatio) { + // the screen is more narrow than the image, and as such, the image will need to be + // zoomed in till it fits in the vertical axis. Due to this, we need to manually adjust + // the image's crop in order for it to fit into the screen without having the framework + // do it (since the framework left aligns the image after zooming) + + // Calculate the height of the adjusted wallpaper crop so it respects the aspect ratio + // of the device. To calculate the height, we will use the width of the current crop. + // This is so we find the largest height possible which also respects the device aspect + // ratio. + int heightToAdd = (int) (0.5f + crop.width() / screenRatio - crop.height()); + + // Calculate how much extra image space available that can be used to adjust + // the crop. If this amount is less than heightToAdd, from above, then that means we + // can't use heightToAdd. Instead we will need to use the maximum possible height, which + // is the height of the original bitmap. NOTE: the bitmap height may be different than + // the crop. + // since there is no guarantee to have height available on both sides + // (e.g. the available height might be fully at the bottom), grab the minimum + int availableHeight = 2 * Math.min(crop.top, bitmapSize.y - crop.bottom); + int actualHeightToAdd = Math.min(heightToAdd, availableHeight); + + // half of the additional height is added to the top and bottom of the crop + adjustedCrop.top -= actualHeightToAdd / 2 + actualHeightToAdd % 2; + adjustedCrop.bottom += actualHeightToAdd / 2; + + // Calculate the width of the adjusted crop. Initially we used the fixed width of the + // crop to calculate the heightToAdd, but since this height may be invalid (based on + // the calculation above) we calculate the width again instead of using the fixed width, + // using the adjustedCrop's updated height. + int widthToRemove = (int) (0.5f + crop.width() - adjustedCrop.height() * screenRatio); + + // half of the additional width is subtracted from the left and right side of the crop + int widthToRemoveLeft = widthToRemove / 2; + int widthToRemoveRight = widthToRemove / 2 + widthToRemove % 2; + + adjustedCrop.left += widthToRemoveLeft; + adjustedCrop.right -= widthToRemoveRight; + + if (DEBUG) { + Slog.d(TAG, "cropRatio: " + cropRatio); + Slog.d(TAG, "screenRatio: " + screenRatio); + Slog.d(TAG, "heightToAdd: " + heightToAdd); + Slog.d(TAG, "actualHeightToAdd: " + actualHeightToAdd); + Slog.d(TAG, "availableHeight: " + availableHeight); + Slog.d(TAG, "widthToRemove: " + widthToRemove); + Slog.d(TAG, "adjustedCrop: " + adjustedCrop); + } + + return adjustedCrop; + } + + return adjustedCrop; + } + + private boolean isTargetMoreNarrowThanSource(Point targetDisplaySize, Point srcDisplaySize) { + float targetScreenRatio = (float) targetDisplaySize.x / targetDisplaySize.y; + float srcScreenRatio = (float) srcDisplaySize.x / srcDisplaySize.y; + + return (targetScreenRatio < srcScreenRatio); + } + private void logRestoreErrorIfNoLiveComponent(int which, String error) { if (mSystemHasLiveComponent) { return; @@ -644,6 +862,7 @@ public class WallpaperBackupAgent extends BackupAgent { mEventLogger.onLockImageWallpaperRestoreFailed(error); } } + private Rect parseCropHint(File wallpaperInfo, String sectionTag) { Rect cropHint = new Rect(); try (FileInputStream stream = new FileInputStream(wallpaperInfo)) { @@ -681,7 +900,7 @@ public class WallpaperBackupAgent extends BackupAgent { if (type != XmlPullParser.START_TAG) continue; String tag = parser.getName(); if (!sectionTag.equals(tag)) continue; - for (Pair<Integer, String> pair: List.of( + for (Pair<Integer, String> pair : List.of( new Pair<>(WallpaperManager.PORTRAIT, "Portrait"), new Pair<>(WallpaperManager.LANDSCAPE, "Landscape"), new Pair<>(WallpaperManager.SQUARE_PORTRAIT, "SquarePortrait"), @@ -907,22 +1126,6 @@ public class WallpaperBackupAgent extends BackupAgent { return internalDisplays; } - /** - * This method compares the source and target dimensions, and returns true if there is a - * significant difference in area between them and the source dimensions are smaller than the - * target dimensions. - * - * @param sourceDimensions is the dimensions of the source device - * @param targetDimensions is the dimensions of the target device - */ - @VisibleForTesting - boolean isSourceDeviceSignificantlySmallerThanTarget(Point sourceDimensions, - Point targetDimensions) { - int rawAreaDelta = (targetDimensions.x * targetDimensions.y) - - (sourceDimensions.x * sourceDimensions.y); - return rawAreaDelta > AREA_THRESHOLD; - } - @VisibleForTesting boolean isDeviceInRestore() { try { diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java index ec9223c7d667..3ecdf3f101a5 100644 --- a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java +++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java @@ -59,7 +59,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.graphics.Point; import android.graphics.Rect; import android.os.FileUtils; import android.os.ParcelFileDescriptor; @@ -841,26 +840,6 @@ public class WallpaperBackupAgentTest { testParseCropHints(testMap); } - @Test - public void test_sourceDimensionsAreLargerThanTarget() { - // source device is larger than target, expecting to get false - Point sourceDimensions = new Point(2208, 1840); - Point targetDimensions = new Point(1080, 2092); - boolean isSourceSmaller = mWallpaperBackupAgent - .isSourceDeviceSignificantlySmallerThanTarget(sourceDimensions, targetDimensions); - assertThat(isSourceSmaller).isEqualTo(false); - } - - @Test - public void test_sourceDimensionsMuchSmallerThanTarget() { - // source device is smaller than target, expecting to get true - Point sourceDimensions = new Point(1080, 2092); - Point targetDimensions = new Point(2208, 1840); - boolean isSourceSmaller = mWallpaperBackupAgent - .isSourceDeviceSignificantlySmallerThanTarget(sourceDimensions, targetDimensions); - assertThat(isSourceSmaller).isEqualTo(true); - } - private void testParseCropHints(Map<Integer, Rect> testMap) throws Exception { assumeTrue(multiCrop()); mockRestoredStaticWallpaperFile(testMap); diff --git a/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml index ff920b290dbb..97559b4feda8 100644 --- a/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml +++ b/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"लुकाइयोस्"</string> + <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"लुकाउनुहोस्"</string> </resources> |