diff options
313 files changed, 6164 insertions, 1169 deletions
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index e23bbc6c347d..d3bde4b4b8a8 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -20,6 +20,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainRunna import android.annotation.NonNull; import android.content.Context; +import android.graphics.ImageFormat; import android.hardware.ICameraService; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; @@ -1478,6 +1479,12 @@ public class CameraDeviceImpl extends CameraDevice } } + // Allow RAW formats, even when not advertised. + if (inputFormat == ImageFormat.RAW_PRIVATE || inputFormat == ImageFormat.RAW10 + || inputFormat == ImageFormat.RAW12 || inputFormat == ImageFormat.RAW_SENSOR) { + return true; + } + if (validFormat == false) { return false; } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 01977f6195ff..619544366b02 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -103,6 +103,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing private static final int MSG_UDFPS_POINTER_DOWN = 108; private static final int MSG_UDFPS_POINTER_UP = 109; private static final int MSG_POWER_BUTTON_PRESSED = 110; + private static final int MSG_UDFPS_OVERLAY_SHOWN = 111; /** * @hide @@ -121,6 +122,24 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing public @interface EnrollReason {} /** + * Udfps ui event of overlay is shown on the screen. + * @hide + */ + public static final int UDFPS_UI_OVERLAY_SHOWN = 1; + /** + * Udfps ui event of the udfps UI being ready (e.g. HBM illumination is enabled). + * @hide + */ + public static final int UDFPS_UI_READY = 2; + + /** + * @hide + */ + @IntDef({UDFPS_UI_OVERLAY_SHOWN, UDFPS_UI_READY}) + @Retention(RetentionPolicy.SOURCE) + public @interface UdfpsUiEvent{} + + /** * Request authentication with any single sensor. * @hide */ @@ -475,12 +494,17 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * Called when a pointer down event has occurred. */ - public void onPointerDown(int sensorId){ } + public void onUdfpsPointerDown(int sensorId){ } /** * Called when a pointer up event has occurred. */ - public void onPointerUp(int sensorId){ } + public void onUdfpsPointerUp(int sensorId){ } + + /** + * Called when udfps overlay is shown. + */ + public void onUdfpsOverlayShown() { } } /** @@ -1112,14 +1136,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void onUiReady(long requestId, int sensorId) { + public void onUdfpsUiEvent(@UdfpsUiEvent int event, long requestId, int sensorId) { if (mService == null) { - Slog.w(TAG, "onUiReady: no fingerprint service"); + Slog.w(TAG, "onUdfpsUiEvent: no fingerprint service"); return; } try { - mService.onUiReady(requestId, sensorId); + mService.onUdfpsUiEvent(event, requestId, sensorId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1365,6 +1389,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing case MSG_POWER_BUTTON_PRESSED: sendPowerPressed(); break; + case MSG_UDFPS_OVERLAY_SHOWN: + sendUdfpsOverlayShown(); default: Slog.w(TAG, "Unknown message: " + msg.what); @@ -1489,7 +1515,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } if (mEnrollmentCallback != null) { - mEnrollmentCallback.onPointerDown(sensorId); + mEnrollmentCallback.onUdfpsPointerDown(sensorId); } } @@ -1500,7 +1526,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing mAuthenticationCallback.onUdfpsPointerUp(sensorId); } if (mEnrollmentCallback != null) { - mEnrollmentCallback.onPointerUp(sensorId); + mEnrollmentCallback.onUdfpsPointerUp(sensorId); } } @@ -1512,6 +1538,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } + private void sendUdfpsOverlayShown() { + if (mEnrollmentCallback != null) { + mEnrollmentCallback.onUdfpsOverlayShown(); + } + } + /** * @hide */ @@ -1787,6 +1819,11 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing public void onUdfpsPointerUp(int sensorId) { mHandler.obtainMessage(MSG_UDFPS_POINTER_UP, sensorId, 0).sendToTarget(); } + + @Override + public void onUdfpsOverlayShown() { + mHandler.obtainMessage(MSG_UDFPS_OVERLAY_SHOWN).sendToTarget(); + } }; } diff --git a/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java b/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java index a9779b51321b..89d710d4adfe 100644 --- a/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java +++ b/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java @@ -75,4 +75,9 @@ public class FingerprintServiceReceiver extends IFingerprintServiceReceiver.Stub public void onUdfpsPointerUp(int sensorId) throws RemoteException { } + + @Override + public void onUdfpsOverlayShown() throws RemoteException { + + } } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index ec5749ed4f05..ff2f313ac3df 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -193,7 +193,7 @@ interface IFingerprintService { // Notifies about the fingerprint UI being ready (e.g. HBM illumination is enabled). @EnforcePermission("USE_BIOMETRIC_INTERNAL") - void onUiReady(long requestId, int sensorId); + void onUdfpsUiEvent(int event, long requestId, int sensorId); // Sets the controller for managing the UDFPS overlay. @EnforcePermission("USE_BIOMETRIC_INTERNAL") diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl index 9cea1fed629d..91a32d78314c 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl @@ -32,4 +32,5 @@ oneway interface IFingerprintServiceReceiver { void onChallengeGenerated(int sensorId, int userId, long challenge); void onUdfpsPointerDown(int sensorId); void onUdfpsPointerUp(int sensorId); + void onUdfpsOverlayShown(); } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index a95ce64ecec8..7f53cb433c98 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -771,7 +771,7 @@ public class ZygoteInit { Zygote.applyInvokeWithSystemProperty(parsedArgs); if (Zygote.nativeSupportsMemoryTagging()) { - String mode = SystemProperties.get("arm64.memtag.process.system_server", ""); + String mode = SystemProperties.get("persist.arm64.memtag.system_server", ""); if (mode.isEmpty()) { /* The system server has ASYNC MTE by default, in order to allow * system services to specify their own MTE level later, as you diff --git a/core/res/res/layout/shutdown_dialog.xml b/core/res/res/layout/shutdown_dialog.xml index ec67aa86bcc9..726c25540e6f 100644 --- a/core/res/res/layout/shutdown_dialog.xml +++ b/core/res/res/layout/shutdown_dialog.xml @@ -40,7 +40,7 @@ android:fontFamily="@string/config_headlineFontFamily"/> <TextView - android:id="@+id/text2" + android:id="@id/text2" android:layout_width="wrap_content" android:layout_height="32sp" android:text="@string/shutdown_progress" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 6a7c06581d8a..961bae00a5af 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gebruik biometrie of skermslot"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifieer dat dit jy is"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Gebruik jou biometrie om voort te gaan"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Gebruik jou vingerafdruk om voort te gaan"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Gebruik jou gesig om voort te gaan"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Gebruik jou biometriese data of skermslot om voort te gaan"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometriese hardeware is nie beskikbaar nie"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Stawing is gekanselleer"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nie herken nie"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Gesig word nie herken nie"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Stawing is gekanselleer"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Geen PIN, patroon of wagwoord is gestel nie"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Kon nie staaf nie"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 58ae722d3d3e..8540316aab40 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ባዮሜትሪክስ ወይም ማያ ገፅ መቆለፊያን ይጠቀሙ"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"እርስዎን መሆንዎን ያረጋግጡ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ለመቀጠል ባዮሜትሪክዎን ይጠቀሙ"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ለመቀጠል የእርስዎን የጣት አሻራ ይጠቀሙ"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ለመቀጠል የእርስዎን መልክ ይጠቀሙ"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ለመቀጠል የባዮሜትሪክ ወይም የማያ ገፅ ቁልፍዎን ይጠቀሙ"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ባዮሜትራዊ ሃርድዌር አይገኝም"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ማረጋገጥ ተሰርዟል"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"አልታወቀም"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"መልክ አልታወቀም"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ማረጋገጥ ተሰርዟል"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"ምንም ፒን፣ ሥርዓተ ጥለት ወይም የይለፍ ቃል አልተቀናበረም"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"ማረጋገጥ ላይ ስህተት"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index fb48e3ac56a5..cd858982dd16 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -620,10 +620,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"استخدام المقاييس الحيوية أو قفل الشاشة"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"إثبات هويتك"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"استخدام المقاييس الحيوية للمتابعة"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"استخدِم بصمة إصبعك للمتابعة"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"استخدِم وجهك للمتابعة"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"استخدام المقاييس الحيوية أو قفل الشاشة للمتابعة"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"معدّات المقاييس الحيوية غير متاحة."</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"تم إلغاء المصادقة."</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"لم يتم التعرف عليها."</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"لم يتم التعرّف على الوجه."</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"تم إلغاء المصادقة."</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"لم يتم ضبط رقم تعريف شخصي أو نقش أو كلمة مرور."</string> <string name="biometric_error_generic" msgid="6784371929985434439">"خطأ في المصادقة"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 2542163edfc0..0cf45991f0b8 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"বায়\'মেট্ৰিক অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"এইয়া আপুনিয়েই বুলি সত্যাপন কৰক"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"অব্যাহত ৰাখিবলৈ আপোনাৰ বায়\'মেট্ৰিক ব্যৱহাৰ কৰক"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"অব্যাহত ৰাখিবলৈ আপোনাৰ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"অব্যাহত ৰাখিবলৈ নিজৰ মুখাৱয়ব ব্যৱহাৰ কৰক"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"অব্যাহত ৰাখিবলৈ আপোনাৰ বায়’মেট্ৰিক অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"বায়োমেট্ৰিক হাৰ্ডৱেৰ উপলব্ধ নহয়"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"বিশ্বাসযোগ্যতাৰ প্ৰমাণীকৰণ বাতিল কৰা হৈছে"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"চিনাক্ত কৰিব পৰা নাই"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"মুখাৱয়ব চিনি পোৱা নাই"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"বিশ্বাসযোগ্যতাৰ প্ৰমাণীকৰণ বাতিল কৰা হৈছে"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"কোনো পিন, আৰ্হি বা পাছৱৰ্ড ছেট কৰা নাই"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"আসোঁৱাহৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰি থকা হৈছে"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 3d7e48779ce8..215b42add96d 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrik məlumatlardan və ya ekran kilidindən istifadə edin"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Kimliyinizi doğrulayın"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Davam etmək üçün biometrik məlumatlarınızdan istifadə edin"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Barmaq izi ilə davam edin"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Üz ilə davam edin"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Davam etmək üçün biometrik məlumatlar və ya ekran kilidinizdən istifadə edin"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrik proqram əlçatan deyil"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Doğrulama ləğv edildi"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Tanınmır"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Üz tanınmadı"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Doğrulama ləğv edildi"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pin, nümunə və ya parol ayarlanmayıb"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Doğrulama zamanı xəta baş verdi"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 1e731e8813ea..caacaf6ec301 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Koristite biometriju ili zaključavanje ekrana"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrdite svoj identitet"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Koristite biometrijski podatak da biste nastavili"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Nastavite pomoću otiska prsta"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Potvrdite identitet licem da biste nastavili"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Koristite biometrijski podatak ili zaključavanje ekrana da biste nastavili"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrijski hardver nije dostupan"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Potvrda identiteta je otkazana"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nije prepoznato"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Lice nije prepoznato"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Potvrda identiteta je otkazana"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Niste podesili ni PIN, ni šablon, ni lozinku"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Greška pri potvrdi identiteta"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index b23022fc0e49..28a71b8804c8 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Выкарыстоўваць біяметрыю ці блакіроўку экрана"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Спраўдзіце, што гэта вы"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Каб працягнуць, скарыстайце свае біяметрычныя даныя"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Каб працягнуць, скарыстайце адбітак пальца"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Каб працягнуць, скарыстайце распазнаванне твару"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Каб працягнуць, скарыстайце біяметрычныя даныя ці сродак разблакіроўкі экрана"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Біяметрычнае абсталяванне недаступнае"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Аўтэнтыфікацыя скасавана"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Не распазнана"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Твар не распазнаны"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Аўтэнтыфікацыя скасавана"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Не заданы PIN-код, узор разблакіроўкі або пароль"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Памылка аўтэнтыфікацыі"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 65c883a6eab5..fe07a292fb98 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Използване на биометрични данни или опцията за заключване на екрана"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Потвърдете, че сте вие"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Използвайте биометричните си данни, за да продължите"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Използвайте отпечатъка си, за да продължите"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Използвайте лицето си, за да продължите"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Използвайте биометричните си данни или опцията за заключване на екрана, за да продължите"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометричният хардуер не е налице"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Удостоверяването бе анулирано"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Не е разпознато"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Лицето не е разпознато"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Удостоверяването бе анулирано"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Няма зададен ПИН код, фигура или парола"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при удостоверяването"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index fe686db71c4e..037b3f2c3ce8 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"বায়োমেট্রিক্স অথবা স্ক্রিন লক ব্যবহার করুন"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"আপনার পরিচয় যাচাই করুন"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"চালিয়ে যেতে আপনার বায়োমেট্রিক্স ব্যবহার করুন"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"চালিয়ে যেতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"চালিয়ে যেতে আপনার ফেস ব্যবহার করুন"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"চালিয়ে যেতে আপনার বায়োমেট্রিক্স বা স্ক্রিন লক ব্যবহার করুন"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"বায়োমেট্রিক হার্ডওয়্যার পাওয়া যাবে না"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"যাচাইকরণ বাতিল হয়েছে"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"স্বীকৃত নয়"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ফেস চেনা যায়নি"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"যাচাইকরণ বাতিল হয়েছে"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"পিন, প্যাটার্ন অথবা পাসওয়ার্ড সেট করা নেই"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"যাচাইকরণে সমস্যা হয়েছে"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 78220bfedac5..7abd13ddf46d 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Koristi biometriju ili zaključavanje ekrana"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrdite identitet"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Koristite biometriju da nastavite"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Potvrdite identitet otiskom prsta da nastavite"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Potvrdite identitet licem da nastavite"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Koristite biometriju ili zaključavanje ekrana da nastavite"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrijski hardver nije dostupan"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentifikacija je otkazana"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nije prepoznato"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Lice nije prepoznato"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentifikacija je otkazana"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nije postavljen PIN, uzorak niti lozinka"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Greška pri autentifikaciji"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index b581d49384b2..2ffa951e42ef 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Fes servir la biometria o el bloqueig de pantalla"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica la teva identitat"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Utilitza la teva biometria per continuar"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Utilitza l\'empremta digital per continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Utilitza la cara per continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Utilitza la biometria o el bloqueig de pantalla per continuar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Maquinari biomètric no disponible"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"S\'ha cancel·lat l\'autenticació"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"No s\'ha reconegut"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"No s\'ha reconegut la cara"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"S\'ha cancel·lat l\'autenticació"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No s\'ha definit cap PIN, patró o contrasenya"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error en l\'autenticació"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index bb07a799eadb..d4e355ea2695 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Použít biometrii nebo zámek obrazovky"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrďte, že jste to vy"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Pokračujte biometrickým ověřením"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Pokračujte přiložením prstu"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Pokračujte ověřením obličeje"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Pokračujte ověřením pomocí biometrických údajů nebo zámku obrazovky"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrický hardware není k dispozici"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Ověření bylo zrušeno"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nerozpoznáno"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Obličej nebyl rozpoznán"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Ověření bylo zrušeno"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Není nastaven žádný PIN, gesto ani heslo"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Při ověřování došlo k chybě"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 0c00737c5c05..b453b486bb92 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Brug biometri eller skærmlås"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verificer, at det er dig"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Brug dine biometriske data for at fortsætte"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Brug dit fingeraftryk for at fortsætte"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Brug dit ansigt for at fortsætte"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Brug dine biometriske data eller din skærmlås for at fortsætte"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrisk hardware er ikke tilgængelig"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Godkendelsen blev annulleret"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Ikke genkendt"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Ansigt blev ikke genkendt"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Godkendelsen blev annulleret"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Der er ikke angivet pinkode, mønster eller adgangskode"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Der opstod fejl i forbindelse med godkendelse"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 55e845586ef1..421fe7fa7fbd 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrisches Verfahren oder Displaysperre verwenden"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Deine Identität bestätigen"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Mithilfe eines biometrischen Verfahrens fortfahren"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Fingerabdruck verwenden, um fortzufahren"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Gesichtserkennung verwenden, um fortzufahren"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Verwende deine biometrischen Daten oder deine Display-Entsperrmethode, um fortzufahren"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrische Hardware nicht verfügbar"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentifizierung abgebrochen"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nicht erkannt"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Gesicht nicht erkannt"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentifizierung abgebrochen"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Keine PIN, kein Muster und kein Passwort festgelegt"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Fehler bei der Authentifizierung"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 5f7306ade927..02ef0b6ba792 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Χρήση βιομετρικών ή κλειδώματος οθόνης"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Επαλήθευση ταυτότητας"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Χρησιμοποιήστε βιομετρικά για να συνεχίσετε"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Χρησιμοποιήστε το δακτυλικό σας αποτύπωμα για να συνεχίσετε"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Χρησιμοποιήστε το πρόσωπό σας για να συνεχίσετε"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Χρήση βιομετρικών στοιχείων ή κλειδώματος οθόνης για συνέχεια"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Δεν υπάρχει διαθέσιμος βιομετρικός εξοπλισμός"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Ο έλεγχος ταυτότητας ακυρώθηκε"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Δεν αναγνωρίστηκε"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Το πρόσωπο δεν αναγνωρίστηκε"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Ο έλεγχος ταυτότητας ακυρώθηκε"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Δεν έχει οριστεί PIN, μοτίβο ή κωδικός πρόσβασης"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Σφάλμα κατά τον έλεγχο ταυτότητας"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 73b2968ab9cc..6bedb64eb0e5 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify that it’s you"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use your biometric to continue"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use your fingerprint to continue"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use your face to continue"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use your biometric or screen lock to continue"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometric hardware unavailable"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentication cancelled"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Not recognised"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Face not recognised"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentication cancelled"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No pin, pattern or password set"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 73017c11ac25..6b8fea94b17e 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify it’s you"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use your biometric to continue"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use your fingerprint to continue"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use your face to continue"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use your biometric or screen lock to continue"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometric hardware unavailable"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentication canceled"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Not recognized"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Face not recognized"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentication canceled"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No pin, pattern, or password set"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error authenticating"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index aeabd0096974..6f432afcb543 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify that it’s you"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use your biometric to continue"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use your fingerprint to continue"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use your face to continue"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use your biometric or screen lock to continue"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometric hardware unavailable"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentication cancelled"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Not recognised"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Face not recognised"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentication cancelled"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No pin, pattern or password set"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 92f989728902..6812fdd828cc 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify that it’s you"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use your biometric to continue"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use your fingerprint to continue"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use your face to continue"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use your biometric or screen lock to continue"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometric hardware unavailable"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentication cancelled"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Not recognised"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Face not recognised"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentication cancelled"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No pin, pattern or password set"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error while authenticating"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index b560c017b7f8..6ac2b97e39ac 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify it’s you"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use your biometric to continue"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use your fingerprint to continue"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use your face to continue"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use your biometric or screen lock to continue"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometric hardware unavailable"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentication canceled"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Not recognized"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Face not recognized"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentication canceled"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No pin, pattern, or password set"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error authenticating"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 655e123ef6ac..1e7b161b387e 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar datos biométricos o bloqueo de pantalla"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Comprueba que eres tú"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Usa tus datos biométricos para continuar"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Usa tu huella dactilar para continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Usa el rostro para continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Usa tus datos biométricos o bloqueo de pantalla para continuar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"No hay hardware biométrico disponible"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Se canceló la autenticación"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"No se reconoció"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"No se reconoció el rostro"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Se canceló la autenticación"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No se estableció ningún PIN, patrón ni contraseña"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error de autenticación"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index d5dc1bc0a369..5e7f9ecd17e2 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar biometría o bloqueo de pantalla"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica que eres tú"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Usa tu biometría para continuar"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Usa la huella digital para continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Usa la cara para continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Usa la biometría o tu bloqueo de pantalla para continuar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biométrico no disponible"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autenticación cancelada"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"No se reconoce"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Cara no reconocida"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticación cancelada"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No se ha definido el PIN, el patrón o la contraseña"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"No se ha podido autenticar"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index e4c99482166d..4be6e30d9a95 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biomeetria või ekraaniluku kasutamine"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Kinnitage oma isik"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Jätkamiseks kasutage biomeetriat"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Jätkamiseks kasutage oma sõrmejälge"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Jätkamiseks kasutage oma nägu"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Jätkamiseks kasutage oma biomeetrilisi andmeid või ekraanilukku"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biomeetriline riistvara ei ole saadaval"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentimine tühistati"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Ei tuvastatud"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Nägu ei tuvastatud"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentimine tühistati"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN-koodi, mustrit ega parooli pole määratud"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Viga autentimisel"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index be67a1300d48..7835a3991853 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Erabili sistema biometrikoak edo pantailaren blokeoa"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Egiaztatu zeu zarela"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Aurrera egiteko, erabili sistema biometrikoak"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Aurrera egiteko, erabili hatz-marka"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Aurrera egiteko, erabili aurpegia"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Aurrera egiteko, erabili sistema biometrikoak edo pantailaren blokeoa"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biometrikoa ez dago erabilgarri"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Utzi da autentifikazioa"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Ez da ezagutu"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Ez da ezagutu aurpegia"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Utzi egin da autentifikazioa"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Ez da ezarri PIN koderik, eredurik edo pasahitzik"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Errorea autentifikatzean"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 249d0408f4c8..1eaa30e87aa5 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"استفاده از زیستسنجشی یا قفل صفحه"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"تأیید کنید این شمایید"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"برای ادامه، از زیستسنجشی استفاده کنید"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"برای ادامه، از اثر انگشتتان استفاده کنید"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"برای ادامه، از چهرهتان استفاده کنید"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"برای ادامه، از زیستسنجشی یا قفل صفحه استفاده کنید"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"سختافزار زیستسنجی دردسترس نیست"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"اصالتسنجی لغو شد"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"شناسایی نشد"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"چهره شناسایی نشد"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"اصالتسنجی لغو شد"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"پین، الگو یا گذرواژهای تنظیم نشده است"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"خطا هنگام اصالتسنجی"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 5f120c58d766..c23d1373738b 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Käytä biometriikkaa tai näytön lukitusta"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Vahvista henkilöllisyytesi"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Jatka käyttämällä biometriikkaa"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Jatka sormenjäljen avulla"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Jatka kasvojen avulla"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Jatka biometriikan tai näytön lukituksen avulla"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrinen laitteisto ei käytettävissä"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Todennus peruutettu"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Ei tunnistettu"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Kasvoja ei tunnistettu"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Todennus peruutettu"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN-koodia, kuviota tai salasanaa ei ole asetettu"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Virhe todennuksessa"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 0c406de7296f..0423fb7e9270 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utiliser les données biométriques ou le verrouillage de l\'écran"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirmez que c\'est vous"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Utilisez votre méthode d\'authentification biométrique pour continuer"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Utilisez votre empreinte digitale pour continuer"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Utilisez votre visage pour continuer"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Utilisez vos données biométriques ou le verrouillage de l\'écran pour continuer"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Matériel biométrique indisponible"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentification annulée"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Données biométriques non reconnues"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Visage non reconnu"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentification annulée"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Aucun NIP, schéma ou mot de passe défini"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Erreur d\'authentification"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 9f8522ce2981..20ba01ad61e0 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utiliser la biométrie ou le verrouillage de l\'écran"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirmez votre identité"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Utilisez la biométrie pour continuer"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Utilisez votre empreinte digitale pour continuer"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Utilisez la reconnaissance faciale pour continuer"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Utilisez la biométrie ou le verrouillage de l\'écran pour continuer"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Matériel biométrique indisponible"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Authentification annulée"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Non reconnue"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Visage non reconnu"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Authentification annulée"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Aucun code, schéma ni mot de passe n\'est défini"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Erreur d\'authentification"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 53967e6dc25d..d8099688703f 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utilizar desbloqueo biométrico ou credencial do dispositivo"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica que es ti"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Para continuar, utiliza o desbloqueo biométrico"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Usa a impresión dixital para continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Usa o recoñecemento facial para continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Para continuar, utiliza o desbloqueo biométrico ou o bloqueo de pantalla"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"O hardware biométrico non está dispoñible"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Cancelouse a autenticación"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Non se recoñeceu"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Non se recoñeceu a cara"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Cancelouse a autenticación"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Non se estableceu ningún PIN, padrón ou contrasinal"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Produciuse un erro ao realizar a autenticación"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index ab3859e39800..32896f97372e 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"બાયોમેટ્રિક્સ અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"તે તમે જ છો એ ચકાસો"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"આગળ વધવા માટે બાયોમેટ્રિકનો ઉપયોગ કરો"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ચાલુ રાખવા માટે તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ચાલુ રાખવા માટે તમારા ચહેરાનો ઉપયોગ કરો"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ચાલુ રાખવા માટે તમારા બાયોમેટ્રિક ડેટા અથવા સ્ક્રીન લૉક સુવિધાનો ઉપયોગ કરો"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"બાયોમેટ્રિક હાર્ડવેર ઉપલબ્ધ નથી"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"પ્રમાણીકરણ રદ કર્યું"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ઓળખાયેલ નથી"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ચહેરો ઓળખાયો નથી"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"પ્રમાણીકરણ રદ કર્યું"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"કોઈ પિન, પૅટર્ન અથવા પાસવર્ડ સેટ કરેલો નથી"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"પ્રમાણિત કરવામાં ભૂલ આવી"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 4c66168f36a8..0a30ee6b93b0 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"बायोमेट्रिक्स या स्क्रीन लॉक का क्रेडेंशियल इस्तेमाल करें"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"अपनी पहचान की पुष्टि करें"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"जारी रखने के लिए, बायोमेट्रिक्स इस्तेमाल करें"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"जारी रखने के लिए, अपने फ़िंगरप्रिंट की मदद से पहचान की पुष्टि करें"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"जारी रखने के लिए, अपने चेहरा की मदद से पहचान की पुष्टि करें"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"जारी रखने के लिए, बायोमेट्रिक या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"बायोमेट्रिक हार्डवेयर उपलब्ध नहीं है"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"प्रमाणीकरण रद्द किया गया"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"पहचान नहीं हो पाई"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"चेहरा नहीं पहचाना गया"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"प्रमाणीकरण रद्द किया गया"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"पिन, पैटर्न या पासवर्ड सेट नहीं है"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"गड़बड़ी की पुष्टि की जा रही है"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index eb8d11118970..177605051486 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Upotreba biometrijske autentifikacije ili zaključavanja zaslona"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrdite da ste to vi"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Upotrijebite svoju biometrijsku autentifikaciju da biste nastavili"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Za nastavak upotrijebite otisak prsta"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Za nastavak se identificirajte licem"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Za nastavak se identificirajte biometrijski ili vjerodajnicom zaključavanja zaslona"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrijski hardver nije dostupan"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentifikacija otkazana"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nije prepoznato"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Lice nije prepoznato"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentifikacija otkazana"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nisu postavljeni PIN, uzorak ni zaporka"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Pogreška prilikom autentifikacije"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 793fc8699d1e..806edf981199 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"A folytatás biometriai feloldással vagy képernyőzárral lehetséges"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Igazolja, hogy Ön az"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"A folytatás biometriai feloldással lehetséges"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"A folytatáshoz használja ujjlenyomatát"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"A folytatáshoz használja az arcalapú feloldást"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"A folytatás biometriai feloldással vagy a képernyőzár feloldásával lehetséges"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrikus hardver nem áll rendelkezésre"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Hitelesítés megszakítva"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nem ismerhető fel"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Sikertelen arcfelismerés"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Hitelesítés megszakítva"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nem állított be PIN-kódot, mintát vagy jelszót."</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Hiba történt a hitelesítés közben"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index da1b5dc71889..52240f52227a 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Օգտագործել կենսաչափական համակարգեր կամ էկրանի կողպում"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Հաստատեք ձեր ինքնությունը"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Շարունակելու համար օգտագործեք կենսաչափական համակարգեր"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Շարունակելու համար օգտագործեք ձեր մատնահետքը"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Շարունակելու համար օգտագործեք դեմքով իսկորոշումը"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Շարունակելու համար օգտագործեք ձեր կենսաչափական տվյալները կամ էկրանի կողպումը"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Կենսաչափական սարքը հասանելի չէ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Նույնականացումը չեղարկվեց"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Չհաջողվեց ճանաչել"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Դեմքը չի ճանաչվել"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Նույնականացումը չեղարկվեց"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Ավելացրեք PIN կոդ, նախշ կամ գաղտնաբառ։"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Չհաջողվեց նույնականացնել"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index af5e5fe1d70f..3e4250a877ad 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gunakan biometrik atau kunci layar"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifikasi bahwa ini memang Anda"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Gunakan biometrik untuk melanjutkan"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Gunakan sidik jari untuk melanjutkan"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Gunakan wajah untuk melanjutkan"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Gunakan biometrik atau kunci layar untuk melanjutkan"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biometrik tidak tersedia"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentikasi dibatalkan"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Tidak dikenali"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Wajah tidak dikenali"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentikasi dibatalkan"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Tidak ada PIN, pola, atau sandi yang disetel"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Error saat mengautentikasi"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index b43935f17844..0150b3921a6e 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Nota lífkenni eða skjálás"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Staðfestu hver þú ert"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Notaðu lífkenni til að halda áfram"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Notaðu fingrafarið til að halda áfram"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Notaðu andlitið til að halda áfram"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Notaðu lífkenni eða skjálás til að halda áfram"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Lífkennavélbúnaður ekki tiltækur"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Hætt við auðkenningu"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Þekktist ekki"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Andlit þekkist ekki"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Hætt við auðkenningu"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Ekkert PIN-númer, mynstur eða aðgangsorð stillt"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Villa við auðkenningu"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 895d54a4c8b2..f6086f48b03a 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usa la biometria o il blocco schermo"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica la tua identità"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Usa la biometria per continuare"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Utilizza la tua impronta per continuare"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Usa il tuo volto per continuare"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Per continuare devi usare i tuoi dati biometrici o il tuo blocco schermo"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biometrico non disponibile"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autenticazione annullata"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Non riconosciuto"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Volto non riconosciuto"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticazione annullata"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Non hai impostato PIN, sequenza o password"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Errore durante l\'autenticazione"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index cc032849fc28..13ba477ede36 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"שימוש במידע ביומטרי בנעילת מסך"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"אימות הזהות שלך"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"יש להשתמש במידע ביומטרי כדי להמשיך"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"צריך להשתמש בטביעת האצבע כדי להמשיך"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"צריך להשתמש בזיהוי הפנים כדי להמשיך"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"יש להשתמש במידע הביומטרי או בנעילת המסך כדי להמשיך"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"חומרה ביומטרית לא זמינה"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"האימות בוטל"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"לא זוהתה"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"הפנים לא זוהו"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"האימות בוטל"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"עוד לא הוגדרו קוד אימות, קו ביטול נעילה או סיסמה"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"שגיאה באימות"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 66d6852e0e2e..a4adcf611c60 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"生体認証または画面ロックの使用"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"本人確認"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"続行するには生体認証を使用してください"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"続行するには指紋認証を使用してください"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"続行するには顔認証を使用してください"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"続行するには、生体認証または画面ロックを使用してください"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"生体認証ハードウェアが利用できません"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"認証をキャンセルしました"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"認識されませんでした"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"顔を認識できません"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"認証をキャンセルしました"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN、パターン、パスワードが設定されていません"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"エラー認証"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index c7fa7d0b2671..cd4df7ff40ce 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"გამოიყენეთ ბიომეტრიული სისტემა ან ეკრანის დაბლოკვა"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"დაადასტურეთ ვინაობა"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"გასაგრძელებლად გამოიყენეთ თქვენი ბიომეტრიული მონაცემები"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"გასაგრძელებლად გამოიყენეთ თქვენი თითის ანაბეჭდი"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"გასაგრძელებლად გამოიყენეთ სახის ამოცნობა"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"გასაგრძელებლად გამოიყენეთ თქვენი ბიომეტრიული მონაცემები ან ეკრანის განბლოკვის ნიმუში"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ბიომეტრიული აპარატურა მიუწვდომელია"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ავტორიზაცია გაუქმდა"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"არ არის ამოცნობილი"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"სახის ამოცნობა ვერ მოხერხდა"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ავტორიზაცია გაუქმდა"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN-კოდი, ნიმუში ან პაროლი დაყენებული არ არის"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"შეცდომა ავთენტიკაციისას"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 09c9bfb3244f..22db3f647b0e 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Биометриканы немесе экран құлпын пайдалану"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Бұл сіз екеніңізді растаңыз"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Жалғастыру үшін биометрикаңызды пайдаланыңыз."</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Жалғастыру үшін саусақ ізін пайдаланыңыз."</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Жалғастыру үшін бетті анықтау функциясын пайдаланыңыз."</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Жалғастыру үшін биометриканы немесе экран құлпын пайдаланыңыз."</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометрикалық жабдық жоқ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Аутентификациядан бас тартылды."</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Танылмады"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Бет танылмады."</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Аутентификациядан бас тартылды."</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Ешқандай PIN коды, өрнек немесе құпия сөз орнатылмаған."</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Аутентификациялауда қате шықты."</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 65c19838910b..d40e12ebce9e 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ប្រើជីវមាត្រ ឬការចាក់សោអេក្រង់"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ផ្ទៀងផ្ទាត់ថាជាអ្នក"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ប្រើជីវមាត្ររបស់អ្នក ដើម្បីបន្ត"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ប្រើស្នាមម្រាមដៃរបស់អ្នក ដើម្បីបន្ត"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ប្រើមុខរបស់អ្នក ដើម្បីបន្ត"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ប្រើការចាក់សោអេក្រង់ ឬជីវមាត្ររបស់អ្នក ដើម្បីបន្ត"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"មិនអាចប្រើឧបករណ៍ស្កេនស្នាមម្រាមដៃបានទេ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"បានបោះបង់ការផ្ទៀងផ្ទាត់"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"មិនអាចសម្គាល់បានទេ"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"មិនស្គាល់មុខ"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"បានបោះបង់ការផ្ទៀងផ្ទាត់"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"គ្មានការកំណត់កូដ pin លំនាំ ឬពាក្យសម្ងាត់ទេ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"មានបញ្ហាក្នុងការផ្ទៀងផ្ទាត់"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 011dfb6ffa6e..e351d7f5af78 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ಇದು ನೀವೇ ಎಂದು ಪರಿಶೀಲಿಸಿ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಬಯೋಮೆಟ್ರಿಕ್ ಬಳಸಿ"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಿ"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಮುಖವನ್ನು ಬಳಸಿ"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಬಯೋಮೆಟ್ರಿಕ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್ವೇರ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ಪ್ರಮಾಣೀಕರಣವನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ಮುಖವನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ಪ್ರಮಾಣೀಕರಣವನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"ಪಿನ್, ಪ್ಯಾಟರ್ನ್ ಅಥವಾ ಪಾಸ್ವರ್ಡ್ ಸೆಟ್ ಮಾಡಿಲ್ಲ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"ದೃಢೀಕರಿಸುವಾಗ ದೋಷ ಎದುರಾಗಿದೆ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 6da3465c6a49..f15415ff7172 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"생체 인식 또는 화면 잠금을 사용"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"본인 확인"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"생체 인식을 사용하여 계속하세요"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"계속하려면 지문을 인증하세요"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"계속하려면 얼굴로 인증하세요"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"계속하려면 생체 인식이나 화면 잠금을 사용하세요"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"생체 인식 하드웨어를 사용할 수 없음"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"인증이 취소되었습니다."</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"인식할 수 없음"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"얼굴을 인식할 수 없습니다."</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"인증이 취소되었습니다."</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN, 패턴, 비밀번호가 설정되지 않음"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"인증 오류"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index b04d4f719e2d..dece887c9c63 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Биометрикалык жөндөөнү же экрандын кулпусун колдонуу"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Өзүңүздү ырастаңыз"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Улантуу үчүн биометрикалык жөндөөнү колдонуу"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Улантуу үчүн манжаңызды сканерге тийгизиңиз"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Улантуу үчүн жүзүңүздү көрсөтүңүз"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Улантуу үчүн биометрикалык маалыматты же экрандын кулпусун колдонуңуз"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометрикалык аппарат жеткиликсиз"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Аныктыгын текшерүү жокко чыгарылды"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Таанылган жок"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Жүз таанылган жок"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Аныктыгын текшерүү жокко чыгарылды"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN код, графикалык ачкыч же сырсөз коюлган жок"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Аутентификация катасы"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 15517b5ee3e3..6ab7ff0f274d 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ໃຊ້ລະບົບຊີວະມິຕິ ຫຼື ການລັອກໜ້າຈໍ"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ຢັ້ງຢືນວ່າແມ່ນທ່ານ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ໃຊ້ລະບົບຊີວະມິຕິຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ໃຊ້ລາຍນິ້ວມືຂອງທ່ານເພື່ອສືບຕໍ່"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ໃຊ້ໃບໜ້າຂອງທ່ານເພື່ອສືບຕໍ່"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ໃຊ້ລະບົບຊີວະມິຕິ ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ຮາດແວຊີວະມິຕິບໍ່ສາມາດໃຊ້ໄດ້"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ຍົກເລີກການຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ບໍ່ຮັບຮູ້"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ຍົກເລີກການຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"ບໍ່ໄດ້ຕັ້ງ PIN, ຮູບແບບປົດລັອກ ຫຼື ລະຫັດຜ່ານ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"ເກີດຄວາມຜິດພາດໃນການພິສູດຢືນຢັນ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 6a12170004c8..a13539460b2f 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Naudoti biometrinius duomenis arba ekrano užraktą"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Patvirtinkite, kad tai jūs"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Norėdami tęsti, naudokite biometrinius duomenis"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Jei norite tęsti, naudokite piršto atspaudą"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Jei norite tęsti, naudokite veido atpažinimo funkciją"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Jei norite tęsti, naudokite biometrinius duomenis arba ekrano užraktą"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrinė aparatinė įranga nepasiekiama"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentifikavimas atšauktas"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Neatpažinta"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Veidas neatpažintas"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentifikavimas atšauktas"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nenustatytas PIN kodas, atrakinimo piešinys arba slaptažodis"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Autentifikuojant įvyko klaida"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index fade02ed8dac..ed871bb5d9ed 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrijas vai ekrāna bloķēšanas izmantošana"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Apstipriniet, ka tas esat jūs"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Lai turpinātu, izmantojiet biometriju"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Izmantojiet pirksta nospiedumu, lai turpinātu"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Izmantojiet autorizāciju pēc sejas, lai turpinātu"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Izmantojiet biometrijas datus vai ekrāna bloķēšanas opciju, lai turpinātu"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrisko datu aparatūra nav pieejama"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentifikācija ir atcelta"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Dati nav atpazīti"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Seja netika atpazīta"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentifikācija ir atcelta"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN, kombinācija vai parole nav iestatīta"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Autentifikācijas kļūda"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 4fb53a7e510a..4b556fa3984b 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Користи биометрика или заклучен екран"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Потврдете дека сте вие"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Користете ја вашата биометрика за да продолжите"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Користете го отпечатокот за да продолжите"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Користете го вашиот лик за да продолжите"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Користете ја вашата биометрика или заклучување екран за да продолжите"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометрискиот хардвер е недостапен"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Проверката е откажана"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Непознат"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Ликот не е препознаен"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Проверката е откажана"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Не е поставен PIN, шема или лозинка"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при проверката"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index c3b86e382399..1db7773c7c01 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ബയോമെട്രിക്സ് അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ഇത് നിങ്ങളാണെന്ന് പരിശോധിച്ചുറപ്പിക്കുക"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"തുടരാൻ ബയോമെട്രിക് ഉപയോഗിക്കുക"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"തുടരാൻ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"തുടരാൻ നിങ്ങളുടെ മുഖം ഉപയോഗിക്കുക"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"തുടരാൻ നിങ്ങളുടെ ബയോമെട്രിക് അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ബയോമെട്രിക് ഹാർഡ്വെയർ ലഭ്യമല്ല"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കി"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"തിരിച്ചറിഞ്ഞില്ല"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"മുഖം തിരിച്ചറിഞ്ഞിട്ടില്ല"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കി"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"പിന്നോ പാറ്റേണോ പാസ്വേഡോ സജ്ജീകരിച്ചിട്ടില്ല"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"പിശക് പരിശോധിച്ചുറപ്പിക്കുന്നു"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index b69fb83dde35..866f808be4d1 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Биометр эсвэл дэлгэцийн түгжээ ашиглах"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Өөрийгөө мөн гэдгийг баталгаажуулаарай"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Үргэлжлүүлэхийн тулд биометрээ ашиглана уу"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Үргэлжлүүлэхийн тулд хурууныхаа хээг ашиглана уу"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Үргэлжлүүлэхийн тулд царайгаа ашиглана уу"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Үргэлжлүүлэхийн тулд биометр эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометрийн техник хангамж боломжгүй байна"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Нотолгоог цуцаллаа"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Таниагүй"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Царайг таньсангүй"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Нотолгоог цуцаллаа"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Тохируулсан пин, хээ эсвэл нууц үг алга"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Баталгаажуулахад алдаа гарлаа"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index cb6191101512..754762dcf9a8 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"बायोमेट्रिक किंवा स्क्रीन लॉक वापरा"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"हे तुम्हीच आहात याची पडताळणी करा"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"पुढे सुरू ठेवण्यासाठी तुमचे बायोमेट्रिक वापरा"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"पुढे सुरू ठेवण्यासाठी तुमची फिंगरप्रिंट वापरा"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"पुढे सुरू ठेवण्यासाठी तुमचा चेहरा वापरा"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"पुढे सुरू ठेवण्यासाठी तुमचे बायोमेट्रिक किंवा स्क्रीन लॉक वापरा"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"बायोमेट्रिक हार्डवेअर उपलब्ध नाही"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ऑथेंटिकेशन रद्द केले"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ओळखले नाही"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"चेहरा ओळखता आला नाही"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ऑथेंटिकेशन रद्द केले"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"कोणताही पिन, पॅटर्न किंवा पासवर्ड सेट केलेला नाही"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"एरर ऑथेंटिकेट करत आहे"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index f62c70690f05..8f6992fa81ae 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gunakan biometrik atau kunci skrin"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Sahkan itu anda"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Gunakan biometrik anda untuk meneruskan"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Gunakan cap jari anda untuk teruskan"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Gunakan muka anda untuk teruskan"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Gunakan biometrik atau kunci skrin anda untuk meneruskan pengesahan"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Perkakasan biometrik tidak tersedia"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Pengesahan dibatalkan"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Tidak dikenali"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Wajah tidak dikenali"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Pengesahan dibatalkan"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pin, corak atau kata laluan tidak ditetapkan"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Ralat semasa membuat pengesahan"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index d2fc38fe01ab..499be48ca6f1 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ဇီဝမက်ထရစ်အချက်အလက်များ (သို့) ဖန်သားပြင်လော့ခ်ချခြင်းကို သုံးခြင်း"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"သင်ဖြစ်ကြောင်း အတည်ပြုပါ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ရှေ့ဆက်ရန် သင်၏ ဇီဝမက်ထရစ်အချက်အလက်ကို သုံးပါ"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ရှေ့ဆက်ရန် သင့်လက်ဗွေကို သုံးပါ"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ရှေ့ဆက်ရန် သင့်မျက်နှာကို သုံးပါ"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ရှေ့ဆက်ရန် သင်၏ ဇီဝမက်ထရစ်အချက်အလက် (သို့) ဖန်သားပြင်လော့ခ်ကို သုံးပါ"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ဇီဝအချက်အလက်သုံး ကွန်ပျူတာစက်ပစ္စည်း မရရှိနိုင်ပါ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"အထောက်အထားစိစစ်ခြင်းကို ပယ်ဖျက်လိုက်သည်"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"မသိ"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"မျက်နှာကို မသိရှိပါ"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"အထောက်အထားစိစစ်ခြင်းကို ပယ်ဖျက်လိုက်သည်"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"ပင်နံပါတ်၊ လော့ခ်ပုံစံ သို့မဟုတ် စကားဝှက် သတ်မှတ်မထားပါ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"အထောက်အထားစိစစ်ရာတွင် အမှားအယွင်းရှိနေသည်"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 15ef328cfbb0..e0954cc2efe9 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Bruk biometri eller skjermlås"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Bekreft at det er deg"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Bruk biometri for å fortsette"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Bruk fingeravtrykket for å fortsette"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Bruk ansiktet for å fortsette"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Bruk biometri eller skjermlåsen for å fortsette"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrisk maskinvare er utilgjengelig"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentiseringen er avbrutt"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Ikke gjenkjent"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Gjenkjenner ikke ansiktet"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentiseringen er avbrutt"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN-kode, mønster eller passord er ikke angitt"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Feil under autentiseringen"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 92ee0a1cad69..468e3da720ae 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"बायोमेट्रिक्स वा स्क्रिन लक प्रयोग गर्नुहोस्"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"यो व्यक्ति तपाईं नै हो भन्ने प्रमाणित गर्नुहोस्"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"जारी राख्न आफ्नो बायोमेट्रिक प्रयोग गर्नुहोस्"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"जारी राख्न आफ्नो फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"जारी राख्न आफ्नो अनुहार प्रयोग गर्नुहोस्"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"जारी राख्न आफ्नो बायोमेट्रिक वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"बायोमेट्रिक हार्डवेयर उपलब्ध छैन"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"प्रमाणीकरण रद्द गरियो"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"पहिचान भएन"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"अनुहार पहिचान गर्न सकिएन"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"प्रमाणीकरण रद्द गरियो"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"कुनै पनि PIN, ढाँचा वा पासवर्ड सेट गरिएको छैन"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"प्रमाणित गर्ने क्रममा त्रुटि भयो"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 5cf334cde115..da7fc0fce7cf 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrische gegevens of schermvergrendeling gebruiken"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Je identiteit verifiëren"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Gebruik je biometrische gegevens om door te gaan"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Gebruik je vingerafdruk om door te gaan"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Gebruik je gezicht om door te gaan"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Gebruik je biometrische gegevens of schermvergrendeling om door te gaan"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrische hardware niet beschikbaar"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Verificatie geannuleerd"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Niet herkend"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Gezicht niet herkend"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Verificatie geannuleerd"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Geen pincode, patroon of wachtwoord ingesteld"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Fout bij verificatie"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 4dba4ab8621e..b48e954059ce 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ବାୟୋମେଟ୍ରିକ୍ସ ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ଏହା ଆପଣ ବୋଲି ଯାଞ୍ଚ କରନ୍ତୁ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ବାୟୋମେଟ୍ରିକ୍ସ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଫେସ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ବାୟୋମେଟ୍ରିକ୍ କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ବାୟୋମେଟ୍ରିକ୍ ହାର୍ଡୱେର୍ ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ପ୍ରାମାଣିକତାକୁ ବାତିଲ୍ କରାଯାଇଛି"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ପ୍ରାମାଣିକତାକୁ ବାତିଲ୍ କରାଯାଇଛି"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"କୌଣସି ପିନ୍, ପେଟେର୍ନ ବା ପାସ୍ୱର୍ଡ ସେଟ୍ ନାହିଁ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"ପ୍ରାମାଣିକରଣ କରିବା ସମୟରେ ତ୍ରୁଟି"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 41aad16fd2a6..3790fd4f35e7 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ਬਾਇਓਮੈਟ੍ਰਿਕ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣੇ ਬਾਇਓਮੈਟ੍ਰਿਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣੇ ਚਿਹਰੇ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਬਾਇਓਮੈਟ੍ਰਿਕ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ਬਾਇਓਮੈਟ੍ਰਿਕ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ਪ੍ਰਮਾਣੀਕਰਨ ਰੱਦ ਕੀਤਾ ਗਿਆ"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ਪ੍ਰਮਾਣੀਕਰਨ ਰੱਦ ਕੀਤਾ ਗਿਆ"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"ਕੋਈ ਪਿੰਨ, ਪੈਟਰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"ਗੜਬੜ ਨੂੰ ਪ੍ਰਮਾਣਿਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 7a8684f4e8bc..0f7951ae0eda 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Używaj biometrii lub blokady ekranu"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Potwierdź, że to Ty"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Użyj biometrii, by kontynuować"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Aby kontynuować, użyj odcisku palca"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Aby kontynuować, użyj rozpoznawania twarzy"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Aby kontynuować, użyj biometrii lub blokady ekranu"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Sprzęt biometryczny niedostępny"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Anulowano uwierzytelnianie"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nie rozpoznano"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Nie rozpoznano twarzy"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Anulowano uwierzytelnianie"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nie ustawiono kodu PIN, wzoru ani hasła"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Podczas uwierzytelniania wystąpił błąd"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 0a6f769a13dc..6a00cd61d8f2 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar biometria ou bloqueio de tela"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme que é você"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use seus dados biométricos para continuar"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use sua impressão digital para continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use seu rosto para continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use sua autenticação biométrica ou o bloqueio de tela para continuar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biométrico indisponível"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autenticação cancelada"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Não reconhecido"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Rosto não reconhecido"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticação cancelada"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nenhum PIN, padrão ou senha configurado"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Erro na autenticação"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 83e7cea8a9c0..c4de8e512c17 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar a biometria ou o bloqueio de ecrã"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme a sua identidade"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Utilize a biometria para continuar."</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use a impressão digital para continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use o rosto para continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Utilize a biometria ou o bloqueio de ecrã para continuar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biométrico indisponível."</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autenticação cancelada"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Não reconhecido."</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Rosto não reconhecido"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticação cancelada"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nenhum PIN, padrão ou palavra-passe definidos."</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Erro ao autenticar."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 0a6f769a13dc..6a00cd61d8f2 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar biometria ou bloqueio de tela"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme que é você"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Use seus dados biométricos para continuar"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Use sua impressão digital para continuar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Use seu rosto para continuar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Use sua autenticação biométrica ou o bloqueio de tela para continuar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biométrico indisponível"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autenticação cancelada"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Não reconhecido"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Rosto não reconhecido"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticação cancelada"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nenhum PIN, padrão ou senha configurado"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Erro na autenticação"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 2c58ed5ac323..255c282755ba 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Folosește sistemele biometrice sau blocarea ecranului"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirmă-ți identitatea"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Folosește sistemele biometrice pentru a continua"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Folosește amprenta pentru a continua"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Folosește-ți chipul pentru a continua"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Folosește sistemele biometrice sau blocarea ecranului pentru a continua"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Hardware biometric indisponibil"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentificarea a fost anulată"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nu este recunoscut"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Fața nu a fost recunoscută"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentificarea a fost anulată"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nu este setat un cod PIN, un model sau o parolă"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Eroare la autentificare"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index e48c48711a3b..f9ac8877a523 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Использовать биометрию или блокировку экрана"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Подтвердите, что это вы"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Чтобы продолжить, используйте биометрические данные."</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Чтобы продолжить, прикоснитесь пальцем к сканеру."</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Чтобы продолжить, используйте фейсконтроль."</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Чтобы продолжить, используйте биометрию или данные для разблокировки экрана."</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометрическое оборудование недоступно"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Аутентификация отменена"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Не распознано"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Лицо не распознано."</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Аутентификация отменена"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Укажите PIN-код, пароль или графический ключ"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Ошибка аутентификации."</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 0df5c652a35a..1fe77c180a91 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ජෛවමිතික හෝ තිර අගුල භාවිත කරන්න"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"එය ඔබ බව තහවුරු කරන්න"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ඉදිරියට යාමට ඔබගේ ජෛවමිතික භාවිත කරන්න"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ඉදිරියට යාමට ඔබේ ඇඟිලි සලකුණ භාවිත කරන්න"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ඉදිරියට යාමට ඔබේ මුහුණ භාවිත කරන්න"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ඉදිරියට යාමට ඔබගේ ජෛවමිතික හෝ තිර අගුල භාවිත කරන්න"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ජීවමිතික දෘඪාංග ලබා ගත නොහැකිය"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"සත්යාපනය අවලංගු කළා"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"හඳුනා නොගන්නා ලදී"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"මුහුණ හඳුනා නොගන්නා ලදි"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"සත්යාපනය අවලංගු කළා"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"රහස් අංක, රටා, හෝ මුරපද කිසිවක් සකසා නැත"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"සත්යාපනය කිරීමේ දෝෂයකි"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index d4cfcf9b5524..b81af1cc08d6 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Použiť biometrické údaje alebo zámku obrazovky"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Overenie, že ste to vy"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Ak chcete pokračovať, použite biometrický údaj"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Pokračujte nasnímaním odtlačku prsta"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Pokračujte nasnímaním tváre"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Pokračujte použitím biometrických údajov alebo zámky obrazovky"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrický hardvér nie je k dispozícii"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Overenie bolo zrušené"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nerozpoznané"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Tvár nebola rozpoznaná"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Overenie bolo zrušené"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nie je nastavený PIN, vzor ani heslo"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Chyba overenia"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 1b06b0f31e0a..927686f7a719 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Uporaba biometrike ali odklepanja s poverilnico"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Preverite, da ste res vi"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Za nadaljevanje uporabite biometrični podatek."</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Za nadaljevanje uporabite prstni odtis"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Za nadaljevanje uporabite obraz"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Za nadaljevanje uporabite biometrični podatek ali odklepanje s poverilnico."</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Strojna oprema za biometrične podatke ni na voljo"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Preverjanje pristnosti je preklicano"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Ni prepoznano"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Obraz ni prepoznan"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Preverjanje pristnosti je preklicano"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nastavljena ni nobena koda PIN, vzorec ali geslo"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Napaka pri preverjanju pristnosti"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 82d92c1d9039..2382ec51bdd4 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Përdor sistemet biometrike ose kyçjen e ekranit"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifiko që je ti"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Përdor sistemet e tua biometrike për të vazhduar"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Përdor gjurmën e gishtit për të vazhduar"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Përdor fytyrën tënde për të vazhduar"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Përdor sistemet e tua biometrike ose kyçjen e ekranit për të vazhduar"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Nuk ofrohet harduer biometrik"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Vërtetimi u anulua"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Nuk njihet"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Fytyra nuk njihet"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Vërtetimi u anulua"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nuk është vendosur kod PIN, motiv ose fjalëkalim"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Gabim gjatë vërtetimit"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index ef2456e24bae..9d0c8e6a21d0 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -617,10 +617,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Користите биометрију или закључавање екрана"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Потврдите свој идентитет"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Користите биометријски податак да бисте наставили"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Наставите помоћу отиска прста"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Потврдите идентитет лицем да бисте наставили"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Користите биометријски податак или закључавање екрана да бисте наставили"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометријски хардвер није доступан"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Потврда идентитета је отказана"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Није препознато"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Лице није препознато"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Потврда идентитета је отказана"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Нисте подесили ни PIN, ни шаблон, ни лозинку"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при потврди идентитета"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index c40b2055986d..75457af4721c 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Använd biometrisk data eller skärmlåset"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifiera din identitet"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Fortsätt med hjälp av din biometriska data"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Fortsätt med hjälp av ditt fingeravtryck"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Fortsätt med hjälp av ditt ansikte"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Fortsätt med hjälp av din biometriska data eller skärmlåset"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrisk maskinvara är inte tillgänglig"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentiseringen avbröts"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Identifierades inte"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Ansiktet känns inte igen"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentiseringen avbröts"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pinkod, mönster eller lösenord har inte angetts"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Ett fel uppstod vid autentiseringen"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index caf09cbd81c6..67ff43cb33e4 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Tumia bayometriki au mbinu ya kufunga skrini"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Thibitisha kuwa ni wewe"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Tumia bayometriki yako ili uendelee"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Tumia alama ya kidole chako ili uendelee"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Tumia uso wako ili uendelee"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Tumia bayometriki au mbinu yako ya kufunga skrini ili uendelee"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Maunzi ya bayometriki hayapatikani"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Imeghairi uthibitishaji"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Hayatambuliki"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Imeshindwa kutambua uso"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Imeghairi uthibitishaji"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Hujaweka pin, mchoro au nenosiri"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Hitilafu imetokea wakati wa uthibitishaji"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 4c765ed52773..d7cd1fed5f80 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"பயோமெட்ரிக்ஸையோ திரைப் பூட்டையோ பயன்படுத்து"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"நீங்கள்தான் என உறுதிசெய்க"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"தொடர உங்கள் பயோமெட்ரிக்கைப் பயன்படுத்துங்கள்"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"தொடர்வதற்கு உங்கள் கைரேகையைப் பயன்படுத்துங்கள்"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"தொடர்வதற்கு உங்கள் முகத்தைப் பயன்படுத்துங்கள்"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"தொடர, உங்கள் பயோமெட்ரிக்கையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"பயோமெட்ரிக் வன்பொருள் இல்லை"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"அங்கீகரிப்பு ரத்தானது"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"அடையாளங்காணபடவில்லை"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"முகத்தைக் கண்டறிய முடியவில்லை"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"அங்கீகரிப்பு ரத்தானது"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"பின்னோ, பேட்டர்னோ, கடவுச்சொல்லோ அமைக்கப்படவில்லை"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"அங்கீகரிப்பதில் பிழை"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 19a3e4e9ac81..92ac5d7dcd01 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"బయోమెట్రిక్స్ను లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ఇది మీరేనని వెరిఫై చేసుకోండి"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"కొనసాగించడానికి, మీ బయోమెట్రిక్ను ఉపయోగించండి"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"కొనసాగించడానికి మీ వేలిముద్రను ఉపయోగించండి"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"కొనసాగించడానికి మీ ముఖాన్ని ఉపయోగించండి"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"కొనసాగించడానికి మీ బయోమెట్రిక్ లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"బయోమెట్రిక్ హార్డ్వేర్ అందుబాటులో లేదు"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ప్రమాణీకరణ రద్దు చేయబడింది"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"గుర్తించలేదు"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ముఖం గుర్తించబడలేదు"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ప్రమాణీకరణ రద్దు చేయబడింది"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"పిన్, ఆకృతి లేదా పాస్వర్డ్ సెట్ చేయబడలేదు"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"ప్రామాణీకరిస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 107a66a77710..9f115a427be1 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ใช้ข้อมูลไบโอเมตริกหรือการล็อกหน้าจอ"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ยืนยันว่าเป็นตัวคุณ"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"ใช้ข้อมูลไบโอเมตริกเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"ใช้ลายนิ้วมือของคุณเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"ใช้ใบหน้าของคุณเพื่อดำเนินการต่อ"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"ใช้ข้อมูลไบโอเมตริกหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"ฮาร์ดแวร์ไบโอเมตริกไม่พร้อมใช้งาน"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"ยกเลิกการตรวจสอบสิทธิ์แล้ว"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"ไม่รู้จัก"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"ไม่รู้จักใบหน้า"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"ยกเลิกการตรวจสอบสิทธิ์แล้ว"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"ไม่ได้ตั้ง PIN, รูปแบบ หรือรหัสผ่าน"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"การตรวจสอบข้อผิดพลาด"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 549882b8480d..d57c17aff783 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gumamit ng biometrics o lock ng screen"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"I-verify na ikaw ito"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Gamitin ang iyong biometric para magpatuloy"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Gamitin ang iyong fingerprint para magpatuloy"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Gamitin ang iyong mukha para magpatuloy"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Gamitin ang iyong biometric o lock ng screen para magpatuloy"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Walang biometric hardware"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Nakansela ang pag-authenticate"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Hindi nakilala"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Hindi nakilala ang mukha"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Nakansela ang pag-authenticate"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Walang itinakdang pin, pattern, o password"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Nagkaroon ng error sa pag-authenticate"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 12b7b6c09c96..623150ed9927 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biyometri veya ekran kilidi kullan"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Siz olduğunuzu doğrulayın"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Devam etmek için biyometri kullanın"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Devam etmek için parmak izinizi kullanın"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Devam etmek için yüzünüzü kullanın"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Devam etmek için biyometrik kimlik bilginizi veya ekran kilidinizi kullanın"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biyometrik donanım kullanılamıyor"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Kimlik doğrulama iptal edildi"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Tanınmadı"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Yüz tanınmadı"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Kimlik doğrulama iptal edildi"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN, desen veya şifre seti yok"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Kimlik doğrulama sırasında hata oluştu"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index c6ba301a0a7f..64f1e90a7bbf 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -618,10 +618,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Використовувати біометрію або дані для розблокування екрана"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Підтвердьте, що це ви"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Щоб продовжити, скористайтеся біометрією"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Щоб продовжити, скористайтеся відбитком пальця"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Щоб продовжити, скористайтеся фейс-контролем"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Щоб продовжити, скористайтеся біометрією або даними для розблокування екрана"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Біометричне апаратне забезпечення недоступне"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Автентифікацію скасовано"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Не розпізнано"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Обличчя не розпізнано"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Автентифікацію скасовано"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Не вказано PIN-код, ключ або пароль"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Помилка автентифікації"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index e692be7d9f7c..c42f7d542b7a 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"بایو میٹرکس یا اسکرین لاک استعمال کریں"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"توثیق کریں کہ یہ آپ ہیں"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"جاری رکھنے کیلئے اپنا بایو میٹرک استعمال کریں"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"جاری رکھنے کے لیے اپنا فنگر پرنٹ استعمال کریں"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"جاری رکھنے کے لیے اپنے چہرے کا استعمال کریں"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"جاری رکھنے کے لیے اپنے بایو میٹرک اور اسکرین لاک کا استعمال کریں"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"بایومیٹرک ہارڈ ویئر دستیاب نہیں ہے"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"تصدیق کا عمل منسوخ ہو گیا"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"تسلیم شدہ نہیں ہے"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"چہرے کی شناخت نہیں ہو سکی"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"تصدیق کا عمل منسوخ ہو گیا"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"کوئی پن، پیٹرن، یا پاس ورڈ سیٹ نہیں ہے"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"خرابی کی توثیق ہو رہی ہے"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index bb9cbd28b680..0b0c7c6388b4 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrika yoki ekran qulfi"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Oʻzingizni taniting"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Davom etish uchun biometrik tasdiqlang"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Davom etish uchun barmoq izingizdan foydalaning"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Yuz tekshiruvi bilan davom eting"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Davom etish uchun biometrika yoki ekran qulfidan foydalaning"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Biometrik sensor ishlamayapti"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentifikatsiya bekor qilindi"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Aniqlanmadi"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Yuz aniqlanmadi"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Autentifikatsiya bekor qilindi"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"PIN kod, grafik kalit yoki parol sozlanmagan"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Autentifikatsiya amalga oshmadi"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 83730d5862df..29670716bd5f 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Dùng dữ liệu sinh trắc học hoặc phương thức khóa màn hình"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Xác minh danh tính của bạn"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Dùng dữ liệu sinh trắc học của bạn để tiếp tục"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Hãy dùng vân tay để tiếp tục"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Hãy dùng khuôn mặt để tiếp tục"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Dùng dữ liệu sinh trắc học của bạn hoặc phương thức khóa màn hình để tiếp tục"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Không có phần cứng sinh trắc học"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Đã hủy xác thực"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Không nhận dạng được"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Không nhận dạng được khuôn mặt"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Đã hủy xác thực"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Chưa đặt mã PIN, hình mở khóa hoặc mật khẩu"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Lỗi khi xác thực"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 77e9363b520d..d145bebab159 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"使用生物识别或屏幕锁定凭据"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"验证是您本人在操作"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"使用生物识别验证身份才能继续"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"如需继续操作,请使用指纹验证身份"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"如需继续操作,请刷脸验证身份"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"使用生物识别或屏幕锁定凭据验证身份,才能继续操作"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"生物识别硬件无法使用"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"身份验证已取消"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"无法识别"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"无法识别面孔"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"身份验证已取消"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"未设置任何 PIN 码、图案和密码"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"进行身份验证时出错"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index e81fb3842b15..6750ef5cd90b 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"使用生物識別或螢幕鎖定"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"驗證是你本人"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"如要繼續操作,請使用使用生物識別驗證身分"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"如要繼續操作,請使用你的指紋驗證身分"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"如要繼續操作,請使用你的面孔驗證身分"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"請使用生物識別或螢幕鎖定功能驗證身分,才能繼續操作"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"無法使用生物識別硬件"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"已取消驗證"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"未能識別"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"無法辨識面孔"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"已取消驗證"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"未設定 PIN、圖案或密碼"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"驗證時發生錯誤"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 958073a4ab99..9ab7eb815a3e 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"使用生物特徵辨識或螢幕鎖定功能"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"驗證你的身分"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"如要繼續操作,請使用生物特徵辨識功能驗證身分"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"如要繼續操作,請使用指紋驗證身分"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"如要繼續操作,請使用臉孔驗證身分"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"請使用生物特徵辨識或螢幕鎖定功能驗證身分,才能繼續操作"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"無法使用生物特徵辨識硬體"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"已取消驗證"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"無法辨識"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"無法辨識臉孔"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"已取消驗證"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"未設定 PIN 碼、解鎖圖案或密碼"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"驗證時發生錯誤"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 270cc4bf1d61..023efcfd3c46 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -616,10 +616,13 @@ <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Sebenzisa i-biometrics noma ukukhiya isikrini"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Qinisekisa ukuthi nguwe"</string> <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Sebenzisa i-biometric yakho ukuze uqhubeke"</string> + <string name="biometric_dialog_fingerprint_subtitle" msgid="2520227942533751342">"Sebenzisa isigxivizo sakho somunwe ukuze uqhubeke"</string> + <string name="biometric_dialog_face_subtitle" msgid="5269284162191087084">"Sebenzisa ubuso bakho ukuze uqhubeke"</string> <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Sebenzisa i-biometric noma ukukhiya isikrini ukuze uqhubeke"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"I-Biometric hardware ayitholakali"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Ukufakazela ubuqiniso kukhanseliwe"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Akwaziwa"</string> + <string name="biometric_face_not_recognized" msgid="5535599455744525200">"Ubuso abaziwa"</string> <string name="biometric_error_canceled" msgid="8266582404844179778">"Ukufakazela ubuqiniso kukhanseliwe"</string> <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Ayikho iphinikhodi, iphethini, noma iphasiwedi esethiwe"</string> <string name="biometric_error_generic" msgid="6784371929985434439">"Iphutha lokufakazela ubuqiniso"</string> diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml index fd7418542a2b..4ae54a052859 100644 --- a/core/res/res/values/config_telephony.xml +++ b/core/res/res/values/config_telephony.xml @@ -168,8 +168,9 @@ <bool name="ignore_emergency_number_routing_from_db">false</bool> <java-symbol type="bool" name="ignore_emergency_number_routing_from_db" /> - <!-- Whether "Virtual DSDA", i.e. in-call IMS connectivity can be provided on both subs with - only single logical modem, by using its data connection in addition to cellular IMS. --> - <bool name="config_enable_virtual_dsda">false</bool> - <java-symbol type="bool" name="config_enable_virtual_dsda" /> + <!-- Boolean indicating whether allow sending null to modem to clear the previous initial attach + data profile --> + <bool name="allow_clear_initial_attach_data_profile">false</bool> + <java-symbol type="bool" name="allow_clear_initial_attach_data_profile" /> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index a5b2b853fddd..79426c8311ab 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1780,6 +1780,10 @@ <string name="biometric_dialog_default_title">Verify it\u2019s you</string> <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with a biometric (e.g. fingerprint or face). [CHAR LIMIT=70] --> <string name="biometric_dialog_default_subtitle">Use your biometric to continue</string> + <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with fingerprint. [CHAR LIMIT=70] --> + <string name="biometric_dialog_fingerprint_subtitle">Use your fingerprint to continue</string> + <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with face. [CHAR LIMIT=70] --> + <string name="biometric_dialog_face_subtitle">Use your face to continue</string> <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with a biometric (e.g. fingerprint or face) or their screen lock credential (i.e. PIN, pattern, or password). [CHAR LIMIT=90] --> <string name="biometric_or_screen_lock_dialog_default_subtitle">Use your biometric or screen lock to continue</string> @@ -1789,6 +1793,8 @@ <string name="biometric_error_user_canceled">Authentication canceled</string> <!-- Message shown by the biometric dialog when biometric is not recognized --> <string name="biometric_not_recognized">Not recognized</string> + <!-- Message shown by the biometric dialog when face is not recognized [CHAR LIMIT=50] --> + <string name="biometric_face_not_recognized">Face not recognized</string> <!-- Message shown when biometric authentication has been canceled [CHAR LIMIT=50] --> <string name="biometric_error_canceled">Authentication canceled</string> <!-- Message returned to applications if BiometricPrompt setAllowDeviceCredentials is enabled but no pin, pattern, or password is set. [CHAR LIMIT=NONE] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 2d040bb66d83..cafa74e7250b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2567,10 +2567,13 @@ <java-symbol type="string" name="biometric_or_screen_lock_app_setting_name" /> <java-symbol type="string" name="biometric_dialog_default_title" /> <java-symbol type="string" name="biometric_dialog_default_subtitle" /> + <java-symbol type="string" name="biometric_dialog_face_subtitle" /> + <java-symbol type="string" name="biometric_dialog_fingerprint_subtitle" /> <java-symbol type="string" name="biometric_or_screen_lock_dialog_default_subtitle" /> <java-symbol type="string" name="biometric_error_hw_unavailable" /> <java-symbol type="string" name="biometric_error_user_canceled" /> <java-symbol type="string" name="biometric_not_recognized" /> + <java-symbol type="string" name="biometric_face_not_recognized" /> <java-symbol type="string" name="biometric_error_canceled" /> <java-symbol type="string" name="biometric_error_device_not_secured" /> <java-symbol type="string" name="biometric_error_generic" /> @@ -5021,6 +5024,7 @@ <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" /> <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" /> + <java-symbol name="materialColorOnSecondaryFixedVariant" type="attr"/> <java-symbol name="materialColorOnTertiaryFixedVariant" type="attr"/> <java-symbol name="materialColorSurfaceContainerLowest" type="attr"/> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index a044602f7ec0..b05507e7e128 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -257,6 +257,7 @@ applications that come with the platform <permission name="android.permission.CLEAR_APP_CACHE"/> <permission name="android.permission.ACCESS_INSTANT_APPS" /> <permission name="android.permission.CONNECTIVITY_INTERNAL"/> + <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" /> <permission name="android.permission.DELETE_CACHE_FILES"/> <permission name="android.permission.DELETE_PACKAGES"/> <permission name="android.permission.DUMP"/> diff --git a/packages/SettingsLib/Spa/tests/Android.bp b/packages/SettingsLib/Spa/tests/Android.bp index b4c67ccda6f2..f9e64aee1513 100644 --- a/packages/SettingsLib/Spa/tests/Android.bp +++ b/packages/SettingsLib/Spa/tests/Android.bp @@ -31,7 +31,6 @@ android_test { "SpaLib", "SpaLibTestUtils", "androidx.compose.runtime_runtime", - "androidx.lifecycle_lifecycle-runtime-testing", "androidx.test.ext.junit", "androidx.test.runner", "mockito-target-minus-junit4", diff --git a/packages/SettingsLib/Spa/testutils/Android.bp b/packages/SettingsLib/Spa/testutils/Android.bp index 2c1e1c2abc2c..e4d56cc4f2a0 100644 --- a/packages/SettingsLib/Spa/testutils/Android.bp +++ b/packages/SettingsLib/Spa/testutils/Android.bp @@ -29,6 +29,7 @@ android_library { "androidx.compose.runtime_runtime", "androidx.compose.ui_ui-test-junit4", "androidx.compose.ui_ui-test-manifest", + "androidx.lifecycle_lifecycle-runtime-testing", "mockito", "truth-prebuilt", ], diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java index c9d9b57c7170..5b7899b1e3af 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java @@ -16,7 +16,7 @@ package com.android.settingslib.drawer; -/** Interface for {@link SwitchController} whose instances support dynamic summary */ +/** Interface for {@link EntryController} whose instances support dynamic summary */ public interface DynamicSummary { /** @return the dynamic summary text */ String getDynamicSummary(); diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java index af711ddd59c2..cb157734aa6a 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java @@ -16,7 +16,7 @@ package com.android.settingslib.drawer; -/** Interface for {@link SwitchController} whose instances support dynamic title */ +/** Interface for {@link EntryController} whose instances support dynamic title */ public interface DynamicTitle { /** @return the dynamic title text */ String getDynamicTitle(); diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntriesProvider.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntriesProvider.java new file mode 100644 index 000000000000..1c14c0a72ce4 --- /dev/null +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntriesProvider.java @@ -0,0 +1,222 @@ +/* + * 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.settingslib.drawer; + +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Context; +import android.content.pm.ProviderInfo; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * An abstract class for injecting entries to Settings. + */ +public abstract class EntriesProvider extends ContentProvider { + private static final String TAG = "EntriesProvider"; + + public static final String METHOD_GET_ENTRY_DATA = "getEntryData"; + public static final String METHOD_GET_PROVIDER_ICON = "getProviderIcon"; + public static final String METHOD_GET_DYNAMIC_TITLE = "getDynamicTitle"; + public static final String METHOD_GET_DYNAMIC_SUMMARY = "getDynamicSummary"; + public static final String METHOD_IS_CHECKED = "isChecked"; + public static final String METHOD_ON_CHECKED_CHANGED = "onCheckedChanged"; + + /** + * @deprecated use {@link #METHOD_GET_ENTRY_DATA} instead. + */ + @Deprecated + public static final String METHOD_GET_SWITCH_DATA = "getSwitchData"; + + public static final String EXTRA_ENTRY_DATA = "entry_data"; + public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state"; + public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error"; + public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message"; + + /** + * @deprecated use {@link #EXTRA_ENTRY_DATA} instead. + */ + @Deprecated + public static final String EXTRA_SWITCH_DATA = "switch_data"; + + private String mAuthority; + private final Map<String, EntryController> mControllerMap = new LinkedHashMap<>(); + private final List<Bundle> mEntryDataList = new ArrayList<>(); + + /** + * Get a list of {@link EntryController} for this provider. + */ + protected abstract List<? extends EntryController> createEntryControllers(); + + protected EntryController getController(String key) { + return mControllerMap.get(key); + } + + @Override + public void attachInfo(Context context, ProviderInfo info) { + mAuthority = info.authority; + Log.i(TAG, mAuthority); + super.attachInfo(context, info); + } + + @Override + public boolean onCreate() { + final List<? extends EntryController> controllers = createEntryControllers(); + if (controllers == null || controllers.isEmpty()) { + throw new IllegalArgumentException(); + } + + for (EntryController controller : controllers) { + final String key = controller.getKey(); + if (TextUtils.isEmpty(key)) { + throw new NullPointerException("Entry key cannot be null: " + + controller.getClass().getSimpleName()); + } else if (mControllerMap.containsKey(key)) { + throw new IllegalArgumentException("Entry key " + key + " is duplicated by: " + + controller.getClass().getSimpleName()); + } + + controller.setAuthority(mAuthority); + mControllerMap.put(key, controller); + if (!(controller instanceof PrimarySwitchController)) { + mEntryDataList.add(controller.getBundle()); + } + } + return true; + } + + @Override + public Bundle call(String method, String uriString, Bundle extras) { + final Bundle bundle = new Bundle(); + final String key = extras != null + ? extras.getString(META_DATA_PREFERENCE_KEYHINT) + : null; + if (TextUtils.isEmpty(key)) { + switch (method) { + case METHOD_GET_ENTRY_DATA: + bundle.putParcelableList(EXTRA_ENTRY_DATA, mEntryDataList); + return bundle; + case METHOD_GET_SWITCH_DATA: + bundle.putParcelableList(EXTRA_SWITCH_DATA, mEntryDataList); + return bundle; + default: + return null; + } + } + + final EntryController controller = mControllerMap.get(key); + if (controller == null) { + return null; + } + + switch (method) { + case METHOD_GET_ENTRY_DATA: + case METHOD_GET_SWITCH_DATA: + if (!(controller instanceof PrimarySwitchController)) { + return controller.getBundle(); + } + break; + case METHOD_GET_PROVIDER_ICON: + if (controller instanceof ProviderIcon) { + return ((ProviderIcon) controller).getProviderIcon(); + } + break; + case METHOD_GET_DYNAMIC_TITLE: + if (controller instanceof DynamicTitle) { + bundle.putString(META_DATA_PREFERENCE_TITLE, + ((DynamicTitle) controller).getDynamicTitle()); + return bundle; + } + break; + case METHOD_GET_DYNAMIC_SUMMARY: + if (controller instanceof DynamicSummary) { + bundle.putString(META_DATA_PREFERENCE_SUMMARY, + ((DynamicSummary) controller).getDynamicSummary()); + return bundle; + } + break; + case METHOD_IS_CHECKED: + if (controller instanceof ProviderSwitch) { + bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE, + ((ProviderSwitch) controller).isSwitchChecked()); + return bundle; + } + break; + case METHOD_ON_CHECKED_CHANGED: + if (controller instanceof ProviderSwitch) { + return onSwitchCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE), + (ProviderSwitch) controller); + } + break; + } + return null; + } + + private Bundle onSwitchCheckedChanged(boolean checked, ProviderSwitch controller) { + final boolean success = controller.onSwitchCheckedChanged(checked); + final Bundle bundle = new Bundle(); + bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success); + if (success) { + if (controller instanceof DynamicSummary) { + ((EntryController) controller).notifySummaryChanged(getContext()); + } + } else { + bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE, + controller.getSwitchErrorMessage(checked)); + } + return bundle; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + throw new UnsupportedOperationException(); + } + + @Override + public String getType(Uri uri) { + throw new UnsupportedOperationException(); + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException(); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(); + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(); + } +} + diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntryController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntryController.java new file mode 100644 index 000000000000..5d6e6a3adeb7 --- /dev/null +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntryController.java @@ -0,0 +1,246 @@ +/* + * 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.settingslib.drawer; + +import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY; +import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE; +import static com.android.settingslib.drawer.TileUtils.EXTRA_CATEGORY_KEY; +import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI; + +import android.app.PendingIntent; +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.os.Bundle; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + +/** + * A controller that manages events for switch. + */ +public abstract class EntryController { + + private String mAuthority; + + /** + * Returns the key for this switch. + */ + public abstract String getKey(); + + /** + * Returns the {@link MetaData} for this switch. + */ + protected abstract MetaData getMetaData(); + + /** + * Notify registered observers that title was updated and attempt to sync changes. + */ + public void notifyTitleChanged(Context context) { + if (this instanceof DynamicTitle) { + notifyChanged(context, METHOD_GET_DYNAMIC_TITLE); + } + } + + /** + * Notify registered observers that summary was updated and attempt to sync changes. + */ + public void notifySummaryChanged(Context context) { + if (this instanceof DynamicSummary) { + notifyChanged(context, METHOD_GET_DYNAMIC_SUMMARY); + } + } + + void setAuthority(String authority) { + mAuthority = authority; + } + + Bundle getBundle() { + final MetaData metaData = getMetaData(); + if (metaData == null) { + throw new NullPointerException("Should not return null in getMetaData()"); + } + + final Bundle bundle = metaData.build(); + final String uriString = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(mAuthority) + .build() + .toString(); + bundle.putString(META_DATA_PREFERENCE_KEYHINT, getKey()); + if (this instanceof ProviderIcon) { + bundle.putString(META_DATA_PREFERENCE_ICON_URI, uriString); + } + if (this instanceof DynamicTitle) { + bundle.putString(META_DATA_PREFERENCE_TITLE_URI, uriString); + } + if (this instanceof DynamicSummary) { + bundle.putString(META_DATA_PREFERENCE_SUMMARY_URI, uriString); + } + if (this instanceof ProviderSwitch) { + bundle.putString(META_DATA_PREFERENCE_SWITCH_URI, uriString); + } + return bundle; + } + + private void notifyChanged(Context context, String method) { + final Uri uri = TileUtils.buildUri(mAuthority, method, getKey()); + context.getContentResolver().notifyChange(uri, null); + } + + /** + * Collects all meta data of the item. + */ + protected static class MetaData { + private String mCategory; + private int mOrder; + @DrawableRes + private int mIcon; + private int mIconBackgroundHint; + private int mIconBackgroundArgb; + private Boolean mIconTintable; + @StringRes + private int mTitleId; + private String mTitle; + @StringRes + private int mSummaryId; + private String mSummary; + private PendingIntent mPendingIntent; + + /** + * @param category the category of the switch. This value must be from {@link CategoryKey}. + */ + public MetaData(@NonNull String category) { + mCategory = category; + } + + /** + * Set the order of the item that should be displayed on screen. Bigger value items displays + * closer on top. + */ + public MetaData setOrder(int order) { + mOrder = order; + return this; + } + + /** Set the icon that should be displayed for the item. */ + public MetaData setIcon(@DrawableRes int icon) { + mIcon = icon; + return this; + } + + /** Set the icon background color. The value may or may not be used by Settings app. */ + public MetaData setIconBackgoundHint(int hint) { + mIconBackgroundHint = hint; + return this; + } + + /** Set the icon background color as raw ARGB. */ + public MetaData setIconBackgoundArgb(int argb) { + mIconBackgroundArgb = argb; + return this; + } + + /** Specify whether the icon is tintable. */ + public MetaData setIconTintable(boolean tintable) { + mIconTintable = tintable; + return this; + } + + /** Set the title that should be displayed for the item. */ + public MetaData setTitle(@StringRes int id) { + mTitleId = id; + return this; + } + + /** Set the title that should be displayed for the item. */ + public MetaData setTitle(String title) { + mTitle = title; + return this; + } + + /** Set the summary text that should be displayed for the item. */ + public MetaData setSummary(@StringRes int id) { + mSummaryId = id; + return this; + } + + /** Set the summary text that should be displayed for the item. */ + public MetaData setSummary(String summary) { + mSummary = summary; + return this; + } + + public MetaData setPendingIntent(PendingIntent pendingIntent) { + mPendingIntent = pendingIntent; + return this; + } + + protected Bundle build() { + final Bundle bundle = new Bundle(); + bundle.putString(EXTRA_CATEGORY_KEY, mCategory); + + if (mOrder != 0) { + bundle.putInt(META_DATA_KEY_ORDER, mOrder); + } + + if (mIcon != 0) { + bundle.putInt(META_DATA_PREFERENCE_ICON, mIcon); + } + if (mIconBackgroundHint != 0) { + bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, mIconBackgroundHint); + } + if (mIconBackgroundArgb != 0) { + bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, mIconBackgroundArgb); + } + if (mIconTintable != null) { + bundle.putBoolean(META_DATA_PREFERENCE_ICON_TINTABLE, mIconTintable); + } + + if (mTitleId != 0) { + bundle.putInt(META_DATA_PREFERENCE_TITLE, mTitleId); + } else if (mTitle != null) { + bundle.putString(META_DATA_PREFERENCE_TITLE, mTitle); + } + + if (mSummaryId != 0) { + bundle.putInt(META_DATA_PREFERENCE_SUMMARY, mSummaryId); + } else if (mSummary != null) { + bundle.putString(META_DATA_PREFERENCE_SUMMARY, mSummary); + } + + if (mPendingIntent != null) { + bundle.putParcelable(META_DATA_PREFERENCE_PENDING_INTENT, mPendingIntent); + } + + return bundle; + } + } +} diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java index 2945d5c1099a..3aa6fcb06016 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java @@ -19,7 +19,7 @@ package com.android.settingslib.drawer; import android.os.Bundle; /** - * Interface for {@link SwitchController} whose instances support icon provided from the content + * Interface for {@link EntryController} whose instances support icon provided from the content * provider */ public interface ProviderIcon { diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderSwitch.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderSwitch.java new file mode 100644 index 000000000000..47eb31cefa29 --- /dev/null +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderSwitch.java @@ -0,0 +1,41 @@ +/* + * 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.settingslib.drawer; + +/** + * Interface for {@link EntryController} whose instances support switch widget provided from the + * content provider + */ +public interface ProviderSwitch { + /** + * Returns the checked state of this switch. + */ + boolean isSwitchChecked(); + + /** + * Called when the checked state of this switch is changed. + * + * @return true if the checked state was successfully changed, otherwise false + */ + boolean onSwitchCheckedChanged(boolean checked); + + /** + * Returns the error message which will be toasted when {@link #onSwitchCheckedChanged} returns + * false. + */ + String getSwitchErrorMessage(boolean attemptedChecked); +} diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java index 54da585aba7a..b775e93bf69c 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java @@ -75,7 +75,7 @@ public class ProviderTile extends Tile { if (infoList != null && !infoList.isEmpty()) { final ProviderInfo providerInfo = infoList.get(0).providerInfo; mComponentInfo = providerInfo; - setMetaData(TileUtils.getSwitchDataFromProvider(context, providerInfo.authority, + setMetaData(TileUtils.getEntryDataFromProvider(context, providerInfo.authority, mKey)); } else { Log.e(TAG, "Cannot find package info for " diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java index 23669b2743ce..a1a4e5867299 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java @@ -16,38 +16,16 @@ package com.android.settingslib.drawer; -import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY; -import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE; -import static com.android.settingslib.drawer.SwitchesProvider.METHOD_IS_CHECKED; -import static com.android.settingslib.drawer.TileUtils.EXTRA_CATEGORY_KEY; -import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI; - -import android.content.ContentResolver; -import android.content.Context; -import android.net.Uri; -import android.os.Bundle; - -import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; -import androidx.annotation.StringRes; /** * A controller that manages events for switch. + * + * @deprecated Use {@link EntriesProvider} with {@link ProviderSwitch} instead. */ -public abstract class SwitchController { +@Deprecated +public abstract class SwitchController extends EntryController implements ProviderSwitch { - private String mAuthority; /** * Returns the key for this switch. @@ -55,11 +33,6 @@ public abstract class SwitchController { public abstract String getSwitchKey(); /** - * Returns the {@link MetaData} for this switch. - */ - protected abstract MetaData getMetaData(); - - /** * Returns the checked state of this switch. */ protected abstract boolean isChecked(); @@ -76,181 +49,41 @@ public abstract class SwitchController { */ protected abstract String getErrorMessage(boolean attemptedChecked); - /** - * Notify registered observers that title was updated and attempt to sync changes. - */ - public void notifyTitleChanged(Context context) { - if (this instanceof DynamicTitle) { - notifyChanged(context, METHOD_GET_DYNAMIC_TITLE); - } - } - - /** - * Notify registered observers that summary was updated and attempt to sync changes. - */ - public void notifySummaryChanged(Context context) { - if (this instanceof DynamicSummary) { - notifyChanged(context, METHOD_GET_DYNAMIC_SUMMARY); - } - } - - /** - * Notify registered observers that checked state was updated and attempt to sync changes. - */ - public void notifyCheckedChanged(Context context) { - notifyChanged(context, METHOD_IS_CHECKED); + @Override + public String getKey() { + return getSwitchKey(); } - void setAuthority(String authority) { - mAuthority = authority; + @Override + public boolean isSwitchChecked() { + return isChecked(); } - Bundle getBundle() { - final MetaData metaData = getMetaData(); - if (metaData == null) { - throw new NullPointerException("Should not return null in getMetaData()"); - } - - final Bundle bundle = metaData.build(); - final String uriString = new Uri.Builder() - .scheme(ContentResolver.SCHEME_CONTENT) - .authority(mAuthority) - .build() - .toString(); - bundle.putString(META_DATA_PREFERENCE_KEYHINT, getSwitchKey()); - bundle.putString(META_DATA_PREFERENCE_SWITCH_URI, uriString); - if (this instanceof ProviderIcon) { - bundle.putString(META_DATA_PREFERENCE_ICON_URI, uriString); - } - if (this instanceof DynamicTitle) { - bundle.putString(META_DATA_PREFERENCE_TITLE_URI, uriString); - } - if (this instanceof DynamicSummary) { - bundle.putString(META_DATA_PREFERENCE_SUMMARY_URI, uriString); - } - return bundle; + @Override + public boolean onSwitchCheckedChanged(boolean checked) { + return onCheckedChanged(checked); } - private void notifyChanged(Context context, String method) { - final Uri uri = TileUtils.buildUri(mAuthority, method, getSwitchKey()); - context.getContentResolver().notifyChange(uri, null); + @Override + public String getSwitchErrorMessage(boolean attemptedChecked) { + return getErrorMessage(attemptedChecked); } /** - * Collects all meta data of the item. + * Same as {@link EntryController.MetaData}, for backwards compatibility purpose. + * + * @deprecated Use {@link EntryController.MetaData} instead. */ - protected static class MetaData { - private String mCategory; - private int mOrder; - @DrawableRes - private int mIcon; - private int mIconBackgroundHint; - private int mIconBackgroundArgb; - private Boolean mIconTintable; - @StringRes - private int mTitleId; - private String mTitle; - @StringRes - private int mSummaryId; - private String mSummary; - + @Deprecated + protected static class MetaData extends EntryController.MetaData { /** * @param category the category of the switch. This value must be from {@link CategoryKey}. + * + * @deprecated Use {@link EntryController.MetaData} instead. */ + @Deprecated public MetaData(@NonNull String category) { - mCategory = category; - } - - /** - * Set the order of the item that should be displayed on screen. Bigger value items displays - * closer on top. - */ - public MetaData setOrder(int order) { - mOrder = order; - return this; - } - - /** Set the icon that should be displayed for the item. */ - public MetaData setIcon(@DrawableRes int icon) { - mIcon = icon; - return this; - } - - /** Set the icon background color. The value may or may not be used by Settings app. */ - public MetaData setIconBackgoundHint(int hint) { - mIconBackgroundHint = hint; - return this; - } - - /** Set the icon background color as raw ARGB. */ - public MetaData setIconBackgoundArgb(int argb) { - mIconBackgroundArgb = argb; - return this; - } - - /** Specify whether the icon is tintable. */ - public MetaData setIconTintable(boolean tintable) { - mIconTintable = tintable; - return this; - } - - /** Set the title that should be displayed for the item. */ - public MetaData setTitle(@StringRes int id) { - mTitleId = id; - return this; - } - - /** Set the title that should be displayed for the item. */ - public MetaData setTitle(String title) { - mTitle = title; - return this; - } - - /** Set the summary text that should be displayed for the item. */ - public MetaData setSummary(@StringRes int id) { - mSummaryId = id; - return this; - } - - /** Set the summary text that should be displayed for the item. */ - public MetaData setSummary(String summary) { - mSummary = summary; - return this; - } - - private Bundle build() { - final Bundle bundle = new Bundle(); - bundle.putString(EXTRA_CATEGORY_KEY, mCategory); - - if (mOrder != 0) { - bundle.putInt(META_DATA_KEY_ORDER, mOrder); - } - - if (mIcon != 0) { - bundle.putInt(META_DATA_PREFERENCE_ICON, mIcon); - } - if (mIconBackgroundHint != 0) { - bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, mIconBackgroundHint); - } - if (mIconBackgroundArgb != 0) { - bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, mIconBackgroundArgb); - } - if (mIconTintable != null) { - bundle.putBoolean(META_DATA_PREFERENCE_ICON_TINTABLE, mIconTintable); - } - - if (mTitleId != 0) { - bundle.putInt(META_DATA_PREFERENCE_TITLE, mTitleId); - } else if (mTitle != null) { - bundle.putString(META_DATA_PREFERENCE_TITLE, mTitle); - } - - if (mSummaryId != 0) { - bundle.putInt(META_DATA_PREFERENCE_SUMMARY, mSummaryId); - } else if (mSummary != null) { - bundle.putString(META_DATA_PREFERENCE_SUMMARY, mSummary); - } - return bundle; + super(category); } } } diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java index f2b3e30dc252..ad00ced8a3ac 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java @@ -16,46 +16,15 @@ package com.android.settingslib.drawer; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.Context; -import android.content.pm.ProviderInfo; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.text.TextUtils; -import android.util.Log; - -import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; /** * An abstract class for injecting switches to Settings. + * + * @deprecated Use {@link EntriesProvider} instead. */ -public abstract class SwitchesProvider extends ContentProvider { - private static final String TAG = "SwitchesProvider"; - - public static final String METHOD_GET_SWITCH_DATA = "getSwitchData"; - public static final String METHOD_GET_PROVIDER_ICON = "getProviderIcon"; - public static final String METHOD_GET_DYNAMIC_TITLE = "getDynamicTitle"; - public static final String METHOD_GET_DYNAMIC_SUMMARY = "getDynamicSummary"; - public static final String METHOD_IS_CHECKED = "isChecked"; - public static final String METHOD_ON_CHECKED_CHANGED = "onCheckedChanged"; - - public static final String EXTRA_SWITCH_DATA = "switch_data"; - public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state"; - public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error"; - public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message"; - - private String mAuthority; - private final Map<String, SwitchController> mControllerMap = new LinkedHashMap<>(); - private final List<Bundle> mSwitchDataList = new ArrayList<>(); +@Deprecated +public abstract class SwitchesProvider extends EntriesProvider { /** * Get a list of {@link SwitchController} for this provider. @@ -63,129 +32,7 @@ public abstract class SwitchesProvider extends ContentProvider { protected abstract List<SwitchController> createSwitchControllers(); @Override - public void attachInfo(Context context, ProviderInfo info) { - mAuthority = info.authority; - Log.i(TAG, mAuthority); - super.attachInfo(context, info); - } - - @Override - public boolean onCreate() { - final List<SwitchController> controllers = createSwitchControllers(); - if (controllers == null || controllers.isEmpty()) { - throw new IllegalArgumentException(); - } - - controllers.forEach(controller -> { - final String key = controller.getSwitchKey(); - if (TextUtils.isEmpty(key)) { - throw new NullPointerException("Switch key cannot be null: " - + controller.getClass().getSimpleName()); - } else if (mControllerMap.containsKey(key)) { - throw new IllegalArgumentException("Switch key " + key + " is duplicated by: " - + controller.getClass().getSimpleName()); - } - - controller.setAuthority(mAuthority); - mControllerMap.put(key, controller); - if (!(controller instanceof PrimarySwitchController)) { - mSwitchDataList.add(controller.getBundle()); - } - }); - return true; - } - - @Override - public Bundle call(String method, String uriString, Bundle extras) { - final Bundle bundle = new Bundle(); - final String key = extras != null - ? extras.getString(META_DATA_PREFERENCE_KEYHINT) - : null; - if (TextUtils.isEmpty(key)) { - if (METHOD_GET_SWITCH_DATA.equals(method)) { - bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchDataList); - return bundle; - } - return null; - } - - final SwitchController controller = mControllerMap.get(key); - if (controller == null) { - return null; - } - - switch (method) { - case METHOD_GET_SWITCH_DATA: - if (!(controller instanceof PrimarySwitchController)) { - return controller.getBundle(); - } - break; - case METHOD_GET_PROVIDER_ICON: - if (controller instanceof ProviderIcon) { - return ((ProviderIcon) controller).getProviderIcon(); - } - break; - case METHOD_GET_DYNAMIC_TITLE: - if (controller instanceof DynamicTitle) { - bundle.putString(META_DATA_PREFERENCE_TITLE, - ((DynamicTitle) controller).getDynamicTitle()); - return bundle; - } - break; - case METHOD_GET_DYNAMIC_SUMMARY: - if (controller instanceof DynamicSummary) { - bundle.putString(META_DATA_PREFERENCE_SUMMARY, - ((DynamicSummary) controller).getDynamicSummary()); - return bundle; - } - break; - case METHOD_IS_CHECKED: - bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE, controller.isChecked()); - return bundle; - case METHOD_ON_CHECKED_CHANGED: - return onCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE), controller); - } - return null; - } - - private Bundle onCheckedChanged(boolean checked, SwitchController controller) { - final boolean success = controller.onCheckedChanged(checked); - final Bundle bundle = new Bundle(); - bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success); - if (success) { - if (controller instanceof DynamicSummary) { - controller.notifySummaryChanged(getContext()); - } - } else { - bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE, - controller.getErrorMessage(checked)); - } - return bundle; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - throw new UnsupportedOperationException(); - } - - @Override - public String getType(Uri uri) { - throw new UnsupportedOperationException(); - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - throw new UnsupportedOperationException(); - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException(); - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException(); + protected List<? extends EntryController> createEntryControllers() { + return createSwitchControllers(); } } 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 a0c8ac4e0a51..1a938d6ec37e 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java @@ -19,6 +19,7 @@ package com.android.settingslib.drawer; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE; import static com.android.settingslib.drawer.TileUtils.META_DATA_NEW_TASK; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; @@ -29,6 +30,7 @@ import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITL import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL; import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ComponentInfo; @@ -47,6 +49,7 @@ import androidx.annotation.VisibleForTesting; import java.util.ArrayList; import java.util.Comparator; +import java.util.HashMap; /** * Description of a single dashboard tile that the user can select. @@ -60,6 +63,8 @@ public abstract class Tile implements Parcelable { */ public ArrayList<UserHandle> userHandle = new ArrayList<>(); + public HashMap<UserHandle, PendingIntent> pendingIntentMap = new HashMap<>(); + @VisibleForTesting long mLastUpdateTime; private final String mComponentPackage; @@ -174,7 +179,8 @@ public abstract class Tile implements Parcelable { * Check whether tile has order. */ public boolean hasOrder() { - return mMetaData.containsKey(META_DATA_KEY_ORDER) + return mMetaData != null + && mMetaData.containsKey(META_DATA_KEY_ORDER) && mMetaData.get(META_DATA_KEY_ORDER) instanceof Integer; } @@ -186,13 +192,20 @@ public abstract class Tile implements Parcelable { } /** + * Check whether tile has a pending intent. + */ + public boolean hasPendingIntent() { + return !pendingIntentMap.isEmpty(); + } + + /** * Title of the tile that is shown to the user. */ public CharSequence getTitle(Context context) { CharSequence title = null; ensureMetadataNotStale(context); final PackageManager packageManager = context.getPackageManager(); - if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE)) { + if (mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_TITLE)) { if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE_URI)) { // If has as uri to provide dynamic title, skip loading here. UI will later load // at tile binding time. @@ -272,10 +285,10 @@ public abstract class Tile implements Parcelable { * Optional key to use for this tile. */ public String getKey(Context context) { + ensureMetadataNotStale(context); if (!hasKey()) { return null; } - ensureMetadataNotStale(context); if (mMetaData.get(META_DATA_PREFERENCE_KEYHINT) instanceof Integer) { return context.getResources().getString(mMetaData.getInt(META_DATA_PREFERENCE_KEYHINT)); } else { @@ -395,6 +408,76 @@ public abstract class Tile implements Parcelable { return TextUtils.equals(profile, PROFILE_PRIMARY); } + /** + * Returns whether the tile belongs to another group / category. + */ + public boolean hasGroupKey() { + return mMetaData != null + && !TextUtils.isEmpty(mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY)); + } + + /** + * Returns the group / category key this tile belongs to. + */ + public String getGroupKey() { + return (mMetaData == null) ? null : mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY); + } + + /** + * The type of the tile. + */ + public enum Type { + /** + * 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. + */ + EXTERNAL_ACTION, + + /** + * A preference that shows an on / off switch that can be toggled by the user. + */ + SWITCH, + + /** + * A preference with both an on / off switch, and a tappable area that can perform an + * action. + */ + SWITCH_WITH_ACTION, + + /** + * A preference category with a title that can be used to group multiple preferences + * together. + */ + GROUP; + } + + /** + * Returns the type of the tile. + * + * @see Type + */ + public Type getType() { + boolean hasExternalAction = hasPendingIntent(); + boolean hasAction = hasExternalAction || this instanceof ActivityTile; + boolean hasSwitch = hasSwitch(); + + if (hasSwitch && hasAction) { + return Type.SWITCH_WITH_ACTION; + } else if (hasSwitch) { + return Type.SWITCH; + } else if (hasExternalAction) { + return Type.EXTERNAL_ACTION; + } else if (hasAction) { + return Type.ACTION; + } else { + return Type.GROUP; + } + } + public static final Comparator<Tile> TILE_COMPARATOR = (lhs, rhs) -> rhs.getOrder() - lhs.getOrder(); } 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 acc0087f6dcf..e46db75f633e 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java @@ -113,6 +113,12 @@ public class TileUtils { public static final String META_DATA_PREFERENCE_KEYHINT = "com.android.settings.keyhint"; /** + * Name of the meta-data item that can be set in the AndroidManifest.xml or in the content + * provider to specify the key of a group / category where this preference belongs to. + */ + public static final String META_DATA_PREFERENCE_GROUP_KEY = "com.android.settings.group_key"; + + /** * Order of the item that should be displayed on screen. Bigger value items displays closer on * top. */ @@ -202,6 +208,13 @@ public class TileUtils { "com.android.settings.switch_uri"; /** + * Name of the meta-data item that can be set from the content provider providing the intent + * that will be executed when the user taps on the preference. + */ + public static final String META_DATA_PREFERENCE_PENDING_INTENT = + "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. * @@ -331,12 +344,12 @@ public class TileUtils { continue; } final ProviderInfo providerInfo = resolved.providerInfo; - final List<Bundle> switchData = getSwitchDataFromProvider(context, + final List<Bundle> entryData = getEntryDataFromProvider(context, providerInfo.authority); - if (switchData == null || switchData.isEmpty()) { + if (entryData == null || entryData.isEmpty()) { continue; } - for (Bundle metaData : switchData) { + for (Bundle metaData : entryData) { loadTile(user, addedCache, defaultCategory, outTiles, intent, metaData, providerInfo); } @@ -386,27 +399,43 @@ public class TileUtils { if (!tile.userHandle.contains(user)) { tile.userHandle.add(user); } + if (metaData.containsKey(META_DATA_PREFERENCE_PENDING_INTENT)) { + tile.pendingIntentMap.put( + user, metaData.getParcelable(META_DATA_PREFERENCE_PENDING_INTENT)); + } if (!outTiles.contains(tile)) { outTiles.add(tile); } } - /** Returns the switch data of the key specified from the provider */ + /** Returns the entry data of the key specified from the provider */ // TODO(b/144732809): rearrange methods by access level modifiers - static Bundle getSwitchDataFromProvider(Context context, String authority, String key) { + static Bundle getEntryDataFromProvider(Context context, String authority, String key) { final Map<String, IContentProvider> providerMap = new ArrayMap<>(); - final Uri uri = buildUri(authority, SwitchesProvider.METHOD_GET_SWITCH_DATA, key); - return getBundleFromUri(context, uri, providerMap, null /* bundle */); + final Uri uri = buildUri(authority, EntriesProvider.METHOD_GET_ENTRY_DATA, key); + Bundle result = getBundleFromUri(context, uri, providerMap, null /* bundle */); + if (result == null) { + Uri fallbackUri = buildUri(authority, EntriesProvider.METHOD_GET_SWITCH_DATA, key); + result = getBundleFromUri(context, fallbackUri, providerMap, null /* bundle */); + } + return result; } - /** Returns all switch data from the provider */ - private static List<Bundle> getSwitchDataFromProvider(Context context, String authority) { + /** Returns all entry data from the provider */ + private static List<Bundle> getEntryDataFromProvider(Context context, String authority) { final Map<String, IContentProvider> providerMap = new ArrayMap<>(); - final Uri uri = buildUri(authority, SwitchesProvider.METHOD_GET_SWITCH_DATA); + final Uri uri = buildUri(authority, EntriesProvider.METHOD_GET_ENTRY_DATA); final Bundle result = getBundleFromUri(context, uri, providerMap, null /* bundle */); - return result != null - ? result.getParcelableArrayList(SwitchesProvider.EXTRA_SWITCH_DATA) - : null; + if (result != null) { + return result.getParcelableArrayList(EntriesProvider.EXTRA_ENTRY_DATA); + } else { + Uri fallbackUri = buildUri(authority, EntriesProvider.METHOD_GET_SWITCH_DATA); + Bundle fallbackResult = + getBundleFromUri(context, fallbackUri, providerMap, null /* bundle */); + return fallbackResult != null + ? fallbackResult.getParcelableArrayList(EntriesProvider.EXTRA_SWITCH_DATA) + : null; + } } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 2e6bb535a8f0..f522fd13c9f8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -583,7 +583,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> */ public void setName(String name) { // Prevent getName() to be set to null if setName(null) is called - if (name == null || TextUtils.equals(name, getName())) { + if (TextUtils.isEmpty(name) || TextUtils.equals(name, getName())) { return; } mDevice.setAlias(name); diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java index 09abc394634a..9ee8a32fdc77 100644 --- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java +++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java @@ -209,8 +209,7 @@ public class MetricsFeatureProvider { } final ComponentName cn = intent.getComponent(); final String key = cn != null ? cn.flattenToString() : intent.getAction(); - return logSettingsTileClick(key + (isWorkProfile ? "/work" : "/personal"), - sourceMetricsCategory); + return logSettingsTileClickWithProfile(key, sourceMetricsCategory, isWorkProfile); } /** @@ -226,4 +225,20 @@ public class MetricsFeatureProvider { clicked(sourceMetricsCategory, logKey); return true; } + + /** + * Logs an event when the setting key is clicked with a specific profile from Profile select + * dialog. + * + * @return true if the key is loggable, otherwise false + */ + public boolean logSettingsTileClickWithProfile(String logKey, int sourceMetricsCategory, + boolean isWorkProfile) { + if (TextUtils.isEmpty(logKey)) { + // Not loggable + return false; + } + clicked(sourceMetricsCategory, logKey + (isWorkProfile ? "/work" : "/personal")); + return true; + } } 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 6444f3bd4341..4b61ff1177bd 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 @@ -1015,6 +1015,13 @@ public class CachedBluetoothDeviceTest { } @Test + public void setName_setDeviceNameIsEmpty() { + mCachedDevice.setName(""); + + verify(mDevice, never()).setAlias(any()); + } + + @Test public void getProfileConnectionState_nullProfile_returnDisconnected() { assertThat(mCachedDevice.getProfileConnectionState(null)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java index 3352d86b2dcc..dd8d54a62ff4 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java @@ -203,4 +203,24 @@ public class MetricsFeatureProviderTest { assertThat(loggable).isFalse(); verifyNoMoreInteractions(mLogWriter); } + + @Test + public void logSettingsTileClickWithProfile_isPersonalProfile_shouldTagPersonal() { + final String key = "abc"; + final boolean loggable = mProvider.logSettingsTileClickWithProfile(key, + MetricsEvent.SETTINGS_GESTURES, false); + + assertThat(loggable).isTrue(); + verify(mLogWriter).clicked(MetricsEvent.SETTINGS_GESTURES, "abc/personal"); + } + + @Test + public void logSettingsTileClickWithProfile_isWorkProfile_shouldTagWork() { + final String key = "abc"; + final boolean loggable = mProvider.logSettingsTileClickWithProfile(key, + MetricsEvent.SETTINGS_GESTURES, true); + + assertThat(loggable).isTrue(); + verify(mLogWriter).clicked(MetricsEvent.SETTINGS_GESTURES, "abc/work"); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java index aa6b0bf33b69..4d2b1ae2ade0 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java @@ -17,19 +17,23 @@ package com.android.settingslib.drawer; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI; import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL; import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY; import static com.google.common.truth.Truth.assertThat; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.os.UserHandle; import org.junit.Before; import org.junit.Test; @@ -191,4 +195,65 @@ public class ActivityTileTest { assertThat(tile.getTitle(RuntimeEnvironment.application)).isNull(); } + + @Test + public void hasPendingIntent_empty_returnsFalse() { + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.hasPendingIntent()).isFalse(); + } + + @Test + public void hasPendingIntent_notEmpty_returnsTrue() { + final Tile tile = new ActivityTile(mActivityInfo, "category"); + tile.pendingIntentMap.put( + UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0)); + + assertThat(tile.hasPendingIntent()).isTrue(); + } + + @Test + public void hasGroupKey_empty_returnsFalse() { + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.hasGroupKey()).isFalse(); + } + + @Test + public void hasGroupKey_notEmpty_returnsTrue() { + mActivityInfo.metaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key"); + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.hasGroupKey()).isTrue(); + } + + @Test + public void getGroupKey_empty_returnsNull() { + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.getGroupKey()).isNull(); + } + + @Test + public void getGroupKey_notEmpty_returnsValue() { + mActivityInfo.metaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key"); + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.getGroupKey()).isEqualTo("test_key"); + } + + @Test + public void getType_withoutSwitch_returnsAction() { + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.getType()).isEqualTo(Tile.Type.ACTION); + } + + @Test + public void getType_withSwitch_returnsSwitchWithAction() { + mActivityInfo.metaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "test://testabc/"); + final Tile tile = new ActivityTile(mActivityInfo, "category"); + + assertThat(tile.getType()).isEqualTo(Tile.Type.SWITCH_WITH_ACTION); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/EntriesProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/EntriesProviderTest.java new file mode 100644 index 000000000000..a2483305c94a --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/EntriesProviderTest.java @@ -0,0 +1,472 @@ +/* + * 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.settingslib.drawer; + +import static com.android.settingslib.drawer.EntriesProvider.EXTRA_ENTRY_DATA; +import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_CHECKED_STATE; +import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_DATA; +import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_SET_CHECKED_ERROR; +import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_DYNAMIC_SUMMARY; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_DYNAMIC_TITLE; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_ENTRY_DATA; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_PROVIDER_ICON; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_SWITCH_DATA; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_IS_CHECKED; +import static com.android.settingslib.drawer.EntriesProvider.METHOD_ON_CHECKED_CHANGED; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ProviderInfo; +import android.os.Bundle; + +import com.android.settingslib.drawer.EntryController.MetaData; +import com.android.settingslib.drawer.PrimarySwitchControllerTest.TestPrimarySwitchController; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class EntriesProviderTest { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + private Context mContext; + private ProviderInfo mProviderInfo; + + private TestEntriesProvider mEntriesProvider; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mEntriesProvider = new TestEntriesProvider(); + mProviderInfo = new ProviderInfo(); + mProviderInfo.authority = "auth"; + } + + @Test + public void attachInfo_noController_shouldThrowIllegalArgumentException() { + thrown.expect(IllegalArgumentException.class); + + mEntriesProvider.attachInfo(mContext, mProviderInfo); + } + + @Test + public void attachInfo_NoKeyInController_shouldThrowNullPointerException() { + thrown.expect(NullPointerException.class); + final TestEntryController controller = new TestEntryController(); + mEntriesProvider.addController(controller); + + mEntriesProvider.attachInfo(mContext, mProviderInfo); + } + + @Test + public void attachInfo_NoMetaDataInController_shouldThrowNullPointerException() { + thrown.expect(NullPointerException.class); + final TestEntryController controller = new TestEntryController(); + controller.setKey("123"); + mEntriesProvider.addController(controller); + + mEntriesProvider.attachInfo(mContext, mProviderInfo); + } + + @Test + public void attachInfo_duplicateKey_shouldThrowIllegalArgumentException() { + thrown.expect(IllegalArgumentException.class); + final TestEntryController controller1 = new TestEntryController(); + final TestEntryController controller2 = new TestEntryController(); + controller1.setKey("123"); + controller2.setKey("123"); + controller1.setMetaData(new MetaData("category")); + controller2.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller1); + mEntriesProvider.addController(controller2); + + mEntriesProvider.attachInfo(mContext, mProviderInfo); + } + + @Test + public void attachInfo_hasDifferentControllers_shouldNotThrowException() { + final TestEntryController controller1 = new TestEntryController(); + final TestEntryController controller2 = new TestEntryController(); + controller1.setKey("123"); + controller2.setKey("456"); + controller1.setMetaData(new MetaData("category")); + controller2.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller1); + mEntriesProvider.addController(controller2); + + mEntriesProvider.attachInfo(mContext, mProviderInfo); + } + + @Test + public void getEntryData_shouldNotReturnPrimarySwitchData() { + final EntryController controller = new TestPrimarySwitchController("123"); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle switchData = mEntriesProvider.call(METHOD_GET_ENTRY_DATA, "uri", + null /* extras*/); + + final ArrayList<Bundle> dataList = switchData.getParcelableArrayList(EXTRA_ENTRY_DATA); + assertThat(dataList).isEmpty(); + } + + @Test + public void getEntryData_shouldReturnDataList() { + final TestEntryController controller = new TestEntryController(); + final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + controller.setKey("123"); + controller.setMetaData(new MetaData("category").setPendingIntent(pendingIntent)); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle entryData = mEntriesProvider.call(METHOD_GET_ENTRY_DATA, "uri", + null /* extras*/); + + final ArrayList<Bundle> dataList = entryData.getParcelableArrayList(EXTRA_ENTRY_DATA); + assertThat(dataList).hasSize(1); + assertThat(dataList.get(0).getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123"); + assertThat(dataList.get(0).getParcelable(META_DATA_PREFERENCE_PENDING_INTENT, + PendingIntent.class)) + .isEqualTo(pendingIntent); + } + + @Test + public void getSwitchData_shouldReturnDataList() { + final TestEntryController controller = new TestEntryController(); + final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + controller.setKey("123"); + controller.setMetaData(new MetaData("category").setPendingIntent(pendingIntent)); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle entryData = mEntriesProvider.call(METHOD_GET_SWITCH_DATA, "uri", + null /* extras*/); + + final ArrayList<Bundle> dataList = entryData.getParcelableArrayList(EXTRA_SWITCH_DATA); + assertThat(dataList).hasSize(1); + assertThat(dataList.get(0).getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123"); + assertThat(dataList.get(0).getParcelable(META_DATA_PREFERENCE_PENDING_INTENT, + PendingIntent.class)) + .isEqualTo(pendingIntent); + } + + @Test + public void getEntryDataByKey_shouldReturnData() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestEntryController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle entryData = mEntriesProvider.call(METHOD_GET_ENTRY_DATA, "uri", extras); + + assertThat(entryData.getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123"); + } + + @Test + public void getSwitchDataByKey_shouldReturnData() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestEntryController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle entryData = mEntriesProvider.call(METHOD_GET_SWITCH_DATA, "uri", extras); + + assertThat(entryData.getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123"); + } + + @Test + public void isSwitchChecked_shouldReturnCheckedState() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestSwitchController controller = new TestSwitchController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + controller.setSwitchChecked(true); + Bundle result = mEntriesProvider.call(METHOD_IS_CHECKED, "uri", extras); + + assertThat(result.getBoolean(EXTRA_SWITCH_CHECKED_STATE)).isTrue(); + + controller.setSwitchChecked(false); + result = mEntriesProvider.call(METHOD_IS_CHECKED, "uri", extras); + + assertThat(result.getBoolean(EXTRA_SWITCH_CHECKED_STATE)).isFalse(); + } + + @Test + public void getProviderIcon_noImplementInterface_shouldReturnNull() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestEntryController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle iconBundle = mEntriesProvider.call(METHOD_GET_PROVIDER_ICON, "uri", extras); + + assertThat(iconBundle).isNull(); + } + + @Test + public void getProviderIcon_implementInterface_shouldReturnIcon() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestDynamicController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle iconBundle = mEntriesProvider.call(METHOD_GET_PROVIDER_ICON, "uri", extras); + + assertThat(iconBundle).isEqualTo(TestDynamicController.ICON_BUNDLE); + } + + @Test + public void getDynamicTitle_noImplementInterface_shouldReturnNull() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestEntryController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_TITLE, "uri", extras); + + assertThat(result).isNull(); + } + + @Test + public void getDynamicTitle_implementInterface_shouldReturnTitle() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestDynamicController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_TITLE, "uri", extras); + + assertThat(result.getString(META_DATA_PREFERENCE_TITLE)) + .isEqualTo(TestDynamicController.TITLE); + } + + @Test + public void getDynamicSummary_noImplementInterface_shouldReturnNull() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestEntryController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_SUMMARY, "uri", extras); + + assertThat(result).isNull(); + } + + @Test + public void getDynamicSummary_implementInterface_shouldReturnSummary() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestEntryController controller = new TestDynamicController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_SUMMARY, "uri", extras); + + assertThat(result.getString(META_DATA_PREFERENCE_SUMMARY)) + .isEqualTo(TestDynamicController.SUMMARY); + } + + @Test + public void onSwitchCheckedChangedSuccess_shouldReturnNoError() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestSwitchController controller = new TestSwitchController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle result = mEntriesProvider.call(METHOD_ON_CHECKED_CHANGED, "uri", extras); + + assertThat(result.getBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR)).isFalse(); + } + + @Test + public void onSwitchCheckedChangedFailed_shouldReturnErrorMessage() { + final Bundle extras = new Bundle(); + extras.putString(META_DATA_PREFERENCE_KEYHINT, "123"); + final TestSwitchController controller = new TestSwitchController(); + controller.setKey("123"); + controller.setMetaData(new MetaData("category")); + controller.setSwitchErrorMessage("error"); + mEntriesProvider.addController(controller); + mEntriesProvider.attachInfo(mContext, mProviderInfo); + + final Bundle result = mEntriesProvider.call(METHOD_ON_CHECKED_CHANGED, "uri", extras); + + assertThat(result.getBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR)).isTrue(); + assertThat(result.getString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE)).isEqualTo("error"); + } + + private static class TestEntriesProvider extends EntriesProvider { + + private List<EntryController> mControllers; + + @Override + protected List<EntryController> createEntryControllers() { + return mControllers; + } + + void addController(EntryController controller) { + if (mControllers == null) { + mControllers = new ArrayList<>(); + } + mControllers.add(controller); + } + } + + private static class TestEntryController extends EntryController { + + private String mKey; + private MetaData mMetaData; + + @Override + public String getKey() { + return mKey; + } + + @Override + protected MetaData getMetaData() { + return mMetaData; + } + + void setKey(String key) { + mKey = key; + } + + void setMetaData(MetaData metaData) { + mMetaData = metaData; + } + } + + private static class TestSwitchController extends EntryController implements ProviderSwitch { + + private String mKey; + private MetaData mMetaData; + private boolean mChecked; + private String mErrorMsg; + + @Override + public String getKey() { + return mKey; + } + + @Override + protected MetaData getMetaData() { + return mMetaData; + } + + @Override + public boolean isSwitchChecked() { + return mChecked; + } + + @Override + public boolean onSwitchCheckedChanged(boolean checked) { + return mErrorMsg == null ? true : false; + } + + @Override + public String getSwitchErrorMessage(boolean attemptedChecked) { + return mErrorMsg; + } + + void setKey(String key) { + mKey = key; + } + + void setMetaData(MetaData metaData) { + mMetaData = metaData; + } + + void setSwitchChecked(boolean checked) { + mChecked = checked; + } + + void setSwitchErrorMessage(String errorMsg) { + mErrorMsg = errorMsg; + } + } + + private static class TestDynamicController extends TestEntryController + implements ProviderIcon, DynamicTitle, DynamicSummary { + + static final String TITLE = "title"; + static final String SUMMARY = "summary"; + static final Bundle ICON_BUNDLE = new Bundle(); + + @Override + public Bundle getProviderIcon() { + return ICON_BUNDLE; + } + + @Override + public String getDynamicTitle() { + return TITLE; + } + + @Override + public String getDynamicSummary() { + return SUMMARY; + } + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java index abfb407d749e..80f9efb8b5ac 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java @@ -17,20 +17,24 @@ package com.android.settingslib.drawer; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL; import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY; import static com.google.common.truth.Truth.assertThat; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.os.UserHandle; import org.junit.Before; import org.junit.Rule; @@ -173,13 +177,93 @@ public class ProviderTileTest { assertThat(tile.mLastUpdateTime).isNotEqualTo(staleTimeStamp); } + @Test + public void hasPendingIntent_empty_returnsFalse() { + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.hasPendingIntent()).isFalse(); + } + + @Test + public void hasPendingIntent_notEmpty_returnsTrue() { + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + tile.pendingIntentMap.put( + UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0)); + + assertThat(tile.hasPendingIntent()).isTrue(); + } + + @Test + public void hasGroupKey_empty_returnsFalse() { + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.hasGroupKey()).isFalse(); + } + + @Test + public void hasGroupKey_notEmpty_returnsTrue() { + mMetaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key"); + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.hasGroupKey()).isTrue(); + } + + @Test + public void getGroupKey_empty_returnsNull() { + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.getGroupKey()).isNull(); + } + + @Test + public void getGroupKey_notEmpty_returnsValue() { + mMetaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key"); + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.getGroupKey()).isEqualTo("test_key"); + } + + @Test + public void getType_withSwitch_returnsSwitch() { + mMetaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "test://testabc/"); + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.getType()).isEqualTo(Tile.Type.SWITCH); + } + + @Test + public void getType_withSwitchAndPendingIntent_returnsSwitchWithAction() { + mMetaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "test://testabc/"); + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + tile.pendingIntentMap.put( + UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0)); + + assertThat(tile.getType()).isEqualTo(Tile.Type.SWITCH_WITH_ACTION); + } + + @Test + public void getType_withPendingIntent_returnsExternalAction() { + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + tile.pendingIntentMap.put( + UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0)); + + assertThat(tile.getType()).isEqualTo(Tile.Type.EXTERNAL_ACTION); + } + + @Test + public void getType_withoutSwitchAndPendingIntent_returnsGroup() { + final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData); + + assertThat(tile.getType()).isEqualTo(Tile.Type.GROUP); + } + @Implements(TileUtils.class) private static class ShadowTileUtils { private static Bundle sMetaData; @Implementation - protected static Bundle getSwitchDataFromProvider(Context context, String authority, + protected static Bundle getEntryDataFromProvider(Context context, String authority, String key) { return sMetaData; } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index 906e06e81e2b..20864664e512 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -21,6 +21,7 @@ import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; +import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI; import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL; @@ -40,6 +41,7 @@ import static org.mockito.Mockito.when; import static org.robolectric.RuntimeEnvironment.application; import android.app.ActivityManager; +import android.app.PendingIntent; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -350,6 +352,53 @@ public class TileUtilsTest { assertThat(outTiles).isEmpty(); } + @Test + public void loadTilesForAction_multipleUserProfiles_updatesUserHandle() { + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON, + URI_GET_SUMMARY, null, 123, PROFILE_ALL); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt())) + .thenReturn(info); + + TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, + addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */); + TileUtils.loadTilesForAction(mContext, new UserHandle(10), IA_SETTINGS_ACTION, + addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */); + + assertThat(outTiles).hasSize(1); + assertThat(outTiles.get(0).userHandle) + .containsExactly(UserHandle.CURRENT, new UserHandle(10)); + } + + @Test + public void loadTilesForAction_withPendingIntent_updatesPendingIntentMap() { + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON, + URI_GET_SUMMARY, null, 123, PROFILE_ALL); + PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + resolveInfo.activityInfo.metaData + .putParcelable(META_DATA_PREFERENCE_PENDING_INTENT, pendingIntent); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt())) + .thenReturn(info); + + TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, + addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */); + TileUtils.loadTilesForAction(mContext, new UserHandle(10), IA_SETTINGS_ACTION, + addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */); + + assertThat(outTiles).hasSize(1); + assertThat(outTiles.get(0).pendingIntentMap).containsExactly( + UserHandle.CURRENT, pendingIntent, new UserHandle(10), pendingIntent); + } + public static ResolveInfo newInfo(boolean systemApp, String category) { return newInfo(systemApp, category, null); } @@ -424,7 +473,7 @@ public class TileUtilsTest { private static Bundle sMetaData; @Implementation - protected static List<Bundle> getSwitchDataFromProvider(Context context, String authority) { + protected static List<Bundle> getEntryDataFromProvider(Context context, String authority) { return Arrays.asList(sMetaData); } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 56e0643b1e20..ee9883b0b0af 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -320,6 +320,7 @@ <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> + <uses-permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" /> <uses-permission android:name="android.permission.SUSPEND_APPS" /> <uses-permission android:name="android.permission.OBSERVE_APP_USAGE" /> <uses-permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND" /> diff --git a/packages/SystemUI/res/layout/biometric_prompt_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_layout.xml index 595cea8b9018..ecb0bfa35e9f 100644 --- a/packages/SystemUI/res/layout/biometric_prompt_layout.xml +++ b/packages/SystemUI/res/layout/biometric_prompt_layout.xml @@ -39,6 +39,7 @@ android:singleLine="true" android:marqueeRepeatLimit="1" android:ellipsize="marquee" + android:importantForAccessibility="no" style="@style/TextAppearance.AuthCredential.Subtitle"/> <TextView diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 08326cea5327..28a1645ee32c 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesig is herken. Druk om voort te gaan."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesig is herken. Druk die ontsluitikoon om voort te gaan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Gestaaf"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gebruik PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gebruik patroon"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Gebruik wagwoord"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ontsluit met gesig"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gesig is herken"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontsluit om NFC te gebruik"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Probeer \'n ander PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Bevestig verandering vir <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swiep om meer te sien"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Versteek hierdie mediakontrole vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 3397dad443c9..d7cfd0a1ced8 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"መልክ ተለይቶ ታውቋል። ለመቀጠል ይጫኑ።"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"መልክ ተለይቶ ታውቋል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"የተረጋገጠ"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ፒን ይጠቀሙ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ሥርዓተ ጥለትን ተጠቀም"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"የይለፍ ቃልን ተጠቀም"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"በመልክ ተከፍቷል"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"መልክ ተለይቶ ታውቋል"</string> <string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ይህ መሣሪያ ንብረትነቱ የ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ነው"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ሌላ ፒን ይሞክሩ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"ለ<xliff:g id="DEVICE">%s</xliff:g> ለውጥን ያረጋግጡ"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ተጨማሪ ለማየት ያንሸራትቱ"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ሚዲያ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የዚህ ሚዲያ መቆጣጠሪያ ይደበቅ?"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 057f56108186..e23d3b0aa4ee 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"تم التعرّف على الوجه. اضغط للمتابعة."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"تم التعرّف على الوجه. للمتابعة، اضغط على رمز فتح القفل."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"مصادقة"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استخدام رقم تعريف شخصي"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استخدام نقش"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"استخدام كلمة المرور"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"تم فتح قفل جهازك عند تقريبه من وجهك."</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"تم التعرّف على الوجه."</string> <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"افتح قفل الشاشة لاستخدام تقنية NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"حاوِل إدخال رقم تعريف شخصي آخر"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"تأكيد التغيير لـ <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"مرّر سريعًا لرؤية المزيد."</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string> <string name="controls_media_title" msgid="1746947284862928133">"الوسائط"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"هل تريد إخفاء عنصر التحكم في الوسائط هذا للتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>؟"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 9abb8342272f..40618e203887 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যৱহাৰ কৰক"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"আৰ্হি ব্যৱহাৰ কৰক"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"পাছৱৰ্ড ব্যৱহাৰ কৰক"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"মুখাৱয়ব চিনাক্ত কৰা হৈছে"</string> <string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ৰ"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"অন্য এটা পিন ব্যৱহাৰ কৰি চাওক"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>ৰ বাবে সলনি কৰাটো নিশ্চিত কৰক"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"অধিক চাবলৈ ছোৱাইপ কৰক"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string> <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে এই মিডিয়া নিয়ন্ত্ৰণটো লুকুৱাবনে?"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index ad0bd433e129..eadb30920e10 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Üz tanınıb. Davam etmək üçün basın."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb davam edin."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Doğrulandı"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN istifadə edin"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Model istifadə edin"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Parol istifadə edin"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Üz ilə kiliddən çıxarılıb"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Üz tanınıb"</string> <string name="keyguard_retry" msgid="886802522584053523">"Yenidən cəhd etmək üçün yuxarı sürüşdürün"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC istifadə etmək üçün kiliddən çıxarın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz təşkilatınıza məxsusdur"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> təşkilatına məxsusdur"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Başqa PIN\'i yoxlayın"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> üzrə dəyişikliyi təsdiq edin"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Digərlərini görmək üçün sürüşdürün"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tövsiyələr yüklənir"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün bu media nizamlayıcısı gizlədilsin?"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 48360ece2703..0d4b4f353367 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu otključavanja za nastavak."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Identitet je potvrđen"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite šablon"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Koristite lozinku"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano je licem"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste koristili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Probajte drugi PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdite promenu za: <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Prevucite da biste videli još"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Želite da sakrijete ovu kontrolu za medije za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 455059f954f0..1292c5457688 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Твар распазнаны. Націсніце для працягу."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Распазнана"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Увесці PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Выкарыстаць узор разблакіроўкі"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Выкарыстаць пароль"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Разблакіравана распазнаваннем твару"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Твар распазнаны"</string> <string name="keyguard_retry" msgid="886802522584053523">"Прагартайце ўверх, каб паўтарыць спробу"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Разблакіруйце, каб выкарыстоўваць NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Гэта прылада належыць вашай арганізацыі"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Гэта прылада належыць арганізацыі \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Паспрабуйце іншы PIN-код"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Пацвердзіце змяненне для прылады \"<xliff:g id="DEVICE">%s</xliff:g>\""</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Правядзіце пальцам, каб убачыць больш інфармацыі"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загружаюцца рэкамендацыі"</string> <string name="controls_media_title" msgid="1746947284862928133">"Мультымедыя"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Схаваць гэту панэль мультымедыя для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index eb9735837747..079ded0c6145 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -147,6 +147,7 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето бе разпознато. Натиснете, за да продължите."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето бе разпознато. Продължете чрез иконата за отключване."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Удостоверено"</string> + <string name="biometric_dialog_cancel_authentication" msgid="981316588773442637">"Анулиране на удостоверяването"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Използване на ПИН"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Използване на фигура"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Използване на парола"</string> @@ -359,6 +360,7 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Отключено с лице"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицето бе разпознато"</string> <string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string> + <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Плъзнете нагоре, за да изпробвате отново „Отключване с лице“"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отключете, за да използвате NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +930,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Опитайте с друг ПИН код"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Потвърдете промяната за <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Прекарайте пръст, за да видите повече"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string> <string name="controls_media_title" msgid="1746947284862928133">"Мултимедия"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Скриване на мултимед. контрола за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 8d0d57415458..4467c3ebacde 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে আনলক আইকন প্রেস করুন।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"প্রমাণীকৃত"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যবহার করুন"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"প্যাটার্ন ব্যবহার করুন"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"পাসওয়ার্ড ব্যবহার করুন"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ফেস দেখিয়ে আনলক করা হয়েছে"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ফেস চিনে নেওয়া হয়েছে"</string> <string name="keyguard_retry" msgid="886802522584053523">"আবার চেষ্টা করতে উপরের দিকে সোয়াইপ করুন"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যবহার করতে আনলক করুন"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-এর"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"আরেকটি পিন লিখে চেষ্টা করুন"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>-এর জন্য পরিবর্তন কনফার্ম করুন"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"আরও দেখতে সোয়াইপ করুন"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string> <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর মিডিয়া কন্ট্রোল লুকিয়ে রাখতে চান?"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 4792c3691877..aefc7df1184c 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice prepoznato. Pritisnite da nastavite."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu za otklj. da nastavite."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificirano"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristi PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristi uzorak"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Koristi lozinku"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano je licem"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Pokušajte s drugim PIN-om"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdite promjenu za uređaj <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Prevucite da vidite više"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Sakriti kontrolu medija za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index b66d235cfba1..ee4acaa73b41 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"S\'ha reconegut la cara. Prem per continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"S\'ha reconegut la cara. Prem la icona per continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticat"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilitza el PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilitza el patró"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utilitza la contrasenya"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"S\'ha desbloquejat amb la cara"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"S\'ha reconegut la cara"</string> <string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueja per utilitzar l\'NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prova un altre PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirma el canvi per a <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Llisca per veure\'n més"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimèdia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Amagar aquest control multimèdia per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 1ea4c8c1dab6..8afc5303890b 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obličej rozpoznán. Pokračujte stisknutím."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ověřeno"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použít kód PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použít gesto"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Použít heslo"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odemknuto obličejem"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Obličej rozpoznán"</string> <string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC vyžaduje odemknutou obrazovku"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Zkuste jiný PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Ověřte změnu v zařízení <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Přejetím prstem zobrazíte další položky"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string> <string name="controls_media_title" msgid="1746947284862928133">"Média"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Skrýt toto ovládání médií aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 6f112fcffef8..d1175e5db650 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansigt genkendt. Tryk for at fortsætte."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansigt genkendt. Tryk på oplåsningsikonet for at fortsætte."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Godkendt"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Brug pinkode"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Brug mønster"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Brug adgangskode"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst op via ansigtsgenkendelse"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansigtet er genkendt"</string> <string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prøv en anden pinkode"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Bekræft ændring på <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Stryg for at se mere"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medie"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Vil du skjule denne mediefunktion for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 1f26dae0089b..c95f144854fa 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesicht erkannt. Tippe, um fortzufahren."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesicht erkannt. Tippe zum Fortfahren auf das Symbol „Entsperren“."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifiziert"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN verwenden"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Muster verwenden"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Passwort verwenden"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Gerät mit Gesicht entsperrt"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gesicht erkannt"</string> <string name="keyguard_retry" msgid="886802522584053523">"Zum Wiederholen nach oben wischen"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Zur Verwendung von NFC entsperren"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dieses Gerät gehört deiner Organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Andere PIN ausprobieren"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Änderung für <xliff:g id="DEVICE">%s</xliff:g> bestätigen"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Wischen, um weitere zu sehen"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medien"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Mediensteuerung für <xliff:g id="APP_NAME">%1$s</xliff:g> ausblenden?"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index f80fb0d34feb..5ad12898ee8d 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για συνέχεια."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Το πρόσωπο αναγνωρ. Πατήστε το εικον. ξεκλειδ. για συνέχεια."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ολοκληρώθηκε ο έλεγχος ταυτότητας"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Χρήση PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Χρήση μοτίβου"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Χρήση κωδικού πρόσβασης"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ξεκλείδωμα με αναγνώριση προσώπου"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Το πρόσωπο αναγνωρίστηκε"</string> <string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ξεκλείδωμα για χρήση του NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Δοκιμάστε άλλο PIN."</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Επιβεβαίωση αλλαγής για <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Σύρετε για να δείτε περισσότερα."</string> + <string name="retry_face" msgid="416380073082560186">"Επανάληψη ελέγχου ταυτότητας προσώπου"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string> <string name="controls_media_title" msgid="1746947284862928133">"Μέσα"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Απόκρυψη στοιχ. ελέγχου μέσων για <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index b265bdcf5c75..a917ab5f7872 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Use password"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Try another PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Hide this media control for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index f10386b914e4..b70060375b2b 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -147,6 +147,7 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> + <string name="biometric_dialog_cancel_authentication" msgid="981316588773442637">"Cancel Authentication"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Use password"</string> @@ -359,6 +360,7 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognized"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> + <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Swipe up to try Face Unlock again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organization"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +930,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Try another PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string> + <string name="retry_face" msgid="416380073082560186">"Retry face authentication"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Hide this media control for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index b265bdcf5c75..a917ab5f7872 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Use password"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Try another PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Hide this media control for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index b265bdcf5c75..a917ab5f7872 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Use password"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Try another PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Hide this media control for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 530474bded94..c646d9348bf8 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -147,6 +147,7 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> + <string name="biometric_dialog_cancel_authentication" msgid="981316588773442637">"Cancel Authentication"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Use password"</string> @@ -359,6 +360,7 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognized"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> + <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Swipe up to try Face Unlock again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organization"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +930,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Try another PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string> + <string name="retry_face" msgid="416380073082560186">"Retry face authentication"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Hide this media control for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 98f8c1de8bdf..343eb9914c2c 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -147,6 +147,7 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rostro reconocido. Presiona para continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rostro reconocido. Presiona el desbloqueo para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> + <string name="biometric_dialog_cancel_authentication" msgid="981316588773442637">"Cancelar autenticación"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar contraseña"</string> @@ -359,6 +360,7 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Se desbloqueó con el rostro"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Se reconoció el rostro"</string> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string> + <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Desliza hacia arriba para volver a probar Desbloqueo facial"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea el dispositivo para usar NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +930,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prueba con otro PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirmar cambio para <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más elementos"</string> + <string name="retry_face" msgid="416380073082560186">"Vuelve a intentar la autenticación facial"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string> <string name="controls_media_title" msgid="1746947284862928133">"Contenido multimedia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"¿Ocultar control multimedia para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 729d63455971..c9eec503966a 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Cara reconocida. Pulsa para continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Cara reconocida. Pulsa el icono de desbloquear para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Se ha autenticado"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar contraseña"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado con la cara"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Cara reconocida"</string> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea para usar el NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prueba con otro PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirma el cambio de <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"¿Ocultar este control multimedia para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index edb38307a175..fd37375e1233 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nägu tuvastati. Vajutage jätkamiseks."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nägu tuvastati. Jätkamiseks vajutage avamise ikooni."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenditud"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Kasuta PIN-koodi"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Kasuta mustrit"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Kasuta parooli"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Avati näoga"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Nägu tuvastati"</string> <string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC kasutamiseks avage."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Proovige muud PIN-koodi"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Kinnitage seadme <xliff:g id="DEVICE">%s</xliff:g> muudatus"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Pühkige sõrmega, et näha rohkem"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string> <string name="controls_media_title" msgid="1746947284862928133">"Meedia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Kas peita see rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> meediajuhik?"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 545d2a25bb56..e923e6b6f5ba 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ezagutu da aurpegia. Sakatu aurrera egiteko."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ezagutu da aurpegia. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikatuta"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Erabili PINa"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Erabili eredua"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Erabili pasahitza"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Aurpegiaren bidez desblokeatu da"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ezagutu da aurpegia"</string> <string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokea ezazu NFCa erabiltzeko"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Gailu hau zure erakundearena da"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Gailu hau <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> erakundearena da"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Saiatu beste PIN batekin"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Berretsi <xliff:g id="DEVICE">%s</xliff:g> gailuaren aldaketa"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasatu hatza aukera gehiago ikusteko"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Multimedia kontrolatzeko aukerak (<xliff:g id="APP_NAME">%1$s</xliff:g>) ezkutatu?"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index d53dba03c1af..9f36e5755a7b 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چهره شناسایی شد. برای ادامه، فشار دهید."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چهره شناسایی شد. برای ادامه، نماد قفلگشایی را فشار دهید."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"راستیآزماییشده"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استفاده از پین"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استفاده از الگو"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"استفاده از گذرواژه"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"قفل با چهره باز شد"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"چهره شناسایی شد"</string> <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند بهبالا بکشید"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"برای استفاده از NFC، قفل را باز کنید"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> تعلق دارد"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"پین دیگری را امتحان کنید"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"تأیید تغییر مربوط به <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"برای دیدن موارد بیشتر، تند بکشید"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیهها"</string> <string name="controls_media_title" msgid="1746947284862928133">"رسانه"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"این کنترل رسانه برای <xliff:g id="APP_NAME">%1$s</xliff:g> پنهان شود؟"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index c005ec49d603..d89098acff88 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Kasvot tunnistettu. Jatka painamalla."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Todennettu"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Käytä PIN-koodia"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Käytä kuviota"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Käytä salasanaa"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Avattu kasvojen avulla"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Kasvot tunnistettu"</string> <string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus, jotta voit käyttää NFC:tä"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> omistaa tämän laitteen"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Kokeile toista PIN-koodia"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Vahvista muutos: <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Pyyhkäise nähdäksesi lisää"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Piilotetaanko mediaohjain (<xliff:g id="APP_NAME">%1$s</xliff:g>)?"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 5a629bc85b16..0c92649f0337 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur Déverrouiller pour continuer."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un NIP"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utiliser un mot de passe"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Déverrouillé avec le visage"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Visage reconnu"</string> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la CCP"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Essayez un autre NIP"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirmer la modification pour <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Balayez l\'écran pour en afficher davantage"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Commandes multimédias"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Masquer ce contrôleur de contenu multimédia pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index dc3bd0d3a8f8..1f088d26f6bc 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour continuer."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un code PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utiliser un mot de passe"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Déverrouillé par le visage"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Visage reconnu"</string> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour pouvoir utiliser le NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Essayez un autre code PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirmer la modification pour <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Balayer l\'écran pour voir plus d\'annonces"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Masquer cette commande multimédia pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 453849a4d610..466a60e33706 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Recoñeceuse a cara. Preme para continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Recoñeceuse a cara. Preme a icona de desbloquear."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrón"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar contrasinal"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Usouse o desbloqueo facial"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Recoñeceuse a cara"</string> <string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea o dispositivo para utilizar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Proba con outro PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirma o cambio para <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasar o dedo para ver máis"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string> <string name="controls_media_title" msgid="1746947284862928133">"Contido multimedia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Queres ocultar este control multimedia para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index ea4f871b4910..24ac365b0591 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ચહેરો ઓળખ્યો. આગળ વધવા માટે દબાવો."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ચહેરો ઓળખ્યો. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"પ્રમાણિત"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"પિનનો ઉપયોગ કરો"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"પૅટર્નનો ઉપયોગ કરો"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"પાસવર્ડનો ઉપયોગ કરો"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ચહેરા દ્વારા અનલૉક કર્યું"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ચહેરો ઓળખ્યો"</string> <string name="keyguard_retry" msgid="886802522584053523">"ફરી પ્રયાસ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCનો ઉપયોગ કરવા માટે અનલૉક કરો"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"આ ડિવાઇસ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ની માલિકીનું છે"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"બીજા પિનને અજમાવી જુઓ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> માટે ફેરફાર કન્ફર્મ કરો"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"વધુ જોવા માટે સ્વાઇપ કરો"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string> <string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"શું <xliff:g id="APP_NAME">%1$s</xliff:g> માટે મીડિયાના નિયંત્રણો છુપાવીએ?"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index e6a134b645c9..fae8082a75b0 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरे की पहचान हो गई. जारी रखने के लिए टैप करें."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरे की पहचान हो गई. जारी रखने के लिए अनलॉक आइकॉन को टैप करें."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"पुष्टि हो गई"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन इस्तेमाल करें"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पैटर्न इस्तेमाल करें"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"पासवर्ड इस्तेमाल करें"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"चेहरे से अनलॉक किया गया"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"चेहरे की पहचान हो गई"</string> <string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए स्क्रीन को अनलॉक करें"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> के पास है"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"कोई और पिन आज़माएं"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> में बदलाव के लिए पुष्टि करें"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ज़्यादा देखने के लिए स्वाइप करें"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string> <string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"क्या <xliff:g id="APP_NAME">%1$s</xliff:g> के लिए, इस मीडिया कंट्रोल को छिपाना है?"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index c9b5d3551702..e32cc42dff08 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste nastavili."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikacija izvršena"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite uzorak"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Koristite zaporku"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano licem"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string> <string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste upotrijebili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Pokušajte s drugim PIN-om"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdite promjenu za uređaj <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Prijeđite prstom da vidite više"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Želite li sakriti kontroler medija za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 065a1db54435..6fed11d1fdde 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Arc felismerve. Koppintson a folytatáshoz."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Arc felismerve. A folytatáshoz koppintson a Feloldásra."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Hitelesítve"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-kód használata"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Minta használata"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Jelszó használata"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Zárolás arccal feloldva"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Arc felismerve"</string> <string name="keyguard_retry" msgid="886802522584053523">"Az újrapróbálkozáshoz csúsztassa felfelé az ujját"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Az NFC használatához oldja fel a képernyőzárat"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ez az eszköz az Ön szervezetének tulajdonában van"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ez az eszköz a(z) <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tulajdonában van"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Próbálkozzon másik kóddal"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"A(z) <xliff:g id="DEVICE">%s</xliff:g> módosításának megerősítése"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Továbbiak megtekintéséhez csúsztasson"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Média"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Elrejti ezt a(z) <xliff:g id="APP_NAME">%1$s</xliff:g>-médiavezérlőt?"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 0f72f07f1ac0..2c1a935b08bc 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Դեմքը ճանաչվեց։ Սեղմեք շարունակելու համար։"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Դեմքը ճանաչվեց։ Սեղմեք ապակողպման պատկերակը։"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Նույնականացված է"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Օգտագործել PIN կոդ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Օգտագործել նախշ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Օգտագործել գաղտնաբառ"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ապակողպվեց դեմքով"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Դեմքը ճանաչվեց"</string> <string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր ընկերությանը"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>» կազմակերպությանը"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Փորձեք մեկ այլ PIN կոդ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Հաստատեք փոփոխությունը <xliff:g id="DEVICE">%s</xliff:g> սարքի համար"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Սահեցրեք մատը՝ ավելին իմանալու համար"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Բեռնման խորհուրդներ"</string> <string name="controls_media_title" msgid="1746947284862928133">"Մեդիա"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Թաքցնե՞լ <xliff:g id="APP_NAME">%1$s</xliff:g>-ի մեդիա աշխատաշրջանի կառավարման տարրը։"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 6efb071ff122..347e3411f297 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dikenali. Tekan untuk melanjutkan."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dikenali. Tekan ikon buka kunci untuk melanjutkan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Diautentikasi"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan pola"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Gunakan sandi"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Kunci dibuka dengan wajah"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Wajah dikenali"</string> <string name="keyguard_retry" msgid="886802522584053523">"Geser ke atas untuk mencoba lagi"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Perangkat ini milik organisasi Anda"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Perangkat ini milik <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Coba PIN lain"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Konfirmasi perubahan untuk <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Geser untuk melihat selengkapnya"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuat rekomendasi"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Sembunyikan kontrol media untuk <xliff:g id="APP_NAME">%1$s</xliff:g> ini?"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 7de8cd11efec..2b78e2469fbf 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Andlitið var greint. Ýttu til að halda áfram."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Andlitið var greint. Ýttu á opnunartáknið til að halda áfr."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Auðkennt"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Nota PIN-númer"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Nota mynstur"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Nota aðgangsorð"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Opnað með andliti"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Andlitið var greint"</string> <string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Taktu úr lás til að nota NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prófaðu annað PIN-númer"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Staðfesta breytingu fyrir <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Strjúktu til að sjá meira"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string> <string name="controls_media_title" msgid="1746947284862928133">"Margmiðlunarefni"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Fela þessa efnisstýringu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 6accfd1f6f7d..ebd3a3f8874b 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Volto riconosciuto. Premi per continuare."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Volto riconosciuto. Premi l\'icona Sblocca e continua."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticazione eseguita"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizza PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usa sequenza"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utilizza password"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Sbloccato con il volto"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Volto riconosciuto"</string> <string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Sblocca per usare NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Questo dispositivo appartiene alla tua organizzazione"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prova con un altro PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Conferma modifica per <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Scorri per vedere altro"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string> <string name="controls_media_title" msgid="1746947284862928133">"Contenuti multimediali"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Nascondere questo controllo multimediale per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 4226d92e58b6..8fbf1a5ad38e 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"הפנים זוהו. יש ללחוץ כדי להמשיך."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"הפנים זוהו. להמשך יש ללחוץ על סמל ביטול הנעילה."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"מאומת"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"שימוש בקוד אימות"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"שימוש בקו ביטול נעילה"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"שימוש בסיסמה"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"הנעילה בוטלה באמצעות זיהוי הפנים"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"הפנים זוהו"</string> <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"יש לבטל את הנעילה כדי להשתמש ב-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"המכשיר הזה שייך לארגון שלך"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"המכשיר הזה שייך לארגון <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"יש לנסות קוד אימות אחר"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"יש לאשר את השינוי עבור <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"יש להחליק כדי להציג עוד פריטים"</string> + <string name="retry_face" msgid="416380073082560186">"איך מנסים שוב לזהות את הפנים לצורך אימות"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ההמלצות בטעינה"</string> <string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"להסתיר את בקר המדיה הזה לאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 182dab4cb83a..3e948c6f84cc 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"顔を認識しました。押して続行してください。"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"顔を認識しました。ロック解除アイコンを押して続行します。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"認証済み"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN を使用"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"パターンを使用"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"パスワードを使用"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"顔でロック解除しました"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"顔を認識しました"</string> <string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC を使用するには、ロックを解除してください"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"これは <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が所有するデバイスです"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"別の PIN をお試しください"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>の変更を確認する"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"スワイプすると他の構造が表示されます"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string> <string name="controls_media_title" msgid="1746947284862928133">"メディア"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> のこのコントロールを非表示にしますか?"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 7caf1703cdb4..1fac1d0600a6 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ამოცნობილია სახით. დააჭირეთ გასაგრძელებლად."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ამოცნობილია სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ავტორიზებულია"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-კოდის გამოყენება"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ნიმუშის გამოყენება"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"პაროლის გამოყენება"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"განიბლოკა სახით"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"სახე ამოცნობილია"</string> <string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"განბლოკეთ NFC-ის გამოსაყენებლად"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"სხვა PIN-კოდის ცდა"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"დაადასტურეთ ცვლილება <xliff:g id="DEVICE">%s</xliff:g>-ისთვის"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"გადაფურცლეთ მეტის სანახავად"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string> <string name="controls_media_title" msgid="1746947284862928133">"მედია"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"დაიმალოს მედიის ეს კონტროლერი <xliff:g id="APP_NAME">%1$s</xliff:g> აპში?"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 8f60d73c3964..27f43861d0a9 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Бет танылды. Жалғастыру үшін басыңыз."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Бет танылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификацияланған"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодын пайдалану"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Өрнекті пайдалану"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Құпия сөзді пайдалану"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Бетпен ашылды."</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Бет танылды."</string> <string name="keyguard_retry" msgid="886802522584053523">"Әрекетті қайталау үшін жоғары сырғытыңыз."</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC пайдалану үшін құлыпты ашыңыз."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бұл құрылғы ұйымыңызға тиесілі."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Бұл құрылғы <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ұйымына тиесілі."</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Басқа PIN кодын енгізіңіз"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> құрылғысындағы өзгерісті растау"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Толығырақ ақпарат алу үшін сырғытыңыз."</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Жүктеуге қатысты ұсыныстар"</string> <string name="controls_media_title" msgid="1746947284862928133">"Мультимедиа"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін медиа контроллері жасырылсын ба?"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 097fc17a4557..dbdfb86cc382 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"បានស្គាល់មុខ។ សូមចុច ដើម្បីបន្ត។"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"បានស្គាល់មុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"បានផ្ទៀងផ្ទាត់"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ប្រើកូដ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ប្រើលំនាំ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"ប្រើពាក្យសម្ងាត់"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"បានដោះសោដោយប្រើមុខ"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"បានស្គាល់មុខ"</string> <string name="keyguard_retry" msgid="886802522584053523">"អូសឡើងលើ ដើម្បីព្យាយាមម្ដងទៀត"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ដោះសោ ដើម្បីប្រើ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ឧបករណ៍នេះគឺជាកម្មសិទ្ធិរបស់ស្ថាប័នអ្នក"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ឧបករណ៍នេះគឺជាកម្មសិទ្ធិរបស់ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"សាកល្បងប្រើកូដ PIN ផ្សេងទៀត"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"បញ្ជាក់ការផ្លាស់ប្ដូរសម្រាប់ <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"អូសដើម្បីមើលច្រើនទៀត"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"កំពុងផ្ទុកការណែនាំ"</string> <string name="controls_media_title" msgid="1746947284862928133">"មេឌៀ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"លាក់ផ្ទាំងគ្រប់គ្រងមេឌៀនេះសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index a7df97806444..44d6a0307523 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ಪಿನ್ ಬಳಸಿ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ಪ್ಯಾಟರ್ನ್ ಬಳಸಿ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"ಪಾಸ್ವರ್ಡ್ ಬಳಸಿ"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ಮುಖದ ಮೂಲಕ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ಗೆ ಸೇರಿದೆ"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ಮತ್ತೊಂದು ಪಿನ್ ಅನ್ನು ಪ್ರಯತ್ನಿಸಿ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ಸಾಧನಕ್ಕಾಗಿ ಬದಲಾವಣೆಯನ್ನು ದೃಢೀಕರಿಸಿ"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ಇನ್ನಷ್ಟು ನೋಡಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string> + <string name="retry_face" msgid="416380073082560186">"ಮುಖದ ದೃಢೀಕರಣವನ್ನು ಮರುಪ್ರಯತ್ನಿಸಿ"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ಮಾಧ್ಯಮ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಈ ಮಾಧ್ಯಮ ಕಂಟ್ರೋಲ್ಗಳನ್ನು ಮರೆಮಾಡಬೇಕೆ?"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index db9ffcf12cd5..6272ce4c248d 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"얼굴이 인식되었습니다. 계속하려면 누르세요."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"얼굴이 인식되었습니다. 계속하려면 아이콘을 누르세요."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"인증됨"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN 사용"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"패턴 사용"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"비밀번호 사용"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"얼굴 인식으로 잠금 해제되었습니다."</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"얼굴이 인식되었습니다."</string> <string name="keyguard_retry" msgid="886802522584053523">"위로 스와이프하여 다시 시도해 주세요"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"잠금 해제하여 NFC 사용"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"내 조직에 속한 기기입니다."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>에 속한 기기입니다."</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"다른 PIN으로 다시 시도"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> 변경 확인"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"자세히 보려면 스와이프하세요."</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"추천 제어 기능 로드 중"</string> <string name="controls_media_title" msgid="1746947284862928133">"미디어"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 미디어 컨트롤을 숨길까요?"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index c0459020d75f..e30f2994438c 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Жүз таанылды. Улантуу үчүн басыңыз."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Жүз таанылды. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аныктыгы текшерилди"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодду колдонуу"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Графикалык ачкычты колдонуу"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Сырсөз колдонуу"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Түзмөгүңүздү жүзүңүз менен ачтыңыз"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Жүз таанылды"</string> <string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC колдонуу үчүн түзмөктүн кулпусун ачыңыз"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бул түзмөк уюмуңузга таандык"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Бул түзмөк төмөнкүгө таандык: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Башка PIN кодду колдонуңүз"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> түзмөгү үчүн өзгөртүүнү ырастаңыз"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Дагы көрүү үчүн экранды сүрүп коюңуз"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Сунуштар жүктөлүүдө"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> \'да ушул медиа башкарууну жашырасызбы?"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index e2d90d9fa981..e3ec93e6495f 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ໃຊ້ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ໃຊ້ຮູບແບບ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"ໃຊ້ລະຫັດຜ່ານ"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ປົດລັອກດ້ວຍໃບໜ້າແລ້ວ"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ຈຳແນກໜ້າໄດ້ແລ້ວ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ປົດລັອກເພື່ອໃຊ້ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ອຸປະກອນນີ້ເປັນຂອງ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ລອງໃຊ້ PIN ອື່ນ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"ຢືນຢັນການປ່ຽນແປງສຳລັບ <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ປັດເພື່ອເບິ່ງເພີ່ມເຕີມ"</string> + <string name="retry_face" msgid="416380073082560186">"ລອງການພິສູດຢືນຢັນດ້ວຍໃບໜ້າຄືນໃໝ່"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"ເຊື່ອງຕົວຄວບຄຸມມີເດຍນີ້ສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index a338e09f12ca..11d96de070d5 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Veidas atpažintas. Paspauskite, jei norite tęsti."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Veidas atpažintas. Tęskite paspaudę atrakinimo piktogramą."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikuota"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Naudoti PIN kodą"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Naudoti atrakinimo piešinį"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Naudoti slaptažodį"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Atrakinta pagal veidą"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Veidas atpažintas"</string> <string name="keyguard_retry" msgid="886802522584053523">"Jei norite bandyti dar kartą, perbraukite aukštyn"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Norėdami naudoti NFC, atrakinkite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šis įrenginys priklauso jūsų organizacijai"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Šis įrenginys priklauso „<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>“"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Išbandykite kitą PIN kodą"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Patvirtinti <xliff:g id="DEVICE">%s</xliff:g> pakeitimą"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Perbraukite, kad peržiūrėtumėte daugiau"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medija"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Slėpti šį programos „<xliff:g id="APP_NAME">%1$s</xliff:g>“ medijos valdiklį?"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 053e984694eb..7f07ecd9f838 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Seja atpazīta. Nospiediet, lai turpinātu."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Seja atpazīta. Lai turpinātu, nospiediet atbloķēšanas ikonu."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikācija veikta"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Izmantot PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Izmantot kombināciju"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Izmantot paroli"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ierīce atbloķēta pēc sejas"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Seja atpazīta"</string> <string name="keyguard_retry" msgid="886802522584053523">"Velciet augšup, lai mēģinātu vēlreiz"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Atbloķējiet ierīci, lai izmantotu NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šī ierīce pieder jūsu organizācijai."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Šī ierīce pieder organizācijai <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Izmēģiniet citu PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Izmaiņu apstiprināšana ierīcei <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Velciet, lai skatītu citus vienumus"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multivide"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Vai paslēpt šo lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> multivides vadīklu?"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 1632600cf2e2..6b7cb27e5e6a 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето е препознаено. Притиснете за да продолжите."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето е препознаено. Притиснете ја иконата за отклучување за да продолжите."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Проверена"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користи PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користи шема"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Користи лозинка"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Отклучено со лице"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицето е препознаено"</string> <string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отклучете за да користите NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Обидете се со друг PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Потврдете ја промената за <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Повлечете за да видите повеќе"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string> <string name="controls_media_title" msgid="1746947284862928133">"Аудиовизуелни содржини"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Да се скријат контролите за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index b753e98c0184..79c26677e292 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അമർത്തുക."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"പരിശോധിച്ചുറപ്പിച്ചു"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"പിൻ ഉപയോഗിക്കുക"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"പാറ്റേൺ ഉപയോഗിക്കുക"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"പാസ്വേഡ് ഉപയോഗിക്കുക"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"മുഖം തിരിച്ചറിഞ്ഞു"</string> <string name="keyguard_retry" msgid="886802522584053523">"വീണ്ടും ശ്രമിക്കാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ഈ ഉപകരണം <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> എന്ന സ്ഥാപനത്തിന്റേതാണ്"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"മറ്റൊരു പിൻ പരീക്ഷിക്കുക"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> എന്നതിനുള്ള മാറ്റം സ്ഥിരീകരിക്കുക"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"കൂടുതൽ കാണാൻ സ്വൈപ്പ് ചെയ്യുക"</string> + <string name="retry_face" msgid="416380073082560186">"മുഖം പരിശോധിച്ചുറപ്പിക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string> <string name="controls_media_title" msgid="1746947284862928133">"മീഡിയ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനുള്ള ഈ മീഡിയാ കൺട്രോൾ മറയ്ക്കണോ?"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 927dbdf6137b..5b88ec95529b 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Царайг таньсан. Үргэлжлүүлэхийн тулд дарна уу."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Царайг таньсан. Үргэлжлүүлэх бол түгжээг тайлах дүрсийг дар."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Баталгаажуулагдсан"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ПИН ашиглах"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Хээ ашиглах"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Нууц үг ашиглах"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Царайгаар түгжээг тайлсан"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Царайг таньсан"</string> <string name="keyguard_retry" msgid="886802522584053523">"Дахин оролдохын тулд дээш шударна уу"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC-г ашиглахын тулд түгжээг тайлна уу"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Энэ төхөөрөмж <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-д харьяалагддаг"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Өөр ПИН ашиглах"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>-н өөрчлөлтийг баталгаажуулна уу"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Илүү ихийг харахын тулд шударна уу"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Зөвлөмжүүдийг ачаалж байна"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Энэ медиа хяналтыг <xliff:g id="APP_NAME">%1$s</xliff:g>-д нуух уу?"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index e54bcfc67c10..c0d3191ce790 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी अनलॉक करा आयकन प्रेस करा."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ऑथेंटिकेशन केलेले"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन वापरा"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पॅटर्न वापरा"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"पासवर्ड वापरा"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"चेहऱ्याने अनलॉक केले आहे"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"चेहरा ओळखला आहे"</string> <string name="keyguard_retry" msgid="886802522584053523">"पुन्हा प्रयत्न करण्यासाठी वर स्वाइप करा"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC वापरण्यासाठी स्क्रीन अनलॉक करा"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> चे आहे"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"दुसरा पिन वापरून पहा"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> च्या बदलांची निश्चिती करा"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"अधिक पाहण्यासाठी स्वाइप करा"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string> <string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी हा मीडिया नियंत्रक लपवायचा आहे का?"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index a73a743a7808..9d46cb11c661 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dicam. Tekan untuk meneruskan."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dicam. Tekan ikon buka kunci untuk meneruskan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Disahkan"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan corak"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Gunakan kata laluan"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Dibuka kunci dengan wajah"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Wajah dicam"</string> <string name="keyguard_retry" msgid="886802522584053523">"Leret ke atas untuk mencuba lagi"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Peranti ini milik organisasi anda"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Peranti ini milik <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Cuba PIN lain"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Sahkan perubahan untuk <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Leret untuk melihat selanjutnya"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuatkan cadangan"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Sembunyikan kawalan media ini untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 2962966c2c06..747f35829219 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"အထောက်အထားစိစစ်ပြီးပြီ"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ပင်နံပါတ်သုံးရန်"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ပုံစံကို သုံးရန်"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"စကားဝှက် သုံးရန်"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"မျက်နှာဖြင့် ဖွင့်လိုက်သည်"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"မျက်နှာ မှတ်မိသည်"</string> <string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ကို အသုံးပြုရန် လော့ခ်ဖွင့်ပါ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က ပိုင်ဆိုင်သည်"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"နောက်ပင်နံပါတ်တစ်ခု စမ်းကြည့်ရန်"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> အတွက် အပြောင်းအလဲကို အတည်ပြုပါ"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ပိုကြည့်ရန် ပွတ်ဆွဲပါ"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string> <string name="controls_media_title" msgid="1746947284862928133">"မီဒီယာ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် ဤမီဒီယာထိန်းချုပ်မှု ဖျောက်ထားမလား။"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 682b4a0f2364..2f67bbd9b8ad 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet er gjenkjent. Trykk for å fortsette."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentisert"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Bruk PIN-kode"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Bruk mønster"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Bruk passord"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst opp med ansiktet"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansiktet er gjenkjent"</string> <string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås opp for å bruke NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prøv en annen PIN-kode"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Bekreft endringen for <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Sveip for å se flere"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medier"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Vil du skjule denne mediekontrollen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index d9ee7a36e84a..5f3dd505159b 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"अनुहार पहिचान गरियो। जारी राख्न थिच्नुहोस्।"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"अनुहार पहिचान गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"प्रमाणीकरण गरियो"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN प्रयोग गर्नुहोस्"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ढाँचा प्रयोग गर्नुहोस्"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"पासवर्ड प्रयोग गर्नुहोस्"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"अनुहार प्रयोग गरी अनलक गरियो"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"अनुहार पहिचान गरियो"</string> <string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"यो डिभाइस तपाईंको सङ्गठनको स्वामित्वमा छ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"यो डिभाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> को स्वामित्वमा छ"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"अर्को PIN प्रयोग गरी हेर्नु…"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> का हकमा गरिएको परिवर्तन पुष्टि गर्नुहोस्"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"थप हेर्न स्वाइप गर्नुहोस्"</string> + <string name="retry_face" msgid="416380073082560186">"फेरि अनुहारमार्फत प्रमाणीकरण गरी हेर्नुहोस्"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string> <string name="controls_media_title" msgid="1746947284862928133">"मिडिया"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> का हकमा यो मिडिया कन्ट्रोल लुकाउने हो?"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 70c746ccc36f..20a41b1d3b32 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gezicht herkend. Druk om door te gaan."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gezicht herkend. Druk op het ontgrendelicoon."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Geverifieerd"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Pincode gebruiken"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Patroon gebruiken"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Wachtwoord gebruiken"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ontgrendeld via gezicht"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gezicht herkend"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe omhoog om het opnieuw te proberen"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontgrendel het apparaat om NFC te gebruiken"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Andere pincode proberen"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Bevestig de wijziging voor <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe om meer te zien"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Deze mediabediening verbergen voor <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 192aee7518bc..3137de2cbd8b 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ପ୍ରାମାଣିକତା ହୋଇଛି"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"ପାସ୍ୱାର୍ଡ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି"</string> <string name="keyguard_retry" msgid="886802522584053523">"ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ର ଅଟେ"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ଅନ୍ୟ ଏକ PIN ଚେଷ୍ଟା କରି ଦେଖନ୍ତୁ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ପାଇଁ ପରିବର୍ତ୍ତନ ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ଅଧିକ ଦେଖିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string> <string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଏହି ମିଡିଆ ନିୟନ୍ତ୍ରଣକୁ ଲୁଚାଇବେ?"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 4f1960a32eb6..b9f7e8ba5989 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ਪਿੰਨ ਵਰਤੋ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ਪੈਟਰਨ ਵਰਤੋ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"ਪਾਸਵਰਡ ਵਰਤੋ"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਉੱਤੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ਕੋਈ ਹੋਰ ਪਿੰਨ ਵਰਤ ਕੇ ਦੇਖੋ"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ਲਈ ਤਬਦੀਲੀ ਦੀ ਤਸਦੀਕ ਕਰੋ"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"ਹੋਰ ਦੇਖਣ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਇਹ ਮੀਡੀਆ ਕੰਟਰੋਲ ਲੁਕਾਉਣਾ ਹੈ?"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index a98616cdd349..a3fa36759101 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Twarz rozpoznana. Kliknij, aby kontynuować."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Twarz rozpoznana. Aby kontynuować, kliknij ikonę odblokowywania."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Uwierzytelniono"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Użyj kodu PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Użyj wzoru"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Użyj hasła"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odblokowano skanem twarzy"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Twarz rozpoznana"</string> <string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć komunikacji NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"To urządzenie należy do Twojej organizacji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Właściciel tego urządzenia: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Wpisz inny kod PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Potwierdź zmianę dotyczącą urządzenia <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Przesuń palcem, by zobaczyć więcej"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ukryć sterowanie multimediami w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 1db32e8166e1..4dc74c4df316 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar senha"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado pelo rosto"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à organização <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Tente usar outro PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirme a mudança para <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize para ver mais"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ocultar este controle de mídia para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index c9e41766a2f0..6e06aa9c8a56 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -147,6 +147,7 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Prima para continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Prima ícone de desbloqueio para continuar"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> + <string name="biometric_dialog_cancel_authentication" msgid="981316588773442637">"Cancelar autenticação"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar palavra-passe"</string> @@ -359,6 +360,7 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado com o rosto"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string> + <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Deslize para cima para tentar o Desbloqueio facial novamente"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para utilizar o NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua entidade."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> @@ -928,6 +930,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Experimente outro PIN."</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirme a alteração para <xliff:g id="DEVICE">%s</xliff:g>."</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize rapidamente para ver mais."</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ocultar controlo de multimédia para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 1db32e8166e1..4dc74c4df316 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar senha"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado pelo rosto"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à organização <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Tente usar outro PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirme a mudança para <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize para ver mais"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ocultar este controle de mídia para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 95ac2233b8af..1b96e9057120 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Chipul a fost recunoscut. Apasă pentru a continua."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Chip recunoscut. Apasă pictograma Deblocare ca să continui."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificat"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Folosește PIN-ul"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Folosește modelul"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Folosește parola"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"S-a deblocat folosind fața"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Chipul a fost recunoscut"</string> <string name="keyguard_retry" msgid="886802522584053523">"Glisează pentru a încerca din nou"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Deblochează pentru a folosi NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației tale"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Acest dispozitiv aparține organizației <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Încearcă alt cod PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Confirmă schimbarea pentru <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Glisează pentru a vedea mai multe"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Se încarcă recomandările"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ascunzi comanda media pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 182fe52db22b..dbf2543109e3 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицо распознано. Нажмите, чтобы продолжить."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицо распознано. Нажмите на значок разблокировки."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификация выполнена"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Использовать графический ключ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Использовать пароль"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Разблокировано сканированием лица"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицо распознано"</string> <string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Чтобы использовать NFC, разблокируйте устройство."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Этим устройством владеет организация \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Введите другой PIN-код"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Подтвердите изменения для устройства \"<xliff:g id="DEVICE">%s</xliff:g>\""</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Проведите по экрану, чтобы увидеть больше"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загрузка рекомендаций…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Скрыть этот элемент в приложении \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index a83ac866acf7..56eca2e15f3a 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට ඔබන්න."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"සත්යාපනය විය"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN භාවිත කරන්න"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"රටාව භාවිත කරන්න"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"මුරපදය භාවිත කරන්න"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"මුහුණ මගින් අගුලු හරින ලදි"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"මුහුණ හඳුනා ගන්නා ලදි"</string> <string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC භාවිත කිරීමට අගුලු හරින්න"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> සංවිධානයට අයිතිය"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"තවත් PIN එකක් උත්සාහ කරන්න"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> සඳහා වෙනස තහවුරු කරන්න"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"තව බැලීමට ස්වයිප් කරන්න"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string> <string name="controls_media_title" msgid="1746947284862928133">"මාධ්ය"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා මෙම මාධ්ය පාලනය වසන්නද?"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 322386acc039..b9c5eed5928f 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Tvár bola rozpoznaná. Pokračujte stlačením."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Tvár bola rozpoznaná. Pokračujte stlačením ikony odomknutia"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Overené"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použiť PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použiť vzor"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Použiť heslo"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odomknuté tvárou"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Tvár bola rozpoznaná"</string> <string name="keyguard_retry" msgid="886802522584053523">"Potiahnutím nahor to skúste znova"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ak chcete použiť NFC, odomknite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zariadenie patrí vašej organizácii"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zariadení patrí organizácii <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,7 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Skúste iný PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdenie zmeny zariadenia <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Potiahnutím zobrazíte ďalšie položky"</string> + <string name="retry_face" msgid="416380073082560186">"Znova skúsiť overenie tvárou"</string> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string> <string name="controls_media_title" msgid="1746947284862928133">"Médiá"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Chcete tento ovládač médií pre <xliff:g id="APP_NAME">%1$s</xliff:g> skryť?"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index a1e62d240ccc..6d8976e01a53 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obraz je prepoznan. Pritisnite za nadaljevanje."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obraz je prepoznan. Za nadaljevanje pritisnite ikono za odklepanje."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Preverjena pristnost"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Uporabi kodo PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Uporabi vzorec"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Uporabi geslo"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odklenjeno z obrazom"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Obraz je prepoznan"</string> <string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Poskusite z drugo kodo PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Potrdite spremembo za napravo <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Če si želite ogledati več, povlecite"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string> <string name="controls_media_title" msgid="1746947284862928133">"Predstavnost"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Želite skriti ta nadzor predstavnosti za <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 35e82a6c6a76..6633bb145d3b 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Fytyra u njoh. Shtyp për të vazhduar."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Fytyra u njoh. Shtyp ikonën e shkyçjes për të vazhduar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"U vërtetua"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Përdor kodin PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Përdor motivin"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Përdor fjalëkalimin"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"U shkyç me fytyrë"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Fytyra u njoh"</string> <string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Provo një kod tjetër PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Konfirmo ndryshimin për <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Rrëshqit shpejt për të shikuar më shumë"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Të fshihet kontrolluesi i medias për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index ecabc1b98a50..dcefae358ef1 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лице је препознато. Притисните да бисте наставили."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лице препознато. Притисните икону откључавања за наставак."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Идентитет је потврђен"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користите PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користите шаблон"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Користите лозинку"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Откључано је лицем"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лице је препознато"</string> <string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Откључајте да бисте користили NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Пробајте други PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Потврдите промену за: <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Превуците да бисте видели још"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медији"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Желите да сакријете ову контролу за медије за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 3d07826d804c..630de9cefdad 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet har identifierats. Tryck för att fortsätta."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentiserad"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Använd pinkod"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Använd mönster"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Använd lösenord"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Upplåst med ansiktslås"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansiktet har identifierats"</string> <string name="keyguard_retry" msgid="886802522584053523">"Svep uppåt om du vill försöka igen"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås upp om du vill använda NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Den här enheten tillhör organisationen"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Den här enheten tillhör <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Testa en annan pinkod"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Bekräfta ändring av <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Svep om du vill se mer"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Vill du dölja denna mediastyrning för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 055540a563a0..b6562235e83e 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Uso umetambuliwa. Bonyeza ili uendelee."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili uendelee."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Umethibitishwa"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Tumia PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Tumia mchoro"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Tumia nenosiri"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Imefunguliwa kwa kutumia uso"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Uso umetambuliwa"</string> <string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Fungua ili utumie NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Jaribu PIN nyingine"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Thibitisha mabadiliko kwenye <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Telezesha kidole ili uone zaidi"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string> <string name="controls_media_title" msgid="1746947284862928133">"Maudhui"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ungependa kuficha kidhibiti hiki kwenye <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 72b3598f4a98..6fabb7deb8f0 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அழுத்தவும்."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அன்லாக் ஐகானை அழுத்தவும்."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"அங்கீகரிக்கப்பட்டது"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"பின்னைப் பயன்படுத்து"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"பேட்டர்னைப் பயன்படுத்து"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"கடவுச்சொல்லைப் பயன்படுத்து"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"முகத்தால் அன்லாக் செய்யப்பட்டது"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"முகம் அங்கீகரிக்கப்பட்டது"</string> <string name="keyguard_retry" msgid="886802522584053523">"மீண்டும் முயல மேல்நோக்கி ஸ்வைப் செய்யவும்"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCயைப் பயன்படுத்த அன்லாக் செய்யவும்"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"இந்த சாதனம் <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> நிறுவனத்துக்கு சொந்தமானது"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"வேறு பின்னைப் பயன்படுத்தவும்"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ஐ மாற்றுவதை உறுதிப்படுத்தவும்"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"மேலும் பார்க்க ஸ்வைப் செய்யவும்"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string> <string name="controls_media_title" msgid="1746947284862928133">"மீடியா"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான இந்த மீடியா கட்டுப்பாடுகளை மறைக்கவா?"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 832499331650..f4fc0567d468 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ముఖం గుర్తించబడింది. కొనసాగించడానికి నొక్కండి."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ముఖం గుర్తించబడింది. కొనసాగడానికి అన్లాక్ చిహ్నం నొక్కండి."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ప్రామాణీకరించబడింది"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"పిన్ను ఉపయోగించండి"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ఆకృతిని ఉపయోగించండి"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"పాస్వర్డ్ను ఉపయోగించండి"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ముఖం ద్వారా అన్లాక్ చేయబడింది"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ముఖం గుర్తించబడింది"</string> <string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCని ఉపయోగించడానికి అన్లాక్ చేయండి"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ఈ పరికరం మీ సంస్థకు చెందినది"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>కు చెందినది"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"మరొక పిన్ని ప్రయత్నించండి"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>కి సంబంధించి మార్పును నిర్ధారించండి"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"మరిన్నింటిని చూడటం కోసం స్వైప్ చేయండి"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string> <string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం ఈ మీడియా కంట్రోల్ను దాచి ఉంచాలా?"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 698d52e4c349..047fc2666f97 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"จดจำใบหน้าได้ กดเพื่อดำเนินการต่อ"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ตรวจสอบสิทธิ์แล้ว"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ใช้ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ใช้รูปแบบ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"ใช้รหัสผ่าน"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ปลดล็อกด้วยใบหน้าแล้ว"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"จดจำใบหน้าได้"</string> <string name="keyguard_retry" msgid="886802522584053523">"เลื่อนขึ้นเพื่อลองอีกครั้ง"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ปลดล็อกเพื่อใช้ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> เป็นเจ้าของอุปกรณ์นี้"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ลองใช้ PIN อื่น"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"ยืนยันการเปลี่ยนแปลงสำหรับ<xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"เลื่อนเพื่อดูเพิ่มเติม"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string> <string name="controls_media_title" msgid="1746947284862928133">"สื่อ"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"ซ่อนตัวควบคุมสื่อนี้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 412bbb4dd234..4a9ad6f16f67 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nakilala ang mukha. Pindutin para magpatuloy."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nakilala ang mukha. Pindutin ang unlock para magpatuloy."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Na-authenticate"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gumamit ng PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gumamit ng pattern"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Gumamit ng password"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Na-unlock gamit ang mukha"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Nakilala ang mukha"</string> <string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"I-unlock para magamit ang NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Sumubok ng ibang PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Kumpirmahin ang pagbabago para sa <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Mag-swipe para tumingin ng higit pa"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"itago ang kontrol sa media na ito para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 9a00c073f428..6d28490591cb 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yüzünüz tanındı. Devam etmek için basın."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yüzünüz tanındı. Kilit açma simgesine basın."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kimliği Doğrulandı"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kullan"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Deseni kullan"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Şifre kullan"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Cihazın kilidini yüzünüzle açtınız"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Yüzünüz tanındı"</string> <string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC\'yi kullanmak için kilidi açın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> adlı kuruluşa ait"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Başka bir PIN deneyin"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> için değişikliği onaylayın"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Diğer öğeleri görmek için hızlıca kaydırın"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medya"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bu medya kontrolü gizlensin mi?"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 470d1b1fad4f..cb16c8b58fb1 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Обличчя розпізнано. Натисніть, щоб продовжити."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Обличчя розпізнано. Натисніть значок розблокування."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Автентифіковано"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Ввести PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Намалювати ключ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Ввести пароль"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Розблоковано (фейс-контроль)"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Обличчя розпізнано"</string> <string name="keyguard_retry" msgid="886802522584053523">"Проведіть пальцем угору, щоб повторити спробу"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Розблокуйте екран, щоб скористатись NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Цей пристрій належить вашій організації"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Цей пристрій належить організації \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Спробуйте інший PIN-код"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>: підтвердьте зміну"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Гортайте, щоб переглянути інші"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Завантаження рекомендацій"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медіа"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Приховати цей елемент керування для <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 253e50471fc0..de63e2d3338f 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کے لیے دبائیں۔"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"تصدیق کردہ"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN استعمال کریں"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"پیٹرن کا استعمال کریں"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"پاس ورڈ استعمال کریں"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"چہرے سے غیر مقفل کیا گیا"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"چہرے کی شناخت ہو گئی"</string> <string name="keyguard_retry" msgid="886802522584053523">"دوبارہ کوشش کرنے کے لیے اوپر سوائپ کريں"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC استعمال کرنے کیلئے غیر مقفل کریں"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"یہ آلہ آپ کی تنظیم کا ہے"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"یہ آلہ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> کا ہے"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"کوئی دوسرا PIN آزمائیں"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> کی تبدیلی کی توثیق کریں"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"مزید دیکھنے کیلئے سوائپ کریں"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string> <string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اس میڈیا کنٹرول کو چھپائیں؟"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index d44054130a79..fc3f57974142 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yuz aniqlandi. Davom etish uchun bosing."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yuz aniqlandi. Davom etish uchun ochish belgisini bosing."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Tasdiqlandi"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kod kiritish"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Grafik kalitdan foydalanish"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Paroldan foydalanish"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Yuz bilan ochildi"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Yuz aniqlandi"</string> <string name="keyguard_retry" msgid="886802522584053523">"Qayta urinish uchun tepaga suring"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ishlatish uchun qurilma qulfini oching"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu qurilma tashkilotingizga tegishli"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu qurilma <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tashkilotiga tegishli"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Boshqa PIN kod ishlating"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> uchun oʻzgarishlarni tasdiqlang"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Batafsil axborot olish uchun suring"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun media boshqaruvi berkitilsinmi?"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 9938783408fb..34f5e67cf107 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Đã nhận diện khuôn mặt. Hãy nhấn để tiếp tục."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Đã nhận diện khuôn mặt. Nhấn biểu tượng mở khoá để tiếp tục."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Đã xác thực"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Dùng mã PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Dùng hình mở khóa"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Dùng mật khẩu"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Đã mở khoá bằng khuôn mặt."</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Đã nhận diện khuôn mặt."</string> <string name="keyguard_retry" msgid="886802522584053523">"Vuốt lên để thử lại"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Mở khóa để sử dụng NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Thiết bị này thuộc về tổ chức của bạn"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Thiết bị này thuộc về <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Thử một mã PIN khác"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Xác nhận thay đổi <xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Vuốt để xem thêm"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string> <string name="controls_media_title" msgid="1746947284862928133">"Nội dung nghe nhìn"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Ẩn tính năng điều khiển này cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index f6c189c8ccef..c32220e7529d 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"识别出面孔。点按即可继续。"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"识别出面孔。按下解锁图标即可继续。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已经过身份验证"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 码"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用图案"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"使用密码"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"已用面孔解锁"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"已识别出面孔"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"此设备归<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>所有"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"试试其他 PIN 码"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"确认<xliff:g id="DEVICE">%s</xliff:g>的更改"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"滑动可查看更多结构"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string> <string name="controls_media_title" msgid="1746947284862928133">"媒体"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"要针对“<xliff:g id="APP_NAME">%1$s</xliff:g>”隐藏此媒体控件吗?"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 8fb4e81bd81a..37a88856a248 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"已識別面孔。按下即可繼續操作。"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"已識別面孔。按解鎖圖示即可繼續。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"驗證咗"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用圖案"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"使用密碼"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"已使用面孔解鎖"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"已識別面孔"</string> <string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖方可使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於你的機構"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"此裝置屬於「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"嘗試其他 PIN"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"確認<xliff:g id="DEVICE">%s</xliff:g>變更"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"滑動以查看更多"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string> <string name="controls_media_title" msgid="1746947284862928133">"媒體"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"要隱藏此「<xliff:g id="APP_NAME">%1$s</xliff:g>」媒體控制嗎?"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index c09bb42fb776..8d9b03ec3055 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"臉孔辨識完成,按下即可繼續操作。"</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"臉孔辨識完成,按下「解鎖」圖示即可繼續操作。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已通過驗證"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 碼"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用解鎖圖案"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"使用密碼"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"裝置已透過你的臉解鎖"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"臉孔辨識完成"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於貴機構"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"試試其他 PIN 碼"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"確認「<xliff:g id="DEVICE">%s</xliff:g>」的變更"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"滑動即可查看其他結構"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string> <string name="controls_media_title" msgid="1746947284862928133">"媒體"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"要隱藏「<xliff:g id="APP_NAME">%1$s</xliff:g>」的媒體控制選項嗎?"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 35c8a2b5b855..f313b3b74d54 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -147,6 +147,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ubuso buyaziwa. Cindezela ukuze uqhubeke."</string> <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ubuso buyaziwa. Cindezela isithonjana sokuvula ukuze uqhubeke."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kugunyaziwe"</string> + <!-- no translation found for biometric_dialog_cancel_authentication (981316588773442637) --> + <skip /> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Sebenzisa iphinikhodi"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Sebenzisa iphethini"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Sebenzisa iphasiwedi"</string> @@ -359,6 +361,8 @@ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Vula ngobuso"</string> <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ubuso buyaziwa"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string> + <!-- no translation found for accesssibility_keyguard_retry (8880238862712870676) --> + <skip /> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Vula ukuze usebenzise i-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -928,6 +932,8 @@ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Zama enye Iphinikhodi"</string> <string name="controls_confirmation_message" msgid="7744104992609594859">"Qinisekisa ushintsho lwe-<xliff:g id="DEVICE">%s</xliff:g>"</string> <string name="controls_structure_tooltip" msgid="4355922222944447867">"Swayipha ukuze ubone okuningi"</string> + <!-- no translation found for retry_face (416380073082560186) --> + <skip /> <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string> <string name="controls_media_title" msgid="1746947284862928133">"Imidiya"</string> <string name="controls_media_close_session" msgid="4780485355795635052">"Fihlela i-<xliff:g id="APP_NAME">%1$s</xliff:g> lesi silawuli semidiya?"</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 070748cb92f8..ccc6f8252e9b 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -362,6 +362,8 @@ <string name="biometric_dialog_tap_confirm_with_face_alt_3">Face recognized. Press the unlock icon to continue.</string> <!-- Talkback string when a biometric is authenticated [CHAR LIMIT=NONE] --> <string name="biometric_dialog_authenticated">Authenticated</string> + <!-- Talkback string when a canceling authentication [CHAR LIMIT=NONE] --> + <string name="biometric_dialog_cancel_authentication">Cancel Authentication</string> <!-- Button text shown on BiometricPrompt giving the user the option to use an alternate form of authentication (Pin) [CHAR LIMIT=30] --> <string name="biometric_dialog_use_pin">Use PIN</string> @@ -430,6 +432,8 @@ <string name="face_reenroll_failure_dialog_content">Couldn\u2019t set up face unlock. Go to Settings to try again.</string> <!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication --> <string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string> + <!-- Content description after successful auth when confirmation required --> + <string name="fingerprint_dialog_authenticated_confirmation">Press the unlock icon to continue</string> <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] --> <string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string> <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] --> @@ -946,6 +950,8 @@ <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] --> <string name="keyguard_retry">Swipe up to try again</string> + <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] --> + <string name="accesssibility_keyguard_retry">Swipe up to try Face Unlock again</string> <!-- Message shown when notifying user to unlock in order to use NFC. [CHAR LIMIT=60] --> <string name="require_unlock_for_nfc">Unlock to use NFC</string> @@ -2563,6 +2569,9 @@ <!-- Tooltip to show in management screen when there are multiple structures [CHAR_LIMIT=50] --> <string name="controls_structure_tooltip">Swipe to see more</string> + <!-- Accessibility action informing the user how they can retry face authentication [CHAR LIMIT=NONE] --> + <string name="retry_face">Retry face authentication</string> + <!-- Message to tell the user to wait while systemui attempts to load a set of recommended controls [CHAR_LIMIT=60] --> <string name="controls_seeding_in_progress">Loading recommendations</string> diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt index d8085b9f9f2e..22cdb30376d0 100644 --- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt +++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt @@ -20,6 +20,7 @@ import android.annotation.StringDef import android.os.PowerManager import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger +import com.android.keyguard.FaceAuthApiRequestReason.Companion.ACCESSIBILITY_ACTION import com.android.keyguard.FaceAuthApiRequestReason.Companion.NOTIFICATION_PANEL_CLICKED import com.android.keyguard.FaceAuthApiRequestReason.Companion.PICK_UP_GESTURE_TRIGGERED import com.android.keyguard.FaceAuthApiRequestReason.Companion.QS_EXPANDED @@ -71,6 +72,7 @@ import com.android.keyguard.InternalFaceAuthReasons.USER_SWITCHING NOTIFICATION_PANEL_CLICKED, QS_EXPANDED, PICK_UP_GESTURE_TRIGGERED, + ACCESSIBILITY_ACTION, ) annotation class FaceAuthApiRequestReason { companion object { @@ -80,6 +82,7 @@ annotation class FaceAuthApiRequestReason { const val QS_EXPANDED = "Face auth due to QS expansion." const val PICK_UP_GESTURE_TRIGGERED = "Face auth due to pickup gesture triggered when the device is awake and not from AOD." + const val ACCESSIBILITY_ACTION = "Face auth due to an accessibility action." } } @@ -217,7 +220,8 @@ constructor(private val id: Int, val reason: String, var extraInfo: Int = 0) : @UiEvent(doc = STRONG_AUTH_ALLOWED_CHANGED) FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED(1255, STRONG_AUTH_ALLOWED_CHANGED), @UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED) - FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED); + FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED), + @UiEvent(doc = ACCESSIBILITY_ACTION) FACE_AUTH_ACCESSIBILITY_ACTION(1454, ACCESSIBILITY_ACTION); override fun getId(): Int = this.id @@ -233,6 +237,8 @@ private val apiRequestReasonToUiEvent = FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED, QS_EXPANDED to FaceAuthUiEvent.FACE_AUTH_TRIGGERED_QS_EXPANDED, PICK_UP_GESTURE_TRIGGERED to FaceAuthUiEvent.FACE_AUTH_TRIGGERED_PICK_UP_GESTURE_TRIGGERED, + PICK_UP_GESTURE_TRIGGERED to FaceAuthUiEvent.FACE_AUTH_TRIGGERED_PICK_UP_GESTURE_TRIGGERED, + ACCESSIBILITY_ACTION to FaceAuthUiEvent.FACE_AUTH_ACCESSIBILITY_ACTION, ) /** Converts the [reason] to the corresponding [FaceAuthUiEvent]. */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 74b29a77aad4..78142cea2201 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -68,6 +68,7 @@ import com.android.keyguard.dagger.KeyguardBouncerScope; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Gefingerpoken; import com.android.systemui.R; +import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate; import com.android.systemui.biometrics.SideFpsController; import com.android.systemui.biometrics.SideFpsUiRequestSource; import com.android.systemui.classifier.FalsingA11yDelegate; @@ -385,9 +386,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard TelephonyManager telephonyManager, ViewMediatorCallback viewMediatorCallback, AudioManager audioManager, - KeyguardFaceAuthInteractor keyguardFaceAuthInteractor + KeyguardFaceAuthInteractor keyguardFaceAuthInteractor, + FaceAuthAccessibilityDelegate faceAuthAccessibilityDelegate ) { super(view); + view.setAccessibilityDelegate(faceAuthAccessibilityDelegate); mLockPatternUtils = lockPatternUtils; mUpdateMonitor = keyguardUpdateMonitor; mSecurityModel = keyguardSecurityModel; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index de24024aaa2f..1def25fbd0f8 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -3136,6 +3136,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return false; } + if (isFaceAuthInteractorEnabled()) { + return mFaceAuthInteractor.canFaceAuthRun(); + } + final boolean statusBarShadeLocked = mStatusBarState == StatusBarState.SHADE_LOCKED; final boolean awakeKeyguard = isKeyguardVisible() && mDeviceInteractive && !statusBarShadeLocked; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt index 9807b9e6f1b3..a1b15f4498a7 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt @@ -142,13 +142,18 @@ open class AuthBiometricFingerprintIconController( STATE_IDLE, STATE_AUTHENTICATING_ANIMATING_IN, STATE_AUTHENTICATING, - STATE_PENDING_CONFIRMATION, STATE_AUTHENTICATED -> if (isSideFps) { R.string.security_settings_sfps_enroll_find_sensor_message } else { R.string.fingerprint_dialog_touch_sensor } + STATE_PENDING_CONFIRMATION -> + if (isSideFps) { + R.string.security_settings_sfps_enroll_find_sensor_message + } else { + R.string.fingerprint_dialog_authenticated_confirmation + } STATE_ERROR, STATE_HELP -> R.string.biometric_dialog_try_again else -> null diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index cd8f04d18500..ed4b91c7c4e4 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -737,7 +737,7 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom }); mUseCredentialButton.setOnClickListener((view) -> { - startTransitionToCredentialUI(); + startTransitionToCredentialUI(false /* isError */); }); mConfirmButton.setOnClickListener((view) -> { @@ -768,9 +768,12 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom /** * Kicks off the animation process and invokes the callback. + * + * @param isError if this was triggered due to an error and not a user action (unused, + * previously for haptics). */ @Override - public void startTransitionToCredentialUI() { + public void startTransitionToCredentialUI(boolean isError) { updateSize(AuthDialog.SIZE_LARGE); mCallback.onAction(Callback.ACTION_USE_DEVICE_CREDENTIAL); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricViewAdapter.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricViewAdapter.kt index 631511c231e4..68db564606fd 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricViewAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricViewAdapter.kt @@ -38,7 +38,7 @@ interface AuthBiometricViewAdapter { fun onHelp(@BiometricAuthenticator.Modality modality: Int, help: String) - fun startTransitionToCredentialUI() + fun startTransitionToCredentialUI(isError: Boolean) fun requestLayout() diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 7f706859abb3..76181094c4b3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -58,6 +58,10 @@ import android.widget.ScrollView; import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; + import com.android.app.animation.Interpolators; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.InteractionJankMonitor; @@ -333,6 +337,20 @@ public class AuthContainerView extends LinearLayout addView(mFrameLayout); mBiometricScrollView = mFrameLayout.findViewById(R.id.biometric_scrollview); mBackgroundView = mFrameLayout.findViewById(R.id.background); + ViewCompat.setAccessibilityDelegate(mBackgroundView, new AccessibilityDelegateCompat() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, + AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.addAction( + new AccessibilityNodeInfoCompat.AccessibilityActionCompat( + AccessibilityNodeInfoCompat.ACTION_CLICK, + mContext.getString(R.string.biometric_dialog_cancel_authentication) + ) + ); + } + }); + mPanelView = mFrameLayout.findViewById(R.id.panel); mPanelController = new AuthPanelController(mContext, mPanelView); mBackgroundExecutor = bgExecutor; @@ -374,7 +392,6 @@ public class AuthContainerView extends LinearLayout if (Utils.isBiometricAllowed(config.mPromptInfo)) { mPromptSelectorInteractorProvider.get().useBiometricsForAuthentication( config.mPromptInfo, - config.mRequireConfirmation, config.mUserId, config.mOperationId, new BiometricModalities(fpProps, faceProps)); @@ -802,9 +819,9 @@ public class AuthContainerView extends LinearLayout } @Override - public void animateToCredentialUI() { + public void animateToCredentialUI(boolean isError) { if (mBiometricView != null) { - mBiometricView.startTransitionToCredentialUI(); + mBiometricView.startTransitionToCredentialUI(isError); } else { Log.e(TAG, "animateToCredentialUI(): mBiometricView is null"); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 57f1928fe545..96b144731a1b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -85,7 +85,6 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.data.repository.BiometricType; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.Execution; @@ -185,18 +184,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, private final @Background DelayableExecutor mBackgroundExecutor; private final DisplayInfo mCachedDisplayInfo = new DisplayInfo(); - private final VibratorHelper mVibratorHelper; - - private void vibrateSuccess(int modality) { - mVibratorHelper.vibrateAuthSuccess( - getClass().getSimpleName() + ", modality = " + modality + "BP::success"); - } - - private void vibrateError(int modality) { - mVibratorHelper.vibrateAuthError( - getClass().getSimpleName() + ", modality = " + modality + "BP::error"); - } - @VisibleForTesting final TaskStackListener mTaskStackListener = new TaskStackListener() { @Override @@ -776,7 +763,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, @NonNull InteractionJankMonitor jankMonitor, @Main Handler handler, @Background DelayableExecutor bgExecutor, - @NonNull VibratorHelper vibrator, @NonNull UdfpsUtils udfpsUtils) { mContext = context; mFeatureFlags = featureFlags; @@ -798,7 +784,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, mUdfpsEnrolledForUser = new SparseBooleanArray(); mSfpsEnrolledForUser = new SparseBooleanArray(); mFaceEnrolledForUser = new SparseBooleanArray(); - mVibratorHelper = vibrator; mUdfpsUtils = udfpsUtils; mApplicationCoroutineScope = applicationCoroutineScope; @@ -987,8 +972,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, public void onBiometricAuthenticated(@Modality int modality) { if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: "); - vibrateSuccess(modality); - if (mCurrentDialog != null) { mCurrentDialog.onAuthenticationSucceeded(modality); } else { @@ -1048,6 +1031,18 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, return false; } + private String getNotRecognizedString(@Modality int modality) { + final int messageRes; + final int userId = mCurrentDialogArgs.argi1; + if (isFaceAuthEnrolled(userId) && isFingerprintEnrolled(userId)) { + messageRes = modality == TYPE_FACE + ? R.string.biometric_face_not_recognized + : R.string.fingerprint_error_not_match; + } else { + messageRes = R.string.biometric_not_recognized; + } + return mContext.getString(messageRes); + } private String getErrorString(@Modality int modality, int error, int vendorCode) { switch (modality) { @@ -1073,8 +1068,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, Log.d(TAG, String.format("onBiometricError(%d, %d, %d)", modality, error, vendorCode)); } - vibrateError(modality); - final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT) || (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT); @@ -1091,10 +1084,11 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, if (mCurrentDialog != null) { if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) { if (DEBUG) Log.d(TAG, "onBiometricError, lockout"); - mCurrentDialog.animateToCredentialUI(); + mCurrentDialog.animateToCredentialUI(true /* isError */); } else if (isSoftError) { - final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED) - ? mContext.getString(R.string.biometric_not_recognized) + final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED + || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) + ? getNotRecognizedString(modality) : getErrorString(modality, error, vendorCode); if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage); // The camera privacy error can return before the prompt initializes its state, @@ -1204,8 +1198,11 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, final PromptInfo promptInfo = (PromptInfo) args.arg1; final int[] sensorIds = (int[]) args.arg3; + + // TODO(b/251476085): remove these unused parameters (replaced with SSOT elsewhere) final boolean credentialAllowed = (boolean) args.arg4; final boolean requireConfirmation = (boolean) args.arg5; + final int userId = args.argi1; final String opPackageName = (String) args.arg6; final long operationId = args.argl1; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java index b6eabfa76e36..3cfc6f280110 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java @@ -162,7 +162,7 @@ public interface AuthDialog extends Dumpable { /** * Animate to credential UI. Typically called after biometric is locked out. */ - void animateToCredentialUI(); + void animateToCredentialUI(boolean isError); /** * @return true if device credential is allowed. diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java index 6db266f4f1cb..9d8dcc1efdd8 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java @@ -21,6 +21,8 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE; import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG; import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -30,6 +32,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricSourceType; +import android.hardware.biometrics.BiometricStateListener; +import android.hardware.face.FaceManager; +import android.hardware.fingerprint.FingerprintManager; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; @@ -42,7 +47,6 @@ import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.KeyguardStateController; - import java.util.Optional; import javax.inject.Inject; @@ -69,6 +73,8 @@ public class BiometricNotificationService implements CoreStartable { private final NotificationManager mNotificationManager; private final BiometricNotificationBroadcastReceiver mBroadcastReceiver; private final FingerprintReEnrollNotification mFingerprintReEnrollNotification; + private final FingerprintManager mFingerprintManager; + private final FaceManager mFaceManager; private NotificationChannel mNotificationChannel; private boolean mFaceNotificationQueued; private boolean mFingerprintNotificationQueued; @@ -119,14 +125,29 @@ public class BiometricNotificationService implements CoreStartable { } }; + private final BiometricStateListener mFaceStateListener = new BiometricStateListener() { + @Override + public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { + mNotificationManager.cancelAsUser(TAG, FACE_NOTIFICATION_ID, UserHandle.CURRENT); + } + }; + + private final BiometricStateListener mFingerprintStateListener = new BiometricStateListener() { + @Override + public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { + mNotificationManager.cancelAsUser(TAG, FINGERPRINT_NOTIFICATION_ID, UserHandle.CURRENT); + } + }; @Inject - public BiometricNotificationService(Context context, - KeyguardUpdateMonitor keyguardUpdateMonitor, - KeyguardStateController keyguardStateController, - Handler handler, NotificationManager notificationManager, - BiometricNotificationBroadcastReceiver biometricNotificationBroadcastReceiver, - Optional<FingerprintReEnrollNotification> fingerprintReEnrollNotification) { + public BiometricNotificationService(@NonNull Context context, + @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, + @NonNull KeyguardStateController keyguardStateController, + @NonNull Handler handler, @NonNull NotificationManager notificationManager, + @NonNull BiometricNotificationBroadcastReceiver biometricNotificationBroadcastReceiver, + @NonNull Optional<FingerprintReEnrollNotification> fingerprintReEnrollNotification, + @Nullable FingerprintManager fingerprintManager, + @Nullable FaceManager faceManager) { mContext = context; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardStateController = keyguardStateController; @@ -135,6 +156,8 @@ public class BiometricNotificationService implements CoreStartable { mBroadcastReceiver = biometricNotificationBroadcastReceiver; mFingerprintReEnrollNotification = fingerprintReEnrollNotification.orElse( new FingerprintReEnrollNotificationImpl()); + mFingerprintManager = fingerprintManager; + mFaceManager = faceManager; } @Override @@ -148,9 +171,16 @@ public class BiometricNotificationService implements CoreStartable { intentFilter.addAction(ACTION_SHOW_FACE_REENROLL_DIALOG); mContext.registerReceiver(mBroadcastReceiver, intentFilter, Context.RECEIVER_EXPORTED_UNAUDITED); + if (mFingerprintManager != null) { + mFingerprintManager.registerBiometricStateListener(mFingerprintStateListener); + } + if (mFaceManager != null) { + mFaceManager.registerBiometricStateListener(mFaceStateListener); + } } private void queueFaceReenrollNotification() { + Log.d(TAG, "Face re-enroll notification queued."); mFaceNotificationQueued = true; final String title = mContext.getString(R.string.face_re_enroll_notification_title); final String content = mContext.getString( @@ -163,6 +193,7 @@ public class BiometricNotificationService implements CoreStartable { } private void queueFingerprintReenrollNotification() { + Log.d(TAG, "Fingerprint re-enroll notification queued."); mFingerprintNotificationQueued = true; final String title = mContext.getString(R.string.fingerprint_re_enroll_notification_title); final String content = mContext.getString( diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt new file mode 100644 index 000000000000..b9fa24022ad5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt @@ -0,0 +1,62 @@ +/* + * 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.biometrics + +import android.content.res.Resources +import android.os.Bundle +import android.view.View +import android.view.accessibility.AccessibilityNodeInfo +import com.android.keyguard.FaceAuthApiRequestReason +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor +import javax.inject.Inject + +/** + * Accessibility delegate that will add a click accessibility action to a view when face auth can + * run. When the click a11y action is triggered, face auth will retry. + */ +@SysUISingleton +class FaceAuthAccessibilityDelegate +@Inject +constructor( + @Main private val resources: Resources, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val faceAuthInteractor: KeyguardFaceAuthInteractor, +) : View.AccessibilityDelegate() { + override fun onInitializeAccessibilityNodeInfo(host: View?, info: AccessibilityNodeInfo) { + super.onInitializeAccessibilityNodeInfo(host, info) + if (keyguardUpdateMonitor.shouldListenForFace()) { + val clickActionToRetryFace = + AccessibilityNodeInfo.AccessibilityAction( + AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id, + resources.getString(R.string.retry_face) + ) + info.addAction(clickActionToRetryFace) + } + } + + override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean { + return if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id) { + keyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.ACCESSIBILITY_ACTION) + faceAuthInteractor.onAccessibilityAction() + true + } else super.performAccessibilityAction(host, action, args) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 10e45dadee60..16d12bbfe3b4 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -188,6 +188,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { @Nullable private VelocityTracker mVelocityTracker; // The ID of the pointer for which ACTION_DOWN has occurred. -1 means no pointer is active. private int mActivePointerId = -1; + // Whether a pointer has been pilfered for current gesture + private boolean mPointerPilfered = false; // The timestamp of the most recent touch log. private long mTouchLogTime; // The timestamp of the most recent log of a touch InteractionEvent. @@ -354,7 +356,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { UdfpsController.this.mAlternateTouchProvider.onUiReady(); } else { final long requestId = (mOverlay != null) ? mOverlay.getRequestId() : 0L; - UdfpsController.this.mFingerprintManager.onUiReady(requestId, sensorId); + UdfpsController.this.mFingerprintManager.onUdfpsUiEvent( + FingerprintManager.UDFPS_UI_READY, requestId, sensorId); } } } @@ -557,6 +560,11 @@ public class UdfpsController implements DozeReceiver, Dumpable { || mPrimaryBouncerInteractor.isInTransit()) { return false; } + if (event.getAction() == MotionEvent.ACTION_DOWN + || event.getAction() == MotionEvent.ACTION_HOVER_ENTER) { + // Reset on ACTION_DOWN, start of new gesture + mPointerPilfered = false; + } final TouchProcessorResult result = mTouchProcessor.processTouch(event, mActivePointerId, mOverlayParams); @@ -636,10 +644,11 @@ public class UdfpsController implements DozeReceiver, Dumpable { shouldPilfer = true; } - // Execute the pilfer - if (shouldPilfer) { + // Pilfer only once per gesture + if (shouldPilfer && !mPointerPilfered) { mInputManager.pilferPointers( mOverlay.getOverlayView().getViewRootImpl().getInputToken()); + mPointerPilfered = true; } return processedTouch.getTouchData().isWithinBounds(mOverlayParams.getNativeSensorBounds()); @@ -958,6 +967,10 @@ public class UdfpsController implements DozeReceiver, Dumpable { mOnFingerDown = false; mAttemptedToDismissKeyguard = false; mOrientationListener.enable(); + if (mFingerprintManager != null) { + mFingerprintManager.onUdfpsUiEvent(FingerprintManager.UDFPS_UI_OVERLAY_SHOWN, + overlay.getRequestId(), mSensorProps.sensorId); + } } else { Log.v(TAG, "showUdfpsOverlay | the overlay is already showing"); } @@ -1099,7 +1112,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); }); } else { - mFingerprintManager.onUiReady(requestId, mSensorProps.sensorId); + mFingerprintManager.onUdfpsUiEvent(FingerprintManager.UDFPS_UI_READY, requestId, + mSensorProps.sensorId); mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt index ddf1457e385c..a5e846ad61ca 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt @@ -17,6 +17,8 @@ package com.android.systemui.biometrics.dagger import com.android.settingslib.udfps.UdfpsUtils +import com.android.systemui.biometrics.data.repository.FaceSettingsRepository +import com.android.systemui.biometrics.data.repository.FaceSettingsRepositoryImpl import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepositoryImpl import com.android.systemui.biometrics.data.repository.PromptRepository @@ -47,6 +49,10 @@ interface BiometricsModule { @Binds @SysUISingleton + fun faceSettings(impl: FaceSettingsRepositoryImpl): FaceSettingsRepository + + @Binds + @SysUISingleton fun biometricPromptRepository(impl: PromptRepositoryImpl): PromptRepository @Binds diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FaceSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FaceSettingsRepository.kt new file mode 100644 index 000000000000..3d5ed823f771 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FaceSettingsRepository.kt @@ -0,0 +1,57 @@ +/* + * 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.biometrics.data.repository + +import android.os.Handler +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.util.settings.SecureSettings +import java.util.concurrent.ConcurrentHashMap +import javax.inject.Inject + +/** + * Repository for the global state of users Face Unlock preferences. + * + * Largely a wrapper around [SecureSettings]'s proxy to Settings.Secure. + */ +interface FaceSettingsRepository { + + /** Get Settings for the given user [id]. */ + fun forUser(id: Int?): FaceUserSettingsRepository +} + +@SysUISingleton +class FaceSettingsRepositoryImpl +@Inject +constructor( + @Main private val mainHandler: Handler, + private val secureSettings: SecureSettings, +) : FaceSettingsRepository { + + private val userSettings = ConcurrentHashMap<Int, FaceUserSettingsRepository>() + + override fun forUser(id: Int?): FaceUserSettingsRepository = + if (id != null) { + userSettings.computeIfAbsent(id) { _ -> + FaceUserSettingsRepositoryImpl(id, mainHandler, secureSettings).also { repo -> + repo.start() + } + } + } else { + FaceUserSettingsRepositoryImpl.Empty + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FaceUserSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FaceUserSettingsRepository.kt new file mode 100644 index 000000000000..68c4a10fcfad --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FaceUserSettingsRepository.kt @@ -0,0 +1,88 @@ +/* + * 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.biometrics.data.repository + +import android.database.ContentObserver +import android.os.Handler +import android.provider.Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.util.settings.SecureSettings +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.flowOf + +/** Settings for a user. */ +interface FaceUserSettingsRepository { + /** The user's id. */ + val userId: Int + + /** If BiometricPrompt should always require confirmation (overrides app's preference). */ + val alwaysRequireConfirmationInApps: Flow<Boolean> +} + +class FaceUserSettingsRepositoryImpl( + override val userId: Int, + @Main private val mainHandler: Handler, + private val secureSettings: SecureSettings, +) : FaceUserSettingsRepository { + + /** Indefinitely subscribe to user preference changes. */ + fun start() { + watch( + FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, + _alwaysRequireConfirmationInApps, + ) + } + + private var _alwaysRequireConfirmationInApps = MutableStateFlow(false) + override val alwaysRequireConfirmationInApps: Flow<Boolean> = + _alwaysRequireConfirmationInApps.asStateFlow() + + /** Defaults to use when no user is specified. */ + object Empty : FaceUserSettingsRepository { + override val userId = -1 + override val alwaysRequireConfirmationInApps = flowOf(false) + } + + private fun watch( + key: String, + toUpdate: MutableStateFlow<Boolean>, + defaultValue: Boolean = false, + ) = secureSettings.watch(userId, mainHandler, key, defaultValue) { v -> toUpdate.value = v } +} + +private fun SecureSettings.watch( + userId: Int, + handler: Handler, + key: String, + defaultValue: Boolean = false, + onChange: (Boolean) -> Unit, +) { + fun fetch(): Boolean = getIntForUser(key, if (defaultValue) 1 else 0, userId) > 0 + + registerContentObserverForUser( + key, + false /* notifyForDescendants */, + object : ContentObserver(handler) { + override fun onChange(selfChange: Boolean) = onChange(fetch()) + }, + userId + ) + + onChange(fetch()) +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/PromptRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/PromptRepository.kt index b4dc272b71da..b35fbbc7bb32 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/PromptRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/PromptRepository.kt @@ -1,3 +1,19 @@ +/* + * 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.biometrics.data.repository import android.hardware.biometrics.PromptInfo @@ -12,6 +28,10 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map /** * A repository for the global state of BiometricPrompt. @@ -40,7 +60,7 @@ interface PromptRepository { * * Note: overlaps/conflicts with [PromptInfo.isConfirmationRequested], which needs clean up. */ - val isConfirmationRequired: StateFlow<Boolean> + val isConfirmationRequired: Flow<Boolean> /** Update the prompt configuration, which should be set before [isShowing]. */ fun setPrompt( @@ -48,7 +68,6 @@ interface PromptRepository { userId: Int, gatekeeperChallenge: Long?, kind: PromptKind, - requireConfirmation: Boolean = false, ) /** Unset the prompt info. */ @@ -56,8 +75,12 @@ interface PromptRepository { } @SysUISingleton -class PromptRepositoryImpl @Inject constructor(private val authController: AuthController) : - PromptRepository { +class PromptRepositoryImpl +@Inject +constructor( + private val faceSettings: FaceSettingsRepository, + private val authController: AuthController, +) : PromptRepository { override val isShowing: Flow<Boolean> = conflatedCallbackFlow { val callback = @@ -85,21 +108,30 @@ class PromptRepositoryImpl @Inject constructor(private val authController: AuthC private val _kind: MutableStateFlow<PromptKind> = MutableStateFlow(PromptKind.Biometric()) override val kind = _kind.asStateFlow() - private val _isConfirmationRequired: MutableStateFlow<Boolean> = MutableStateFlow(false) - override val isConfirmationRequired = _isConfirmationRequired.asStateFlow() + private val _faceSettings = + _userId.map { id -> faceSettings.forUser(id) }.distinctUntilChanged() + private val _faceSettingAlwaysRequireConfirmation = + _faceSettings.flatMapLatest { it.alwaysRequireConfirmationInApps }.distinctUntilChanged() + + private val _isConfirmationRequired = _promptInfo.map { it?.isConfirmationRequested ?: false } + override val isConfirmationRequired = + combine(_isConfirmationRequired, _faceSettingAlwaysRequireConfirmation) { + appRequiresConfirmation, + forceRequireConfirmation -> + forceRequireConfirmation || appRequiresConfirmation + } + .distinctUntilChanged() override fun setPrompt( promptInfo: PromptInfo, userId: Int, gatekeeperChallenge: Long?, kind: PromptKind, - requireConfirmation: Boolean, ) { _kind.value = kind _userId.value = userId _challenge.value = gatekeeperChallenge _promptInfo.value = promptInfo - _isConfirmationRequired.value = requireConfirmation } override fun unsetPrompt() { @@ -107,7 +139,6 @@ class PromptRepositoryImpl @Inject constructor(private val authController: AuthC _userId.value = null _challenge.value = null _kind.value = PromptKind.Biometric() - _isConfirmationRequired.value = false } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt index e6e07f9d7794..be99dd92f1bd 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt @@ -59,13 +59,15 @@ interface PromptSelectorInteractor { */ val credentialKind: Flow<PromptKind> - /** If the API caller requested explicit confirmation after successful authentication. */ - val isConfirmationRequested: Flow<Boolean> + /** + * If the API caller or the user's personal preferences require explicit confirmation after + * successful authentication. + */ + val isConfirmationRequired: Flow<Boolean> /** Use biometrics for authentication. */ fun useBiometricsForAuthentication( promptInfo: PromptInfo, - requireConfirmation: Boolean, userId: Int, challenge: Long, modalities: BiometricModalities, @@ -114,10 +116,8 @@ constructor( } } - override val isConfirmationRequested: Flow<Boolean> = - promptRepository.promptInfo - .map { info -> info?.isConfirmationRequested ?: false } - .distinctUntilChanged() + override val isConfirmationRequired: Flow<Boolean> = + promptRepository.isConfirmationRequired.distinctUntilChanged() override val isCredentialAllowed: Flow<Boolean> = promptRepository.promptInfo @@ -142,7 +142,6 @@ constructor( override fun useBiometricsForAuthentication( promptInfo: PromptInfo, - requireConfirmation: Boolean, userId: Int, challenge: Long, modalities: BiometricModalities @@ -152,7 +151,6 @@ constructor( userId = userId, gatekeeperChallenge = challenge, kind = PromptKind.Biometric(modalities), - requireConfirmation = requireConfirmation, ) } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricModality.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/BiometricModality.kt index 3197c0935d0b..fb580ca54aff 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricModality.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/BiometricModality.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.biometrics.domain.model +package com.android.systemui.biometrics.shared.model import android.hardware.biometrics.BiometricAuthenticator 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 8486c3f96b21..4e26601afe2a 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 @@ -46,9 +46,9 @@ import com.android.systemui.biometrics.AuthIconController import com.android.systemui.biometrics.AuthPanelController import com.android.systemui.biometrics.Utils import com.android.systemui.biometrics.domain.model.BiometricModalities -import com.android.systemui.biometrics.domain.model.BiometricModality -import com.android.systemui.biometrics.domain.model.asBiometricModality +import com.android.systemui.biometrics.shared.model.BiometricModality import com.android.systemui.biometrics.shared.model.PromptKind +import com.android.systemui.biometrics.shared.model.asBiometricModality import com.android.systemui.biometrics.ui.BiometricPromptLayout import com.android.systemui.biometrics.ui.viewmodel.FingerprintStartMode import com.android.systemui.biometrics.ui.viewmodel.PromptMessage @@ -158,7 +158,7 @@ object BiometricViewBinder { view.updateFingerprintAffordanceSize(iconController) } if (iconController is HackyCoexIconController) { - iconController.faceMode = !viewModel.isConfirmationRequested.first() + iconController.faceMode = !viewModel.isConfirmationRequired.first() } // the icon controller must be created before this happens for the legacy @@ -305,6 +305,10 @@ object BiometricViewBinder { .collect { onClick -> iconViewOverlay.setOnClickListener(onClick) iconView.setOnClickListener(onClick) + if (onClick == null) { + iconViewOverlay.isClickable = false + iconView.isClickable = false + } } } @@ -339,7 +343,13 @@ object BiometricViewBinder { launch { delay(authState.delay) - legacyCallback.onAction(Callback.ACTION_AUTHENTICATED) + legacyCallback.onAction( + if (authState.isAuthenticatedAndExplicitlyConfirmed) { + Callback.ACTION_AUTHENTICATED_AND_CONFIRMED + } else { + Callback.ACTION_AUTHENTICATED + } + ) } } } @@ -390,7 +400,6 @@ private class Spaghetti( private var lifecycleScope: CoroutineScope? = null private var modalities: BiometricModalities = BiometricModalities() - private var faceFailedAtLeastOnce = false private var legacyCallback: Callback? = null override var legacyIconController: AuthIconController? = null @@ -470,19 +479,15 @@ private class Spaghetti( viewModel.ensureFingerprintHasStarted(isDelayed = true) applicationScope.launch { - val suppress = - modalities.hasFaceAndFingerprint && - (failedModality == BiometricModality.Face) && - faceFailedAtLeastOnce - if (failedModality == BiometricModality.Face) { - faceFailedAtLeastOnce = true - } - viewModel.showTemporaryError( failureReason, messageAfterError = modalities.asDefaultHelpMessage(applicationContext), authenticateAfterError = modalities.hasFingerprint, - suppressIfErrorShowing = suppress, + suppressIf = { currentMessage -> + modalities.hasFaceAndFingerprint && + failedModality == BiometricModality.Face && + currentMessage.isError + }, failedModality = failedModality, ) } @@ -495,11 +500,10 @@ private class Spaghetti( } applicationScope.launch { - val suppress = - modalities.hasFaceAndFingerprint && (errorModality == BiometricModality.Face) viewModel.showTemporaryError( error, - suppressIfErrorShowing = suppress, + messageAfterError = modalities.asDefaultHelpMessage(applicationContext), + authenticateAfterError = modalities.hasFingerprint, ) delay(BiometricPrompt.HIDE_DIALOG_DELAY.toLong()) legacyCallback?.onAction(Callback.ACTION_ERROR) @@ -512,9 +516,12 @@ private class Spaghetti( } applicationScope.launch { - viewModel.showTemporaryHelp( + // help messages from the HAL should be displayed as temporary (i.e. soft) errors + viewModel.showTemporaryError( help, - messageAfterHelp = modalities.asDefaultHelpMessage(applicationContext), + messageAfterError = modalities.asDefaultHelpMessage(applicationContext), + authenticateAfterError = modalities.hasFingerprint, + hapticFeedback = false, ) } } @@ -527,7 +534,7 @@ private class Spaghetti( else -> false } - override fun startTransitionToCredentialUI() { + override fun startTransitionToCredentialUI(isError: Boolean) { applicationScope.launch { viewModel.onSwitchToCredential() legacyCallback?.onAction(Callback.ACTION_USE_DEVICE_CREDENTIAL) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt index 1dffa80a084f..1a286cf57982 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt @@ -28,6 +28,7 @@ import android.view.accessibility.AccessibilityManager import android.widget.TextView import androidx.core.animation.addListener import androidx.core.view.doOnLayout +import androidx.core.view.isGone import androidx.lifecycle.lifecycleScope import com.android.systemui.R import com.android.systemui.biometrics.AuthDialog @@ -78,9 +79,11 @@ object BiometricViewSizeBinder { // cache the original position of the icon view (as done in legacy view) // this must happen before any size changes can be made - var iconHolderOriginalY = 0f view.doOnLayout { - iconHolderOriginalY = iconHolderView.y + // TODO(b/251476085): this old way of positioning has proven itself unreliable + // remove this and associated thing like (UdfpsDialogMeasureAdapter) and + // pin to the physical sensor + val iconHolderOriginalY = iconHolderView.y // bind to prompt // TODO(b/251476085): migrate the legacy panel controller and simplify this @@ -141,7 +144,11 @@ object BiometricViewSizeBinder { listOf( iconHolderView.asVerticalAnimator( duration = duration.toLong(), - toY = iconHolderOriginalY, + toY = + iconHolderOriginalY - + viewsToHideWhenSmall + .filter { it.isGone } + .sumOf { it.height }, ), viewsToFadeInOnSizeChange.asFadeInAnimator( duration = duration.toLong(), diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt index 9cb91b3d51a7..2f9557f70a32 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt @@ -16,7 +16,7 @@ package com.android.systemui.biometrics.ui.viewmodel -import com.android.systemui.biometrics.domain.model.BiometricModality +import com.android.systemui.biometrics.shared.model.BiometricModality /** * The authenticated state with the [authenticatedModality] (when [isAuthenticated]) with an @@ -29,10 +29,16 @@ data class PromptAuthState( val needsUserConfirmation: Boolean = false, val delay: Long = 0, ) { + private var wasConfirmed = false + /** If authentication was successful and the user has confirmed (or does not need to). */ val isAuthenticatedAndConfirmed: Boolean get() = isAuthenticated && !needsUserConfirmation + /** Same as [isAuthenticatedAndConfirmed] but only true if the user clicked a confirm button. */ + val isAuthenticatedAndExplicitlyConfirmed: Boolean + get() = isAuthenticated && wasConfirmed + /** If a successful authentication has not occurred. */ val isNotAuthenticated: Boolean get() = !isAuthenticated @@ -45,12 +51,16 @@ data class PromptAuthState( val isAuthenticatedByFingerprint: Boolean get() = isAuthenticated && authenticatedModality == BiometricModality.Fingerprint - /** Copies this state, but toggles [needsUserConfirmation] to false. */ - fun asConfirmed(): PromptAuthState = + /** + * Copies this state, but toggles [needsUserConfirmation] to false and ensures that + * [isAuthenticatedAndExplicitlyConfirmed] is true. + */ + fun asExplicitlyConfirmed(): PromptAuthState = PromptAuthState( - isAuthenticated = isAuthenticated, - authenticatedModality = authenticatedModality, - needsUserConfirmation = false, - delay = delay, - ) + isAuthenticated = isAuthenticated, + authenticatedModality = authenticatedModality, + needsUserConfirmation = false, + delay = delay, + ) + .apply { wasConfirmed = true } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt index 219da716f7d9..50f491142949 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt @@ -33,9 +33,9 @@ sealed interface PromptMessage { else -> "" } - /** If this is an [Error] or [Help] message. */ - val isErrorOrHelp: Boolean - get() = this is Error || this is Help + /** If this is an [Error]. */ + val isError: Boolean + get() = this is Error /** An error message. */ data class Error(val errorMessage: String) : PromptMessage 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 2f8ed096f4ba..8a2e4059ee73 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 @@ -20,8 +20,9 @@ import android.util.Log import com.android.systemui.biometrics.AuthBiometricView import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.model.BiometricModalities -import com.android.systemui.biometrics.domain.model.BiometricModality +import com.android.systemui.biometrics.shared.model.BiometricModality import com.android.systemui.biometrics.shared.model.PromptKind +import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope @@ -41,6 +42,7 @@ class PromptViewModel @Inject constructor( private val interactor: PromptSelectorInteractor, + private val vibrator: VibratorHelper, ) { /** The set of modalities available for this prompt */ val modalities: Flow<BiometricModalities> = @@ -61,8 +63,11 @@ constructor( /** If the user has successfully authenticated and confirmed (when explicitly required). */ val isAuthenticated: Flow<PromptAuthState> = _isAuthenticated.asStateFlow() - /** If the API caller requested explicit confirmation after successful authentication. */ - val isConfirmationRequested: Flow<Boolean> = interactor.isConfirmationRequested + /** + * If the API caller or the user's personal preferences require explicit confirmation after + * successful authentication. + */ + val isConfirmationRequired: Flow<Boolean> = interactor.isConfirmationRequired /** The kind of credential the user has. */ val credentialKind: Flow<PromptKind> = interactor.credentialKind @@ -91,7 +96,7 @@ constructor( _forceLargeSize, _forceMediumSize, modalities, - interactor.isConfirmationRequested, + interactor.isConfirmationRequired, fingerprintStartMode, ) { forceLarge, forceMedium, modalities, confirmationRequired, fpStartMode -> when { @@ -202,37 +207,43 @@ constructor( private var messageJob: Job? = null /** - * Show a temporary error [message] associated with an optional [failedModality]. + * Show a temporary error [message] associated with an optional [failedModality] and play + * [hapticFeedback]. * - * An optional [messageAfterError] will be shown via [showAuthenticating] when - * [authenticateAfterError] is set (or via [showHelp] when not set) after the error is - * dismissed. + * The [messageAfterError] will be shown via [showAuthenticating] when [authenticateAfterError] + * is set (or via [showHelp] when not set) after the error is dismissed. * - * The error is ignored if the user has already authenticated and it is treated as - * [onSilentError] if [suppressIfErrorShowing] is set and an error message is already showing. + * The error is ignored if the user has already authenticated or if [suppressIf] is true given + * the currently showing [PromptMessage]. */ suspend fun showTemporaryError( message: String, - messageAfterError: String = "", - authenticateAfterError: Boolean = false, - suppressIfErrorShowing: Boolean = false, + messageAfterError: String, + authenticateAfterError: Boolean, + suppressIf: (PromptMessage) -> Boolean = { false }, + hapticFeedback: Boolean = true, failedModality: BiometricModality = BiometricModality.None, ) = coroutineScope { if (_isAuthenticated.value.isAuthenticated) { return@coroutineScope } - if (_message.value.isErrorOrHelp && suppressIfErrorShowing) { - onSilentError(failedModality) + + _canTryAgainNow.value = supportsRetry(failedModality) + + if (suppressIf(_message.value)) { return@coroutineScope } _isAuthenticating.value = false _isAuthenticated.value = PromptAuthState(false) _forceMediumSize.value = true - _canTryAgainNow.value = supportsRetry(failedModality) _message.value = PromptMessage.Error(message) _legacyState.value = AuthBiometricView.STATE_ERROR + if (hapticFeedback) { + vibrator.error(failedModality) + } + messageJob?.cancel() messageJob = launch { delay(BiometricPrompt.HIDE_DIALOG_DELAY.toLong()) @@ -245,18 +256,6 @@ constructor( } /** - * Call instead of [showTemporaryError] if an error from the HAL should be silently ignored to - * enable retry (if the [failedModality] supports retrying). - * - * Ignored if the user has already authenticated. - */ - private fun onSilentError(failedModality: BiometricModality = BiometricModality.None) { - if (_isAuthenticated.value.isNotAuthenticated) { - _canTryAgainNow.value = supportsRetry(failedModality) - } - } - - /** * Call to ensure the fingerprint sensor has started. Either when the dialog is first shown * (most cases) or when it should be enabled after a first error (coex implicit flow). */ @@ -373,6 +372,10 @@ constructor( AuthBiometricView.STATE_AUTHENTICATED } + if (!needsUserConfirmation) { + vibrator.success(modality) + } + messageJob?.cancel() messageJob = null @@ -383,18 +386,18 @@ constructor( private suspend fun needsExplicitConfirmation(modality: BiometricModality): Boolean { val availableModalities = modalities.first() - val confirmationRequested = interactor.isConfirmationRequested.first() + val confirmationRequired = isConfirmationRequired.first() if (availableModalities.hasFaceAndFingerprint) { // coex only needs confirmation when face is successful, unless it happens on the // first attempt (i.e. without failure) before fingerprint scanning starts + val fingerprintStarted = fingerprintStartMode.first() != FingerprintStartMode.Pending if (modality == BiometricModality.Face) { - return (fingerprintStartMode.first() != FingerprintStartMode.Pending) || - confirmationRequested + return fingerprintStarted || confirmationRequired } } if (availableModalities.hasFaceOnly) { - return confirmationRequested + return confirmationRequired } // fingerprint only never requires confirmation return false @@ -409,15 +412,16 @@ constructor( fun confirmAuthenticated() { val authState = _isAuthenticated.value if (authState.isNotAuthenticated) { - "Cannot show authenticated after authenticated" Log.w(TAG, "Cannot confirm authenticated when not authenticated") return } - _isAuthenticated.value = authState.asConfirmed() + _isAuthenticated.value = authState.asExplicitlyConfirmed() _message.value = PromptMessage.Empty _legacyState.value = AuthBiometricView.STATE_AUTHENTICATED + vibrator.success(authState.authenticatedModality) + messageJob?.cancel() messageJob = null } @@ -431,6 +435,12 @@ constructor( _forceLargeSize.value = true } + private fun VibratorHelper.success(modality: BiometricModality) = + vibrateAuthSuccess("$TAG, modality = $modality BP::success") + + private fun VibratorHelper.error(modality: BiometricModality = BiometricModality.None) = + vibrateAuthError("$TAG, modality = $modality BP::error") + companion object { private const val TAG = "PromptViewModel" } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java index a431a59fcef6..a90980fddfb0 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java @@ -16,6 +16,7 @@ package com.android.systemui.dagger; +import com.android.systemui.globalactions.ShutdownUiModule; import com.android.systemui.keyguard.CustomizationProvider; import com.android.systemui.statusbar.NotificationInsetsModule; import com.android.systemui.statusbar.QsFrameTranslateModule; @@ -31,6 +32,7 @@ import dagger.Subcomponent; DependencyProvider.class, NotificationInsetsModule.class, QsFrameTranslateModule.class, + ShutdownUiModule.class, SystemUIBinder.class, SystemUIModule.class, SystemUICoreStartableModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 366056af7ab3..5087b8bd18c9 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -221,7 +221,7 @@ object Flags { // TODO(b/267722622): Tracking Bug @JvmField val WALLPAPER_PICKER_UI_FOR_AIWP = - unreleasedFlag( + releasedFlag( 229, "wallpaper_picker_ui_for_aiwp" ) @@ -662,7 +662,7 @@ object Flags { @JvmField val UDFPS_NEW_TOUCH_DETECTION = releasedFlag(2200, "udfps_new_touch_detection") @JvmField val UDFPS_ELLIPSE_DETECTION = releasedFlag(2201, "udfps_ellipse_detection") // TODO(b/278622168): Tracking Bug - @JvmField val BIOMETRIC_BP_STRONG = unreleasedFlag(2202, "biometric_bp_strong") + @JvmField val BIOMETRIC_BP_STRONG = releasedFlag(2202, "biometric_bp_strong") // 2300 - stylus @JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used") diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java index 290bf0d0734c..c5027cc511a4 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java @@ -15,27 +15,12 @@ package com.android.systemui.globalactions; import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS; -import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; -import android.annotation.Nullable; -import android.annotation.StringRes; -import android.app.Dialog; import android.content.Context; -import android.os.PowerManager; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ProgressBar; -import android.widget.TextView; -import com.android.internal.R; -import com.android.settingslib.Utils; import com.android.systemui.plugins.GlobalActions; -import com.android.systemui.scrim.ScrimDrawable; import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -50,12 +35,14 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks private final CommandQueue mCommandQueue; private final GlobalActionsDialogLite mGlobalActionsDialog; private boolean mDisabled; + private ShutdownUi mShutdownUi; @Inject public GlobalActionsImpl(Context context, CommandQueue commandQueue, GlobalActionsDialogLite globalActionsDialog, BlurUtils blurUtils, KeyguardStateController keyguardStateController, - DeviceProvisionedController deviceProvisionedController) { + DeviceProvisionedController deviceProvisionedController, + ShutdownUi shutdownUi) { mContext = context; mGlobalActionsDialog = globalActionsDialog; mKeyguardStateController = keyguardStateController; @@ -63,6 +50,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks mCommandQueue = commandQueue; mBlurUtils = blurUtils; mCommandQueue.addCallback(this); + mShutdownUi = shutdownUi; } @Override @@ -80,103 +68,8 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks @Override public void showShutdownUi(boolean isReboot, String reason) { - ScrimDrawable background = new ScrimDrawable(); - - final Dialog d = new Dialog(mContext, - com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions); - - d.setOnShowListener(dialog -> { - if (mBlurUtils.supportsBlursOnWindows()) { - int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255); - background.setAlpha(backgroundAlpha); - mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(), - (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255); - } else { - float backgroundAlpha = mContext.getResources().getFloat( - com.android.systemui.R.dimen.shutdown_scrim_behind_alpha); - background.setAlpha((int) (backgroundAlpha * 255)); - } - }); - - // Window initialization - Window window = d.getWindow(); - window.requestFeature(Window.FEATURE_NO_TITLE); - window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - // Inflate the decor view, so the attributes below are not overwritten by the theme. - window.getDecorView(); - window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT; - window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT; - window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); - window.getAttributes().setFitInsetsTypes(0 /* types */); - window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); - window.addFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR - | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); - window.setBackgroundDrawable(background); - window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi); - - d.setContentView(R.layout.shutdown_dialog); - d.setCancelable(false); - - int color; - if (mBlurUtils.supportsBlursOnWindows()) { - color = Utils.getColorAttrDefaultColor(mContext, - com.android.systemui.R.attr.wallpaperTextColor); - } else { - color = mContext.getResources().getColor( - com.android.systemui.R.color.global_actions_shutdown_ui_text); - } - - ProgressBar bar = d.findViewById(R.id.progress); - bar.getIndeterminateDrawable().setTint(color); - - TextView reasonView = d.findViewById(R.id.text1); - TextView messageView = d.findViewById(R.id.text2); - - reasonView.setTextColor(color); - messageView.setTextColor(color); - - messageView.setText(getRebootMessage(isReboot, reason)); - String rebootReasonMessage = getReasonMessage(reason); - if (rebootReasonMessage != null) { - reasonView.setVisibility(View.VISIBLE); - reasonView.setText(rebootReasonMessage); - } - - d.show(); - } - - @StringRes - private int getRebootMessage(boolean isReboot, @Nullable String reason) { - if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { - return R.string.reboot_to_update_reboot; - } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { - return R.string.reboot_to_reset_message; - } else if (isReboot) { - return R.string.reboot_to_reset_message; - } else { - return R.string.shutdown_progress; - } + mShutdownUi.showShutdownUi(isReboot, reason); } - - @Nullable - private String getReasonMessage(@Nullable String reason) { - if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { - return mContext.getString(R.string.reboot_to_update_title); - } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { - return mContext.getString(R.string.reboot_to_reset_title); - } else { - return null; - } - } - @Override public void disable(int displayId, int state1, int state2, boolean animate) { final boolean disabled = (state2 & DISABLE2_GLOBAL_ACTIONS) != 0; diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java new file mode 100644 index 000000000000..68dc1b3dc7d7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java @@ -0,0 +1,164 @@ +/* + * 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.globalactions; + +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + +import android.annotation.Nullable; +import android.annotation.StringRes; +import android.app.Dialog; +import android.content.Context; +import android.os.PowerManager; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.VisibleForTesting; + +import com.android.internal.R; +import com.android.settingslib.Utils; +import com.android.systemui.scrim.ScrimDrawable; +import com.android.systemui.statusbar.BlurUtils; +import com.android.systemui.statusbar.phone.ScrimController; + +/** + * Provides the UI shown during system shutdown. + */ +public class ShutdownUi { + + private Context mContext; + private BlurUtils mBlurUtils; + public ShutdownUi(Context context, BlurUtils blurUtils) { + mContext = context; + mBlurUtils = blurUtils; + } + + /** + * Display the shutdown UI. + * @param isReboot Whether the device will be rebooting after this shutdown. + * @param reason Cause for the shutdown. + */ + public void showShutdownUi(boolean isReboot, String reason) { + ScrimDrawable background = new ScrimDrawable(); + + final Dialog d = new Dialog(mContext, + com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions); + + d.setOnShowListener(dialog -> { + if (mBlurUtils.supportsBlursOnWindows()) { + int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255); + background.setAlpha(backgroundAlpha); + mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(), + (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255); + } else { + float backgroundAlpha = mContext.getResources().getFloat( + com.android.systemui.R.dimen.shutdown_scrim_behind_alpha); + background.setAlpha((int) (backgroundAlpha * 255)); + } + }); + + // Window initialization + Window window = d.getWindow(); + window.requestFeature(Window.FEATURE_NO_TITLE); + window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + // Inflate the decor view, so the attributes below are not overwritten by the theme. + window.getDecorView(); + window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT; + window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT; + window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); + window.getAttributes().setFitInsetsTypes(0 /* types */); + window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + window.addFlags( + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); + window.setBackgroundDrawable(background); + window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi); + + d.setContentView(getShutdownDialogContent(isReboot)); + d.setCancelable(false); + + int color; + if (mBlurUtils.supportsBlursOnWindows()) { + color = Utils.getColorAttrDefaultColor(mContext, + com.android.systemui.R.attr.wallpaperTextColor); + } else { + color = mContext.getResources().getColor( + com.android.systemui.R.color.global_actions_shutdown_ui_text); + } + + ProgressBar bar = d.findViewById(R.id.progress); + bar.getIndeterminateDrawable().setTint(color); + + TextView reasonView = d.findViewById(R.id.text1); + TextView messageView = d.findViewById(R.id.text2); + + reasonView.setTextColor(color); + messageView.setTextColor(color); + + messageView.setText(getRebootMessage(isReboot, reason)); + String rebootReasonMessage = getReasonMessage(reason); + if (rebootReasonMessage != null) { + reasonView.setVisibility(View.VISIBLE); + reasonView.setText(rebootReasonMessage); + } + + d.show(); + } + + /** + * Returns the layout resource to use for UI while shutting down. + * @param isReboot Whether this is a reboot or a shutdown. + * @return + */ + public int getShutdownDialogContent(boolean isReboot) { + return R.layout.shutdown_dialog; + } + + @StringRes + @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason) { + if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { + return R.string.reboot_to_update_reboot; + } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { + return R.string.reboot_to_reset_message; + } else if (isReboot) { + return R.string.reboot_to_reset_message; + } else { + return R.string.shutdown_progress; + } + } + + @Nullable + @VisibleForTesting String getReasonMessage(@Nullable String reason) { + if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { + return mContext.getString(R.string.reboot_to_update_title); + } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { + return mContext.getString(R.string.reboot_to_reset_title); + } else { + return null; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUiModule.kt b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUiModule.kt new file mode 100644 index 000000000000..b7285da49bb7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUiModule.kt @@ -0,0 +1,31 @@ +/* + * 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.globalactions + +import android.content.Context +import com.android.systemui.statusbar.BlurUtils +import dagger.Module +import dagger.Provides + +/** Provides the UI shown during system shutdown. */ +@Module +class ShutdownUiModule { + /** Shutdown UI provider. */ + @Provides + fun provideShutdownUi(context: Context?, blurUtils: BlurUtils?): ShutdownUi { + return ShutdownUi(context, blurUtils) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 85cbcf13ed21..505be0867fe4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2965,6 +2965,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } private void onKeyguardExitFinished() { + if (DEBUG) Log.d(TAG, "onKeyguardExitFinished()"); // only play "unlock" noises if not on a call (since the incall UI // disables the keyguard) if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) { @@ -3186,13 +3187,14 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, flags |= StatusBarManager.DISABLE_RECENT; } - if (mPowerGestureIntercepted) { + if (mPowerGestureIntercepted && mOccluded && isSecure()) { flags |= StatusBarManager.DISABLE_RECENT; } if (DEBUG) { Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded + " isSecure=" + isSecure() + " force=" + forceHideHomeRecentsButtons + + " mPowerGestureIntercepted=" + mPowerGestureIntercepted + " --> flags=0x" + Integer.toHexString(flags)); } @@ -3420,6 +3422,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, pw.print(" mPendingLock: "); pw.println(mPendingLock); pw.print(" wakeAndUnlocking: "); pw.println(mWakeAndUnlocking); pw.print(" mPendingPinLock: "); pw.println(mPendingPinLock); + pw.print(" mPowerGestureIntercepted: "); pw.println(mPowerGestureIntercepted); } /** diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt index 74ef7a50fd44..fe778a6e1ccd 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt @@ -60,6 +60,7 @@ interface KeyguardFaceAuthInteractor { fun onNotificationPanelClicked() fun onSwipeUpOnBouncer() fun onPrimaryBouncerUserInput() + fun onAccessibilityAction() } /** diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt index 5005b6c7f0df..69474e7f93b3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt @@ -60,4 +60,5 @@ class NoopKeyguardFaceAuthInteractor @Inject constructor() : KeyguardFaceAuthInt override fun onSwipeUpOnBouncer() {} override fun onPrimaryBouncerUserInput() {} + override fun onAccessibilityAction() {} } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt index 6b515dab79f6..bcd11a700898 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt @@ -133,6 +133,10 @@ constructor( runFaceAuth(FaceAuthUiEvent.FACE_AUTH_TRIGGERED_UDFPS_POINTER_DOWN, false) } + override fun onAccessibilityAction() { + runFaceAuth(FaceAuthUiEvent.FACE_AUTH_ACCESSIBILITY_ACTION, false) + } + override fun registerListener(listener: FaceAuthenticationListener) { listeners.add(listener) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index b847fb6ded83..03c458918f4b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -1002,7 +1002,13 @@ public class KeyguardIndicationController { return; // udfps affordance is highlighted, no need to show action to unlock } else if (mKeyguardUpdateMonitor.isFaceEnrolled() && !mKeyguardUpdateMonitor.getIsFaceAuthenticated()) { - String message = mContext.getString(R.string.keyguard_retry); + String message; + if (mAccessibilityManager.isEnabled() + || mAccessibilityManager.isTouchExplorationEnabled()) { + message = mContext.getString(R.string.accesssibility_keyguard_retry); + } else { + message = mContext.getString(R.string.keyguard_retry); + } mStatusBarKeyguardViewManager.setKeyguardMessage(message, mInitialTextColorState); } } else { diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java index 640adcc9dd94..5e489b0f38ac 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java @@ -20,15 +20,14 @@ import com.android.systemui.dagger.DefaultComponentBinder; import com.android.systemui.dagger.DependencyProvider; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.SystemUIBinder; import com.android.systemui.dagger.SystemUIModule; +import com.android.systemui.globalactions.ShutdownUiModule; +import com.android.systemui.keyguard.dagger.KeyguardModule; +import com.android.systemui.recents.RecentsModule; import com.android.systemui.statusbar.dagger.CentralSurfacesDependenciesModule; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.row.NotificationRowModule; -import com.android.systemui.keyguard.dagger.KeyguardModule; -import com.android.systemui.recents.RecentsModule; - import dagger.Subcomponent; /** @@ -43,6 +42,7 @@ import dagger.Subcomponent; NotificationRowModule.class, NotificationsModule.class, RecentsModule.class, + ShutdownUiModule.class, SystemUIModule.class, TvSystemUIBinder.class, TVSystemUICoreStartableModule.class, diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index 2f20f76ccc50..95daf1907de6 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -60,6 +60,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate; import com.android.systemui.biometrics.SideFpsController; import com.android.systemui.biometrics.SideFpsUiRequestSource; import com.android.systemui.classifier.FalsingA11yDelegate; @@ -158,6 +159,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { private ViewMediatorCallback mViewMediatorCallback; @Mock private AudioManager mAudioManager; + @Mock + private FaceAuthAccessibilityDelegate mFaceAuthAccessibilityDelegate; @Captor private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback; @@ -216,7 +219,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate, mTelephonyManager, mViewMediatorCallback, mAudioManager, - mock(KeyguardFaceAuthInteractor.class)); + mock(KeyguardFaceAuthInteractor.class), + mFaceAuthAccessibilityDelegate); } @Test @@ -685,6 +689,11 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { verify(mView).setTranslationY(0f); } + @Test + public void setAccessibilityDelegate() { + verify(mView).setAccessibilityDelegate(eq(mFaceAuthAccessibilityDelegate)); + } + private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() { mKeyguardSecurityContainerController.onViewAttached(); verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture()); 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 d31a86ae2809..e3e61306bcd7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -51,6 +51,7 @@ import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -99,6 +100,8 @@ open class AuthContainerViewTest : SysuiTestCase() { lateinit var windowToken: IBinder @Mock lateinit var interactionJankMonitor: InteractionJankMonitor + @Mock + lateinit var vibrator: VibratorHelper // TODO(b/278622168): remove with flag open val useNewBiometricPrompt = false @@ -325,7 +328,7 @@ open class AuthContainerViewTest : SysuiTestCase() { authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL ) - container.animateToCredentialUI() + container.animateToCredentialUI(false) waitForIdleSync() assertThat(container.hasCredentialView()).isTrue() @@ -514,7 +517,7 @@ open class AuthContainerViewTest : SysuiTestCase() { { authBiometricFingerprintViewModel }, { promptSelectorInteractor }, { bpCredentialInteractor }, - PromptViewModel(promptSelectorInteractor), + PromptViewModel(promptSelectorInteractor, vibrator), { credentialViewModel }, Handler(TestableLooper.get(this).looper), fakeExecutor diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index b9f92a064bc8..0a73a9eba9ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -191,6 +191,10 @@ public class AuthControllerTest extends SysuiTestCase { private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor; @Captor private ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; + @Captor + private ArgumentCaptor<Integer> mModalityCaptor; + @Captor + private ArgumentCaptor<String> mMessageCaptor; @Mock private Resources mResources; @@ -202,9 +206,6 @@ public class AuthControllerTest extends SysuiTestCase { private TestableAuthController mAuthController; private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags(); - @Mock - private VibratorHelper mVibratorHelper; - @Before public void setup() throws RemoteException { // TODO(b/278622168): remove with flag @@ -267,7 +268,6 @@ public class AuthControllerTest extends SysuiTestCase { true /* supportsSelfIllumination */, true /* resetLockoutRequireHardwareAuthToken */)); when(mFaceManager.getSensorPropertiesInternal()).thenReturn(faceProps); - when(mVibratorHelper.hasVibrator()).thenReturn(true); mAuthController = new TestableAuthController(mContextSpy); @@ -482,16 +482,63 @@ public class AuthControllerTest extends SysuiTestCase { BiometricConstants.BIOMETRIC_PAUSED_REJECTED, 0 /* vendorCode */); - ArgumentCaptor<Integer> modalityCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class); - verify(mDialog1).onAuthenticationFailed(modalityCaptor.capture(), messageCaptor.capture()); + verify(mDialog1).onAuthenticationFailed(mModalityCaptor.capture(), mMessageCaptor.capture()); - assertEquals(modalityCaptor.getValue().intValue(), modality); - assertEquals(messageCaptor.getValue(), + assertEquals(mModalityCaptor.getValue().intValue(), modality); + assertEquals(mMessageCaptor.getValue(), mContext.getString(R.string.biometric_not_recognized)); } @Test + public void testOnAuthenticationFailedInvoked_coex_whenFaceAuthRejected_withPaused() { + testOnAuthenticationFailedInvoked_coex_whenFaceAuthRejected( + BiometricConstants.BIOMETRIC_PAUSED_REJECTED); + } + + @Test + public void testOnAuthenticationFailedInvoked_coex_whenFaceAuthRejected_withTimeout() { + testOnAuthenticationFailedInvoked_coex_whenFaceAuthRejected( + BiometricConstants.BIOMETRIC_ERROR_TIMEOUT); + } + + private void testOnAuthenticationFailedInvoked_coex_whenFaceAuthRejected(int error) { + final int modality = BiometricAuthenticator.TYPE_FACE; + final int userId = 0; + + enrollFingerprintAndFace(userId); + + showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); + + mAuthController.onBiometricError(modality, error, 0 /* vendorCode */); + + verify(mDialog1).onAuthenticationFailed(mModalityCaptor.capture(), mMessageCaptor.capture()); + + assertThat(mModalityCaptor.getValue().intValue()).isEqualTo(modality); + assertThat(mMessageCaptor.getValue()).isEqualTo( + mContext.getString(R.string.biometric_face_not_recognized)); + } + + @Test + public void testOnAuthenticationFailedInvoked_whenFingerprintAuthRejected() { + final int modality = BiometricAuthenticator.TYPE_FINGERPRINT; + final int userId = 0; + + enrollFingerprintAndFace(userId); + + showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); + + mAuthController.onBiometricError(modality, + BiometricConstants.BIOMETRIC_PAUSED_REJECTED, + 0 /* vendorCode */); + + verify(mDialog1).onAuthenticationFailed(mModalityCaptor.capture(), mMessageCaptor.capture()); + + assertThat(mModalityCaptor.getValue().intValue()).isEqualTo(modality); + assertThat(mMessageCaptor.getValue()).isEqualTo( + mContext.getString(R.string.fingerprint_error_not_match)); + } + + @Test public void testOnAuthenticationFailedInvoked_whenBiometricTimedOut() { showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); final int modality = BiometricAuthenticator.TYPE_FACE; @@ -499,13 +546,11 @@ public class AuthControllerTest extends SysuiTestCase { final int vendorCode = 0; mAuthController.onBiometricError(modality, error, vendorCode); - ArgumentCaptor<Integer> modalityCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class); - verify(mDialog1).onAuthenticationFailed(modalityCaptor.capture(), messageCaptor.capture()); + verify(mDialog1).onAuthenticationFailed(mModalityCaptor.capture(), mMessageCaptor.capture()); - assertEquals(modalityCaptor.getValue().intValue(), modality); - assertEquals(messageCaptor.getValue(), - FaceManager.getErrorString(mContext, error, vendorCode)); + assertThat(mModalityCaptor.getValue().intValue()).isEqualTo(modality); + assertThat(mMessageCaptor.getValue()).isEqualTo( + mContext.getString(R.string.biometric_not_recognized)); } @Test @@ -515,12 +560,10 @@ public class AuthControllerTest extends SysuiTestCase { final String helpMessage = "help"; mAuthController.onBiometricHelp(modality, helpMessage); - ArgumentCaptor<Integer> modalityCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class); - verify(mDialog1).onHelp(modalityCaptor.capture(), messageCaptor.capture()); + verify(mDialog1).onHelp(mModalityCaptor.capture(), mMessageCaptor.capture()); - assertEquals(modalityCaptor.getValue().intValue(), modality); - assertEquals(messageCaptor.getValue(), helpMessage); + assertThat(mModalityCaptor.getValue().intValue()).isEqualTo(modality); + assertThat(mMessageCaptor.getValue()).isEqualTo(helpMessage); } @Test @@ -531,12 +574,10 @@ public class AuthControllerTest extends SysuiTestCase { final int vendorCode = 0; mAuthController.onBiometricError(modality, error, vendorCode); - ArgumentCaptor<Integer> modalityCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class); - verify(mDialog1).onError(modalityCaptor.capture(), messageCaptor.capture()); + verify(mDialog1).onError(mModalityCaptor.capture(), mMessageCaptor.capture()); - assertEquals(modalityCaptor.getValue().intValue(), modality); - assertEquals(messageCaptor.getValue(), + assertThat(mModalityCaptor.getValue().intValue()).isEqualTo(modality); + assertThat(mMessageCaptor.getValue()).isEqualTo( FaceManager.getErrorString(mContext, error, vendorCode)); } @@ -550,7 +591,7 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); verify(mDialog1, never()).onError(anyInt(), anyString()); - verify(mDialog1).animateToCredentialUI(); + verify(mDialog1).animateToCredentialUI(eq(true)); } @Test @@ -563,7 +604,7 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); verify(mDialog1, never()).onError(anyInt(), anyString()); - verify(mDialog1).animateToCredentialUI(); + verify(mDialog1).animateToCredentialUI(eq(true)); } @Test @@ -578,7 +619,7 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.onBiometricError(modality, error, vendorCode); verify(mDialog1).onError( eq(modality), eq(FaceManager.getErrorString(mContext, error, vendorCode))); - verify(mDialog1, never()).animateToCredentialUI(); + verify(mDialog1, never()).animateToCredentialUI(eq(true)); } @Test @@ -593,7 +634,7 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.onBiometricError(modality, error, vendorCode); verify(mDialog1).onError( eq(modality), eq(FaceManager.getErrorString(mContext, error, vendorCode))); - verify(mDialog1, never()).animateToCredentialUI(); + verify(mDialog1, never()).animateToCredentialUI(eq(true)); } @Test @@ -998,6 +1039,31 @@ public class AuthControllerTest extends SysuiTestCase { return HAT; } + private void enrollFingerprintAndFace(final int userId) { + + // Enroll fingerprint + verify(mFingerprintManager).registerBiometricStateListener( + mBiometricStateCaptor.capture()); + assertFalse(mAuthController.isFingerprintEnrolled(userId)); + + mBiometricStateCaptor.getValue().onEnrollmentsChanged(userId, + 1 /* sensorId */, true /* hasEnrollments */); + waitForIdleSync(); + + assertTrue(mAuthController.isFingerprintEnrolled(userId)); + + // Enroll face + verify(mFaceManager).registerBiometricStateListener( + mBiometricStateCaptor.capture()); + assertFalse(mAuthController.isFaceAuthEnrolled(userId)); + + mBiometricStateCaptor.getValue().onEnrollmentsChanged(userId, + 2 /* sensorId */, true /* hasEnrollments */); + waitForIdleSync(); + + assertTrue(mAuthController.isFaceAuthEnrolled(userId)); + } + private final class TestableAuthController extends AuthController { private int mBuildCount = 0; private PromptInfo mLastBiometricPromptInfo; @@ -1012,7 +1078,7 @@ public class AuthControllerTest extends SysuiTestCase { () -> mBiometricPromptCredentialInteractor, () -> mPromptSelectionInteractor, () -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor, mHandler, - mBackgroundExecutor, mVibratorHelper, mUdfpsUtils); + mBackgroundExecutor, mUdfpsUtils); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java index 38c9caf085e2..9cb3b1aa9a55 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java @@ -30,7 +30,11 @@ import android.app.Notification; import android.app.NotificationManager; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricSourceType; +import android.hardware.biometrics.BiometricStateListener; +import android.hardware.face.FaceManager; +import android.hardware.fingerprint.FingerprintManager; import android.os.Handler; +import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -69,6 +73,10 @@ public class BiometricNotificationServiceTest extends SysuiTestCase { Optional<FingerprintReEnrollNotification> mFingerprintReEnrollNotificationOptional; @Mock FingerprintReEnrollNotification mFingerprintReEnrollNotification; + @Mock + FingerprintManager mFingerprintManager; + @Mock + FaceManager mFaceManager; private static final String TAG = "BiometricNotificationService"; private static final int FACE_NOTIFICATION_ID = 1; @@ -81,6 +89,8 @@ public class BiometricNotificationServiceTest extends SysuiTestCase { private TestableLooper mLooper; private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback; private KeyguardStateController.Callback mKeyguardStateControllerCallback; + private BiometricStateListener mFaceStateListener; + private BiometricStateListener mFingerprintStateListener; @Before public void setUp() { @@ -99,25 +109,37 @@ public class BiometricNotificationServiceTest extends SysuiTestCase { mKeyguardUpdateMonitor, mKeyguardStateController, handler, mNotificationManager, broadcastReceiver, - mFingerprintReEnrollNotificationOptional); + mFingerprintReEnrollNotificationOptional, + mFingerprintManager, + mFaceManager); biometricNotificationService.start(); ArgumentCaptor<KeyguardUpdateMonitorCallback> updateMonitorCallbackArgumentCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class); ArgumentCaptor<KeyguardStateController.Callback> stateControllerCallbackArgumentCaptor = ArgumentCaptor.forClass(KeyguardStateController.Callback.class); + ArgumentCaptor<BiometricStateListener> faceStateListenerArgumentCaptor = + ArgumentCaptor.forClass(BiometricStateListener.class); + ArgumentCaptor<BiometricStateListener> fingerprintStateListenerArgumentCaptor = + ArgumentCaptor.forClass(BiometricStateListener.class); verify(mKeyguardUpdateMonitor).registerCallback( updateMonitorCallbackArgumentCaptor.capture()); verify(mKeyguardStateController).addCallback( stateControllerCallbackArgumentCaptor.capture()); + verify(mFaceManager).registerBiometricStateListener( + faceStateListenerArgumentCaptor.capture()); + verify(mFingerprintManager).registerBiometricStateListener( + fingerprintStateListenerArgumentCaptor.capture()); + mFaceStateListener = faceStateListenerArgumentCaptor.getValue(); + mFingerprintStateListener = fingerprintStateListenerArgumentCaptor.getValue(); mKeyguardUpdateMonitorCallback = updateMonitorCallbackArgumentCaptor.getValue(); mKeyguardStateControllerCallback = stateControllerCallbackArgumentCaptor.getValue(); } @Test - public void testShowFingerprintReEnrollNotification() { + public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll() { when(mKeyguardStateController.isShowing()).thenReturn(false); mKeyguardUpdateMonitorCallback.onBiometricHelp( @@ -139,7 +161,7 @@ public class BiometricNotificationServiceTest extends SysuiTestCase { .isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG); } @Test - public void testShowFaceReEnrollNotification() { + public void testShowFaceReEnrollNotification_onErrorReEnroll() { when(mKeyguardStateController.isShowing()).thenReturn(false); mKeyguardUpdateMonitorCallback.onBiometricError( @@ -161,4 +183,52 @@ public class BiometricNotificationServiceTest extends SysuiTestCase { .isEqualTo(ACTION_SHOW_FACE_REENROLL_DIALOG); } + @Test + public void testCancelReEnrollmentNotification_onFaceEnrollmentStateChange() { + when(mKeyguardStateController.isShowing()).thenReturn(false); + + mKeyguardUpdateMonitorCallback.onBiometricError( + BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL, + "Testing Face Re-enrollment" /* errString */, + BiometricSourceType.FACE + ); + mKeyguardStateControllerCallback.onKeyguardShowingChanged(); + + mLooper.moveTimeForward(SHOW_NOTIFICATION_DELAY_MS); + mLooper.processAllMessages(); + + verify(mNotificationManager).notifyAsUser(eq(TAG), eq(FACE_NOTIFICATION_ID), + mNotificationArgumentCaptor.capture(), any()); + + mFaceStateListener.onEnrollmentsChanged(0 /* userId */, 0 /* sensorId */, + false /* hasEnrollments */); + + verify(mNotificationManager).cancelAsUser(eq(TAG), eq(FACE_NOTIFICATION_ID), + eq(UserHandle.CURRENT)); + } + + @Test + public void testCancelReEnrollmentNotification_onFingerprintEnrollmentStateChange() { + when(mKeyguardStateController.isShowing()).thenReturn(false); + + mKeyguardUpdateMonitorCallback.onBiometricHelp( + FINGERPRINT_ACQUIRED_RE_ENROLL, + "Testing Fingerprint Re-enrollment" /* errString */, + BiometricSourceType.FINGERPRINT + ); + mKeyguardStateControllerCallback.onKeyguardShowingChanged(); + + mLooper.moveTimeForward(SHOW_NOTIFICATION_DELAY_MS); + mLooper.processAllMessages(); + + verify(mNotificationManager).notifyAsUser(eq(TAG), eq(FINGERPRINT_NOTIFICATION_ID), + mNotificationArgumentCaptor.capture(), any()); + + mFingerprintStateListener.onEnrollmentsChanged(0 /* userId */, 0 /* sensorId */, + false /* hasEnrollments */); + + verify(mNotificationManager).cancelAsUser(eq(TAG), eq(FINGERPRINT_NOTIFICATION_ID), + eq(UserHandle.CURRENT)); + } + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt new file mode 100644 index 000000000000..ec17794d4ee2 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt @@ -0,0 +1,111 @@ +/* + * 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.biometrics + +import android.testing.TestableLooper +import android.view.View +import android.view.accessibility.AccessibilityNodeInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.keyguard.FaceAuthApiRequestReason +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor +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.whenever +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidJUnit4::class) +@SmallTest +@TestableLooper.RunWithLooper +class FaceAuthAccessibilityDelegateTest : SysuiTestCase() { + + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + @Mock private lateinit var hostView: View + @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor + private lateinit var underTest: FaceAuthAccessibilityDelegate + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + underTest = + FaceAuthAccessibilityDelegate( + context.resources, + keyguardUpdateMonitor, + faceAuthInteractor, + ) + } + + @Test + fun shouldListenForFaceTrue_onInitializeAccessibilityNodeInfo_clickActionAdded() { + whenever(keyguardUpdateMonitor.shouldListenForFace()).thenReturn(true) + + // WHEN node is initialized + val mockedNodeInfo = mock(AccessibilityNodeInfo::class.java) + underTest.onInitializeAccessibilityNodeInfo(hostView, mockedNodeInfo) + + // THEN a11y action is added + val argumentCaptor = argumentCaptor<AccessibilityNodeInfo.AccessibilityAction>() + verify(mockedNodeInfo).addAction(argumentCaptor.capture()) + + // AND the a11y action is a click action + assertEquals( + AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id, + argumentCaptor.value.id + ) + } + + @Test + fun shouldListenForFaceFalse_onInitializeAccessibilityNodeInfo_clickActionNotAdded() { + whenever(keyguardUpdateMonitor.shouldListenForFace()).thenReturn(false) + + // WHEN node is initialized + val mockedNodeInfo = mock(AccessibilityNodeInfo::class.java) + underTest.onInitializeAccessibilityNodeInfo(hostView, mockedNodeInfo) + + // THEN a11y action is NOT added + verify(mockedNodeInfo, never()) + .addAction(any(AccessibilityNodeInfo.AccessibilityAction::class.java)) + } + + @Test + fun performAccessibilityAction_actionClick_retriesFaceAuth() { + whenever(keyguardUpdateMonitor.shouldListenForFace()).thenReturn(true) + + // WHEN click action is performed + underTest.performAccessibilityAction( + hostView, + AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id, + null + ) + + // THEN retry face auth + verify(keyguardUpdateMonitor) + .requestFaceAuth(eq(FaceAuthApiRequestReason.ACCESSIBILITY_ACTION)) + verify(faceAuthInteractor).onAccessibilityAction() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 78341915edb7..7578cc774c48 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -442,6 +442,16 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test + public void showUdfpsOverlay_callsListener() throws RemoteException { + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + verify(mFingerprintManager).onUdfpsUiEvent(FingerprintManager.UDFPS_UI_OVERLAY_SHOWN, + TEST_REQUEST_ID, mOpticalProps.sensorId); + } + + @Test public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception { mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); @@ -761,17 +771,20 @@ public class UdfpsControllerTest extends SysuiTestCase { inOrder.verify(mAlternateTouchProvider).onUiReady(); inOrder.verify(mLatencyTracker).onActionEnd( eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); - verify(mFingerprintManager, never()).onUiReady(anyLong(), anyInt()); + verify(mFingerprintManager, never()).onUdfpsUiEvent( + eq(FingerprintManager.UDFPS_UI_READY), anyLong(), anyInt()); } else { InOrder inOrder = inOrder(mFingerprintManager, mLatencyTracker); - inOrder.verify(mFingerprintManager).onUiReady(eq(TEST_REQUEST_ID), + inOrder.verify(mFingerprintManager).onUdfpsUiEvent( + eq(FingerprintManager.UDFPS_UI_READY), eq(TEST_REQUEST_ID), eq(testParams.sensorProps.sensorId)); inOrder.verify(mLatencyTracker).onActionEnd( eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); verify(mAlternateTouchProvider, never()).onUiReady(); } } else { - verify(mFingerprintManager, never()).onUiReady(anyLong(), anyInt()); + verify(mFingerprintManager, never()).onUdfpsUiEvent( + eq(FingerprintManager.UDFPS_UI_READY), anyLong(), anyInt()); verify(mAlternateTouchProvider, never()).onUiReady(); verify(mLatencyTracker, never()).onActionEnd( eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); @@ -1327,12 +1340,22 @@ public class UdfpsControllerTest extends SysuiTestCase { // WHEN ACTION_DOWN is received when(mSinglePointerTouchProcessor.processTouch(any(), anyInt(), any())).thenReturn( processorResultDown); - MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); - mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + MotionEvent event = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); mBiometricExecutor.runAllReady(); - downEvent.recycle(); - // THEN the touch is pilfered + // WHEN ACTION_MOVE is received after + final TouchProcessorResult processorResultUnchanged = + new TouchProcessorResult.ProcessedTouch( + InteractionEvent.UNCHANGED, 1 /* pointerId */, touchData); + when(mSinglePointerTouchProcessor.processTouch(any(), anyInt(), any())).thenReturn( + processorResultUnchanged); + event.setAction(ACTION_MOVE); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricExecutor.runAllReady(); + event.recycle(); + + // THEN only pilfer once on the initial down verify(mInputManager).pilferPointers(any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FaceSettingsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FaceSettingsRepositoryImplTest.kt new file mode 100644 index 000000000000..0df4fbf86d98 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FaceSettingsRepositoryImplTest.kt @@ -0,0 +1,124 @@ +/* + * 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.biometrics.data.repository + +import android.database.ContentObserver +import android.os.Handler +import android.provider.Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.util.mockito.captureMany +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.mockito.withArgCaptor +import com.android.systemui.util.settings.SecureSettings +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit + +private const val USER_ID = 8 + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(JUnit4::class) +class FaceSettingsRepositoryImplTest : SysuiTestCase() { + + @JvmField @Rule var mockitoRule = MockitoJUnit.rule() + private val testScope = TestScope() + + @Mock private lateinit var mainHandler: Handler + @Mock private lateinit var secureSettings: SecureSettings + + private lateinit var repository: FaceSettingsRepositoryImpl + + @Before + fun setup() { + repository = FaceSettingsRepositoryImpl(mainHandler, secureSettings) + } + + @Test + fun createsOneRepositoryPerUser() = + testScope.runTest { + val userRepo = repository.forUser(USER_ID) + + assertThat(userRepo.userId).isEqualTo(USER_ID) + + assertThat(repository.forUser(USER_ID)).isSameInstanceAs(userRepo) + assertThat(repository.forUser(USER_ID + 1)).isNotSameInstanceAs(userRepo) + } + + @Test + fun startsRepoImmediatelyWithAllSettingKeys() = + testScope.runTest { + val userRepo = repository.forUser(USER_ID) + + val keys = + captureMany<String> { + verify(secureSettings) + .registerContentObserverForUser(capture(), anyBoolean(), any(), eq(USER_ID)) + } + + assertThat(keys).containsExactly(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION) + } + + @Test + fun forwardsSettingsValues() = runTest { + val userRepo = repository.forUser(USER_ID) + + val intAsBooleanSettings = + listOf( + FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION to + collectLastValue(userRepo.alwaysRequireConfirmationInApps) + ) + + for ((setting, accessor) in intAsBooleanSettings) { + val observer = + withArgCaptor<ContentObserver> { + verify(secureSettings) + .registerContentObserverForUser( + eq(setting), + anyBoolean(), + capture(), + eq(USER_ID) + ) + } + + for (value in listOf(true, false)) { + secureSettings.mockIntSetting(setting, if (value) 1 else 0) + observer.onChange(false) + assertThat(accessor()).isEqualTo(value) + } + } + } + + private fun SecureSettings.mockIntSetting(key: String, value: Int) { + whenever(getIntForUser(eq(key), anyInt(), eq(USER_ID))).thenReturn(value) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/PromptRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/PromptRepositoryImplTest.kt index 4836af635aed..ec7ce634fd78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/PromptRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/PromptRepositoryImplTest.kt @@ -1,3 +1,19 @@ +/* + * 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.biometrics.data.repository import android.hardware.biometrics.PromptInfo @@ -5,12 +21,16 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.AuthController import com.android.systemui.biometrics.shared.model.PromptKind +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.withArgCaptor import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Rule import org.junit.Test @@ -21,61 +41,109 @@ import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit +private const val USER_ID = 9 +private const val CHALLENGE = 90L + +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(JUnit4::class) class PromptRepositoryImplTest : SysuiTestCase() { @JvmField @Rule var mockitoRule = MockitoJUnit.rule() + private val testScope = TestScope() + private val faceSettings = FakeFaceSettingsRepository() + @Mock private lateinit var authController: AuthController private lateinit var repository: PromptRepositoryImpl @Before fun setup() { - repository = PromptRepositoryImpl(authController) + repository = PromptRepositoryImpl(faceSettings, authController) } @Test - fun isShowing() = runBlockingTest { - whenever(authController.isShowing).thenReturn(true) + fun isShowing() = + testScope.runTest { + whenever(authController.isShowing).thenReturn(true) + + val values = mutableListOf<Boolean>() + val job = launch { repository.isShowing.toList(values) } + runCurrent() - val values = mutableListOf<Boolean>() - val job = launch { repository.isShowing.toList(values) } - assertThat(values).containsExactly(true) + assertThat(values).containsExactly(true) - withArgCaptor<AuthController.Callback> { - verify(authController).addCallback(capture()) + withArgCaptor<AuthController.Callback> { + verify(authController).addCallback(capture()) - value.onBiometricPromptShown() - assertThat(values).containsExactly(true, true) + value.onBiometricPromptShown() + runCurrent() + assertThat(values).containsExactly(true, true) - value.onBiometricPromptDismissed() - assertThat(values).containsExactly(true, true, false).inOrder() + value.onBiometricPromptDismissed() + runCurrent() + assertThat(values).containsExactly(true, true, false).inOrder() - job.cancel() - verify(authController).removeCallback(eq(value)) + job.cancel() + runCurrent() + verify(authController).removeCallback(eq(value)) + } } - } @Test - fun setsAndUnsetsPrompt() = runBlockingTest { - val kind = PromptKind.Pin - val uid = 8 - val challenge = 90L - val promptInfo = PromptInfo() + fun isConfirmationRequired_whenNotForced() = + testScope.runTest { + faceSettings.setUserSettings(USER_ID, alwaysRequireConfirmationInApps = false) + val isConfirmationRequired by collectLastValue(repository.isConfirmationRequired) + + for (case in listOf(true, false)) { + repository.setPrompt( + PromptInfo().apply { isConfirmationRequested = case }, + USER_ID, + CHALLENGE, + PromptKind.Biometric() + ) + + assertThat(isConfirmationRequired).isEqualTo(case) + } + } - repository.setPrompt(promptInfo, uid, challenge, kind) + @Test + fun isConfirmationRequired_whenForced() = + testScope.runTest { + faceSettings.setUserSettings(USER_ID, alwaysRequireConfirmationInApps = true) + val isConfirmationRequired by collectLastValue(repository.isConfirmationRequired) + + for (case in listOf(true, false)) { + repository.setPrompt( + PromptInfo().apply { isConfirmationRequested = case }, + USER_ID, + CHALLENGE, + PromptKind.Biometric() + ) + + assertThat(isConfirmationRequired).isTrue() + } + } - assertThat(repository.kind.value).isEqualTo(kind) - assertThat(repository.userId.value).isEqualTo(uid) - assertThat(repository.challenge.value).isEqualTo(challenge) - assertThat(repository.promptInfo.value).isSameInstanceAs(promptInfo) + @Test + fun setsAndUnsetsPrompt() = + testScope.runTest { + val kind = PromptKind.Pin + val promptInfo = PromptInfo() - repository.unsetPrompt() + repository.setPrompt(promptInfo, USER_ID, CHALLENGE, kind) - assertThat(repository.promptInfo.value).isNull() - assertThat(repository.userId.value).isNull() - assertThat(repository.challenge.value).isNull() - } + assertThat(repository.kind.value).isEqualTo(kind) + assertThat(repository.userId.value).isEqualTo(USER_ID) + assertThat(repository.challenge.value).isEqualTo(CHALLENGE) + assertThat(repository.promptInfo.value).isSameInstanceAs(promptInfo) + + repository.unsetPrompt() + + assertThat(repository.promptInfo.value).isNull() + assertThat(repository.userId.value).isNull() + assertThat(repository.challenge.value).isNull() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt index a62ea3b77fc2..81cbaeab2a32 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt @@ -106,17 +106,11 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { val currentPrompt by collectLastValue(interactor.prompt) val credentialKind by collectLastValue(interactor.credentialKind) val isCredentialAllowed by collectLastValue(interactor.isCredentialAllowed) - val isExplicitConfirmationRequired by collectLastValue(interactor.isConfirmationRequested) + val isExplicitConfirmationRequired by collectLastValue(interactor.isConfirmationRequired) assertThat(currentPrompt).isNull() - interactor.useBiometricsForAuthentication( - info, - confirmationRequired, - USER_ID, - CHALLENGE, - modalities - ) + interactor.useBiometricsForAuthentication(info, USER_ID, CHALLENGE, modalities) assertThat(currentPrompt).isNotNull() assertThat(currentPrompt?.title).isEqualTo(TITLE) diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt index 689bb0023675..278a43ea1bf1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt @@ -18,7 +18,7 @@ package com.android.systemui.biometrics.ui.viewmodel import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.biometrics.domain.model.BiometricModality +import com.android.systemui.biometrics.shared.model.BiometricModality import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith @@ -33,6 +33,7 @@ class PromptAuthStateTest : SysuiTestCase() { with(PromptAuthState(isAuthenticated = false)) { assertThat(isNotAuthenticated).isTrue() assertThat(isAuthenticatedAndConfirmed).isFalse() + assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse() assertThat(isAuthenticatedByFace).isFalse() assertThat(isAuthenticatedByFingerprint).isFalse() } @@ -43,6 +44,7 @@ class PromptAuthStateTest : SysuiTestCase() { with(PromptAuthState(isAuthenticated = true)) { assertThat(isNotAuthenticated).isFalse() assertThat(isAuthenticatedAndConfirmed).isTrue() + assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse() assertThat(isAuthenticatedByFace).isFalse() assertThat(isAuthenticatedByFingerprint).isFalse() } @@ -50,10 +52,12 @@ class PromptAuthStateTest : SysuiTestCase() { with(PromptAuthState(isAuthenticated = true, needsUserConfirmation = true)) { assertThat(isNotAuthenticated).isFalse() assertThat(isAuthenticatedAndConfirmed).isFalse() + assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse() assertThat(isAuthenticatedByFace).isFalse() assertThat(isAuthenticatedByFingerprint).isFalse() - assertThat(asConfirmed().isAuthenticatedAndConfirmed).isTrue() + assertThat(asExplicitlyConfirmed().isAuthenticatedAndConfirmed).isTrue() + assertThat(asExplicitlyConfirmed().isAuthenticatedAndExplicitlyConfirmed).isTrue() } } @@ -64,6 +68,7 @@ class PromptAuthStateTest : SysuiTestCase() { ) { assertThat(isNotAuthenticated).isFalse() assertThat(isAuthenticatedAndConfirmed).isTrue() + assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse() assertThat(isAuthenticatedByFace).isTrue() assertThat(isAuthenticatedByFingerprint).isFalse() } @@ -79,6 +84,7 @@ class PromptAuthStateTest : SysuiTestCase() { ) { assertThat(isNotAuthenticated).isFalse() assertThat(isAuthenticatedAndConfirmed).isTrue() + assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse() assertThat(isAuthenticatedByFace).isFalse() assertThat(isAuthenticatedByFingerprint).isTrue() } 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 3ba6004e4532..91140a9b0fc4 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 @@ -27,11 +27,14 @@ import com.android.systemui.biometrics.data.repository.FakePromptRepository import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl import com.android.systemui.biometrics.domain.model.BiometricModalities -import com.android.systemui.biometrics.domain.model.BiometricModality 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.BiometricModality import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues +import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first @@ -45,6 +48,9 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit private const val USER_ID = 4 @@ -58,6 +64,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa @JvmField @Rule var mockitoRule = MockitoJUnit.rule() @Mock private lateinit var lockPatternUtils: LockPatternUtils + @Mock private lateinit var vibrator: VibratorHelper private val testScope = TestScope() private val promptRepository = FakePromptRepository() @@ -70,11 +77,11 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa selector = PromptSelectorInteractorImpl(promptRepository, lockPatternUtils) selector.resetPrompt() - viewModel = PromptViewModel(selector) + viewModel = PromptViewModel(selector, vibrator) } @Test - fun `start idle and show authenticating`() = + fun start_idle_and_show_authenticating() = runGenericTest(doNotStart = true) { val expectedSize = if (testCase.shouldStartAsImplicitFlow) PromptSize.SMALL else PromptSize.MEDIUM @@ -107,7 +114,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `shows authenticated - no errors`() = runGenericTest { + fun shows_authenticated_with_no_errors() = runGenericTest { // this case can't happen until fingerprint is started // trigger it now since no error has occurred in this test val forceError = testCase.isCoex && testCase.authenticatedByFingerprint @@ -124,6 +131,24 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa ) } + @Test + fun play_haptic_on_confirm_when_confirmation_required_otherwise_on_authenticated() = + runGenericTest { + val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false) + + viewModel.showAuthenticated(testCase.authenticatedModality, 1_000L) + + verify(vibrator, if (expectConfirmation) never() else times(1)) + .vibrateAuthSuccess(any()) + + if (expectConfirmation) { + viewModel.confirmAuthenticated() + } + + verify(vibrator).vibrateAuthSuccess(any()) + verify(vibrator, never()).vibrateAuthError(any()) + } + private suspend fun TestScope.showAuthenticated( authenticatedModality: BiometricModality, expectConfirmation: Boolean, @@ -172,7 +197,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `shows temporary errors`() = runGenericTest { + fun shows_temporary_errors() = runGenericTest { val checkAtEnd = suspend { assertButtonsVisible(negative = true) } showTemporaryErrors(restart = false) { checkAtEnd() } @@ -180,6 +205,32 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa showTemporaryErrors(restart = true) { checkAtEnd() } } + @Test + fun plays_haptic_on_errors() = runGenericTest { + viewModel.showTemporaryError( + "so sad", + messageAfterError = "", + authenticateAfterError = false, + hapticFeedback = true, + ) + + verify(vibrator).vibrateAuthError(any()) + verify(vibrator, never()).vibrateAuthSuccess(any()) + } + + @Test + fun plays_haptic_on_errors_unless_skipped() = runGenericTest { + viewModel.showTemporaryError( + "still sad", + messageAfterError = "", + authenticateAfterError = false, + hapticFeedback = false, + ) + + verify(vibrator, never()).vibrateAuthError(any()) + verify(vibrator, never()).vibrateAuthSuccess(any()) + } + private suspend fun TestScope.showTemporaryErrors( restart: Boolean, helpAfterError: String = "", @@ -233,7 +284,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `no errors or temporary help after authenticated`() = runGenericTest { + fun no_errors_or_temporary_help_after_authenticated() = runGenericTest { val authenticating by collectLastValue(viewModel.isAuthenticating) val authenticated by collectLastValue(viewModel.isAuthenticated) val message by collectLastValue(viewModel.message) @@ -249,7 +300,13 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa assertThat(canTryAgain).isFalse() } - val errorJob = launch { viewModel.showTemporaryError("error") } + val errorJob = launch { + viewModel.showTemporaryError( + "error", + messageAfterError = "", + authenticateAfterError = false, + ) + } verifyNoError() errorJob.join() verifyNoError() @@ -268,16 +325,70 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa assertThat(messageIsShowing).isTrue() } - // @Test - fun `suppress errors`() = runGenericTest { - val errorMessage = "woot" - val message by collectLastValue(viewModel.message) + @Test + fun suppress_temporary_error() = runGenericTest { + val messages by collectValues(viewModel.message) + + for (error in listOf("never", "see", "me")) { + launch { + viewModel.showTemporaryError( + error, + messageAfterError = "or me", + authenticateAfterError = false, + suppressIf = { _ -> true }, + ) + } + } + + testScheduler.advanceUntilIdle() + assertThat(messages).containsExactly(PromptMessage.Empty) + } + + @Test + fun suppress_temporary_error_when_already_showing_when_requested() = + suppress_temporary_error_when_already_showing(suppress = true) - val errorJob = launch { viewModel.showTemporaryError(errorMessage) } + @Test + fun do_not_suppress_temporary_error_when_already_showing_when_not_requested() = + suppress_temporary_error_when_already_showing(suppress = false) + + private fun suppress_temporary_error_when_already_showing(suppress: Boolean) = runGenericTest { + val errors = listOf("woot", "oh yeah", "nope") + val afterSuffix = "(after)" + val expectedErrorMessage = if (suppress) errors.first() else errors.last() + val messages by collectValues(viewModel.message) + + for (error in errors) { + launch { + viewModel.showTemporaryError( + error, + messageAfterError = "$error $afterSuffix", + authenticateAfterError = false, + suppressIf = { currentMessage -> suppress && currentMessage.isError }, + ) + } + } + + testScheduler.runCurrent() + assertThat(messages) + .containsExactly( + PromptMessage.Empty, + PromptMessage.Error(expectedErrorMessage), + ) + .inOrder() + + testScheduler.advanceUntilIdle() + assertThat(messages) + .containsExactly( + PromptMessage.Empty, + PromptMessage.Error(expectedErrorMessage), + PromptMessage.Help("$expectedErrorMessage $afterSuffix"), + ) + .inOrder() } @Test - fun `authenticated at most once`() = runGenericTest { + fun authenticated_at_most_once() = runGenericTest { val authenticating by collectLastValue(viewModel.isAuthenticating) val authenticated by collectLastValue(viewModel.isAuthenticated) @@ -293,7 +404,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `authenticating cannot restart after authenticated`() = runGenericTest { + fun authenticating_cannot_restart_after_authenticated() = runGenericTest { val authenticating by collectLastValue(viewModel.isAuthenticating) val authenticated by collectLastValue(viewModel.isAuthenticated) @@ -309,7 +420,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `confirm authentication`() = runGenericTest { + fun confirm_authentication() = runGenericTest { val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false) viewModel.showAuthenticated(testCase.authenticatedModality, 0) @@ -341,7 +452,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `cannot confirm unless authenticated`() = runGenericTest { + fun cannot_confirm_unless_authenticated() = runGenericTest { val authenticating by collectLastValue(viewModel.isAuthenticating) val authenticated by collectLastValue(viewModel.isAuthenticated) @@ -360,7 +471,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `shows help - before authenticated`() = runGenericTest { + fun shows_help_before_authenticated() = runGenericTest { val helpMessage = "please help yourself to some cookies" val message by collectLastValue(viewModel.message) val messageVisible by collectLastValue(viewModel.isIndicatorMessageVisible) @@ -379,7 +490,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `shows help - after authenticated`() = runGenericTest { + fun shows_help_after_authenticated() = runGenericTest { val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false) val helpMessage = "more cookies please" val authenticating by collectLastValue(viewModel.isAuthenticating) @@ -409,7 +520,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `retries after failure`() = runGenericTest { + fun retries_after_failure() = runGenericTest { val errorMessage = "bad" val helpMessage = "again?" val expectTryAgainButton = testCase.isFaceOnly @@ -455,7 +566,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } @Test - fun `switch to credential fallback`() = runGenericTest { + fun switch_to_credential_fallback() = runGenericTest { val size by collectLastValue(viewModel.size) // TODO(b/251476085): remove Spaghetti, migrate logic, and update this test @@ -631,7 +742,6 @@ private fun PromptSelectorInteractor.initializePrompt( } useBiometricsForAuthentication( info, - requireConfirmation, USER_ID, CHALLENGE, BiometricModalities(fingerprintProperties = fingerprint, faceProperties = face), diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java new file mode 100644 index 000000000000..9d9b263c5df5 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java @@ -0,0 +1,85 @@ +/* + * 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.globalactions; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; + +import android.os.PowerManager; +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.internal.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.BlurUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class ShutdownUiTest extends SysuiTestCase { + + ShutdownUi mShutdownUi; + @Mock + BlurUtils mBlurUtils; + + @Before + public void setUp() throws Exception { + mShutdownUi = new ShutdownUi(getContext(), mBlurUtils); + } + + @Test + public void getRebootMessage_update() { + int messageId = mShutdownUi.getRebootMessage(true, PowerManager.REBOOT_RECOVERY_UPDATE); + assertEquals(messageId, R.string.reboot_to_update_reboot); + } + + @Test + public void getRebootMessage_rebootDefault() { + int messageId = mShutdownUi.getRebootMessage(true, "anything-else"); + assertEquals(messageId, R.string.reboot_to_reset_message); + } + + @Test + public void getRebootMessage_shutdown() { + int messageId = mShutdownUi.getRebootMessage(false, "anything-else"); + assertEquals(messageId, R.string.shutdown_progress); + } + + @Test + public void getReasonMessage_update() { + String message = mShutdownUi.getReasonMessage(PowerManager.REBOOT_RECOVERY_UPDATE); + assertEquals(message, mContext.getString(R.string.reboot_to_update_title)); + } + + @Test + public void getReasonMessage_rebootDefault() { + String message = mShutdownUi.getReasonMessage(PowerManager.REBOOT_RECOVERY); + assertEquals(message, mContext.getString(R.string.reboot_to_reset_title)); + } + + @Test + public void getRebootMessage_defaultToNone() { + String message = mShutdownUi.getReasonMessage("anything-else"); + assertNull(message); + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFaceSettingsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFaceSettingsRepository.kt new file mode 100644 index 000000000000..af2706e6b287 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFaceSettingsRepository.kt @@ -0,0 +1,37 @@ +/* + * 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.biometrics.data.repository + +import kotlinx.coroutines.flow.flowOf + +/** Fake settings for tests. */ +class FakeFaceSettingsRepository : FaceSettingsRepository { + + private val userRepositories = mutableMapOf<Int, FaceUserSettingsRepository>() + + /** Add fixed settings for a user. */ + fun setUserSettings(userId: Int, alwaysRequireConfirmationInApps: Boolean = false) { + userRepositories[userId] = + object : FaceUserSettingsRepository { + override val userId = userId + override val alwaysRequireConfirmationInApps = + flowOf(alwaysRequireConfirmationInApps) + } + } + + override fun forUser(id: Int?) = userRepositories[id] ?: FaceUserSettingsRepositoryImpl.Empty +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt index d270700aa856..42ec8fed0127 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt @@ -31,13 +31,20 @@ class FakePromptRepository : PromptRepository { userId: Int, gatekeeperChallenge: Long?, kind: PromptKind, - requireConfirmation: Boolean, + ) = setPrompt(promptInfo, userId, gatekeeperChallenge, kind, forceConfirmation = false) + + fun setPrompt( + promptInfo: PromptInfo, + userId: Int, + gatekeeperChallenge: Long?, + kind: PromptKind, + forceConfirmation: Boolean = false, ) { _promptInfo.value = promptInfo _userId.value = userId _challenge.value = gatekeeperChallenge _kind.value = kind - _isConfirmationRequired.value = requireConfirmation + _isConfirmationRequired.value = promptInfo.isConfirmationRequested || forceConfirmation } override fun unsetPrompt() { diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index e4a5a3e0ed00..ca15dd79adbc 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -2166,7 +2166,7 @@ public final class GameManagerService extends IGameManagerService.Stub { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { synchronized (mUidObserverLock) { - if (ActivityManager.isProcStateBackground(procState)) { + if (procState != ActivityManager.PROCESS_STATE_TOP) { disableGameMode(uid); return; } diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index 8ef2a1bd26c2..cb5e7f1be571 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -21,7 +21,10 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE; +import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE; +import static com.android.server.biometrics.BiometricSensor.STATE_CANCELING; +import static com.android.server.biometrics.BiometricSensor.STATE_UNKNOWN; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE; @@ -439,6 +442,13 @@ public final class AuthSession implements IBinder.DeathRecipient { return false; } + final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT + || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; + if (errorLockout) { + cancelAllSensors(sensor -> Utils.isAtLeastStrength(sensorIdToStrength(sensorId), + sensor.getCurrentStrength())); + } + mErrorEscrow = error; mVendorCodeEscrow = vendorCode; @@ -477,8 +487,6 @@ public final class AuthSession implements IBinder.DeathRecipient { case STATE_AUTH_STARTED: case STATE_AUTH_STARTED_UI_SHOWING: { - final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT - || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; if (isAllowDeviceCredential() && errorLockout) { // SystemUI handles transition from biometric to device credential. mState = STATE_SHOWING_DEVICE_CREDENTIAL; @@ -675,7 +683,9 @@ public final class AuthSession implements IBinder.DeathRecipient { } private boolean pauseSensorIfSupported(int sensorId) { - if (sensorIdToModality(sensorId) == TYPE_FACE) { + boolean isSensorCancelling = sensorIdToState(sensorId) == STATE_CANCELING; + // If the sensor is locked out, canceling sensors operation is handled in onErrorReceived() + if (sensorIdToModality(sensorId) == TYPE_FACE && !isSensorCancelling) { cancelAllSensors(sensor -> sensor.id == sensorId); return true; } @@ -948,6 +958,27 @@ public final class AuthSession implements IBinder.DeathRecipient { return TYPE_NONE; } + private @BiometricSensor.SensorState int sensorIdToState(int sensorId) { + for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) { + if (sensorId == sensor.id) { + return sensor.getSensorState(); + } + } + Slog.e(TAG, "Unknown sensor: " + sensorId); + return STATE_UNKNOWN; + } + + @BiometricManager.Authenticators.Types + private int sensorIdToStrength(int sensorId) { + for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) { + if (sensorId == sensor.id) { + return sensor.getCurrentStrength(); + } + } + Slog.e(TAG, "Unknown sensor: " + sensorId); + return BIOMETRIC_CONVENIENCE; + } + private String getAcquiredMessageForSensor(int sensorId, int acquiredInfo, int vendorCode) { final @Modality int modality = sensorIdToModality(sensorId); switch (modality) { diff --git a/services/core/java/com/android/server/biometrics/BiometricCameraManager.java b/services/core/java/com/android/server/biometrics/BiometricCameraManager.java new file mode 100644 index 000000000000..058ea6bbb696 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/BiometricCameraManager.java @@ -0,0 +1,32 @@ +/* + * 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.server.biometrics; + +/** + * Interface for biometrics to get camera status. + */ +public interface BiometricCameraManager { + /** + * Returns true if any camera is in use. + */ + boolean isAnyCameraUnavailable(); + + /** + * Returns true if privacy is enabled and camera access is disabled. + */ + boolean isCameraPrivacyEnabled(); +} diff --git a/services/core/java/com/android/server/biometrics/BiometricCameraManagerImpl.java b/services/core/java/com/android/server/biometrics/BiometricCameraManagerImpl.java new file mode 100644 index 000000000000..000ee5446962 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/BiometricCameraManagerImpl.java @@ -0,0 +1,68 @@ +/* + * 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.server.biometrics; + +import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; + +import android.annotation.NonNull; +import android.hardware.SensorPrivacyManager; +import android.hardware.camera2.CameraManager; + +import java.util.concurrent.ConcurrentHashMap; + +public class BiometricCameraManagerImpl implements BiometricCameraManager { + + private final CameraManager mCameraManager; + private final SensorPrivacyManager mSensorPrivacyManager; + private final ConcurrentHashMap<String, Boolean> mIsCameraAvailable = new ConcurrentHashMap<>(); + + private final CameraManager.AvailabilityCallback mCameraAvailabilityCallback = + new CameraManager.AvailabilityCallback() { + @Override + public void onCameraAvailable(@NonNull String cameraId) { + mIsCameraAvailable.put(cameraId, true); + } + + @Override + public void onCameraUnavailable(@NonNull String cameraId) { + mIsCameraAvailable.put(cameraId, false); + } + }; + + public BiometricCameraManagerImpl(@NonNull CameraManager cameraManager, + @NonNull SensorPrivacyManager sensorPrivacyManager) { + mCameraManager = cameraManager; + mSensorPrivacyManager = sensorPrivacyManager; + mCameraManager.registerAvailabilityCallback(mCameraAvailabilityCallback, null); + } + + @Override + public boolean isAnyCameraUnavailable() { + for (String cameraId : mIsCameraAvailable.keySet()) { + if (!mIsCameraAvailable.get(cameraId)) { + return true; + } + } + return false; + } + + @Override + public boolean isCameraPrivacyEnabled() { + return mSensorPrivacyManager != null && mSensorPrivacyManager + .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, CAMERA); + } +} diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 0942d8527565..279aaf9d3253 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -17,6 +17,8 @@ package com.android.server.biometrics; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricManager.Authenticators; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE; @@ -33,6 +35,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; +import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricPrompt; @@ -47,6 +50,7 @@ import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorPropertiesInternal; +import android.hardware.camera2.CameraManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.net.Uri; @@ -124,6 +128,8 @@ public class BiometricService extends SystemService { AuthSession mAuthSession; private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final BiometricCameraManager mBiometricCameraManager; + /** * Tracks authenticatorId invalidation. For more details, see * {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}. @@ -365,7 +371,7 @@ public class BiometricService extends SystemService { public boolean getConfirmationAlwaysRequired(@BiometricAuthenticator.Modality int modality, int userId) { switch (modality) { - case BiometricAuthenticator.TYPE_FACE: + case TYPE_FACE: if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) { onChange(true /* selfChange */, FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, @@ -563,22 +569,6 @@ public class BiometricService extends SystemService { Utils.combineAuthenticatorBundles(promptInfo); - // Set the default title if necessary. - if (promptInfo.isUseDefaultTitle()) { - if (TextUtils.isEmpty(promptInfo.getTitle())) { - promptInfo.setTitle(getContext() - .getString(R.string.biometric_dialog_default_title)); - } - } - - // Set the default subtitle if necessary. - if (promptInfo.isUseDefaultSubtitle()) { - if (TextUtils.isEmpty(promptInfo.getSubtitle())) { - promptInfo.setSubtitle(getContext() - .getString(R.string.biometric_dialog_default_subtitle)); - } - } - final long requestId = mRequestCounter.get(); mHandler.post(() -> handleAuthenticate( token, requestId, operationId, userId, receiver, opPackageName, promptInfo)); @@ -933,7 +923,7 @@ public class BiometricService extends SystemService { return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */, - getContext()); + getContext(), mBiometricCameraManager); } /** @@ -1026,6 +1016,11 @@ public class BiometricService extends SystemService { public UserManager getUserManager(Context context) { return context.getSystemService(UserManager.class); } + + public BiometricCameraManager getBiometricCameraManager(Context context) { + return new BiometricCameraManagerImpl(context.getSystemService(CameraManager.class), + context.getSystemService(SensorPrivacyManager.class)); + } } /** @@ -1054,6 +1049,7 @@ public class BiometricService extends SystemService { mRequestCounter = mInjector.getRequestGenerator(); mBiometricContext = injector.getBiometricContext(context); mUserManager = injector.getUserManager(context); + mBiometricCameraManager = injector.getBiometricCameraManager(context); try { injector.getActivityManagerService().registerUserSwitchObserver( @@ -1290,7 +1286,34 @@ public class BiometricService extends SystemService { final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo, opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(), - getContext()); + getContext(), mBiometricCameraManager); + + // Set the default title if necessary. + if (promptInfo.isUseDefaultTitle()) { + if (TextUtils.isEmpty(promptInfo.getTitle())) { + promptInfo.setTitle(getContext() + .getString(R.string.biometric_dialog_default_title)); + } + } + + final int eligible = preAuthInfo.getEligibleModalities(); + final boolean hasEligibleFingerprintSensor = + (eligible & TYPE_FINGERPRINT) == TYPE_FINGERPRINT; + final boolean hasEligibleFaceSensor = (eligible & TYPE_FACE) == TYPE_FACE; + + // Set the subtitle according to the modality. + if (promptInfo.isUseDefaultSubtitle()) { + if (hasEligibleFingerprintSensor && hasEligibleFaceSensor) { + promptInfo.setSubtitle(getContext() + .getString(R.string.biometric_dialog_default_subtitle)); + } else if (hasEligibleFingerprintSensor) { + promptInfo.setSubtitle(getContext() + .getString(R.string.biometric_dialog_fingerprint_subtitle)); + } else if (hasEligibleFaceSensor) { + promptInfo.setSubtitle(getContext() + .getString(R.string.biometric_dialog_face_subtitle)); + } + } final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus(); @@ -1300,9 +1323,7 @@ public class BiometricService extends SystemService { + promptInfo.isIgnoreEnrollmentState()); // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can // be shown for this case. - if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS - || preAuthStatus.second - == BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED) { + if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) { // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but // CREDENTIAL is requested and available, set the bundle to only request // CREDENTIAL. diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java index 3813fd1971a6..b1740a780539 100644 --- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java +++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java @@ -27,7 +27,6 @@ import android.annotation.NonNull; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustManager; import android.content.Context; -import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.PromptInfo; @@ -73,13 +72,16 @@ class PreAuthInfo { final Context context; private final boolean mBiometricRequested; private final int mBiometricStrengthRequested; + private final BiometricCameraManager mBiometricCameraManager; + private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List<BiometricSensor> eligibleSensors, List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, boolean confirmationRequested, boolean ignoreEnrollmentState, int userId, - Context context) { + Context context, BiometricCameraManager biometricCameraManager) { mBiometricRequested = biometricRequested; mBiometricStrengthRequested = biometricStrengthRequested; + mBiometricCameraManager = biometricCameraManager; this.credentialRequested = credentialRequested; this.eligibleSensors = eligibleSensors; @@ -96,7 +98,8 @@ class PreAuthInfo { BiometricService.SettingObserver settingObserver, List<BiometricSensor> sensors, int userId, PromptInfo promptInfo, String opPackageName, - boolean checkDevicePolicyManager, Context context) + boolean checkDevicePolicyManager, Context context, + BiometricCameraManager biometricCameraManager) throws RemoteException { final boolean confirmationRequested = promptInfo.isConfirmationRequested(); @@ -124,7 +127,7 @@ class PreAuthInfo { checkDevicePolicyManager, requestedStrength, promptInfo.getAllowedSensorIds(), promptInfo.isIgnoreEnrollmentState(), - context); + biometricCameraManager); Slog.d(TAG, "Package: " + opPackageName + " Sensor ID: " + sensor.id @@ -138,7 +141,7 @@ class PreAuthInfo { // // Note: if only a certain sensor is required and the privacy is enabled, // canAuthenticate() will return false. - if (status == AUTHENTICATOR_OK || status == BIOMETRIC_SENSOR_PRIVACY_ENABLED) { + if (status == AUTHENTICATOR_OK) { eligibleSensors.add(sensor); } else { ineligibleSensors.add(new Pair<>(sensor, status)); @@ -148,7 +151,7 @@ class PreAuthInfo { return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested, - promptInfo.isIgnoreEnrollmentState(), userId, context); + promptInfo.isIgnoreEnrollmentState(), userId, context, biometricCameraManager); } /** @@ -165,12 +168,16 @@ class PreAuthInfo { BiometricSensor sensor, int userId, String opPackageName, boolean checkDevicePolicyManager, int requestedStrength, @NonNull List<Integer> requestedSensorIds, - boolean ignoreEnrollmentState, Context context) { + boolean ignoreEnrollmentState, BiometricCameraManager biometricCameraManager) { if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) { return BIOMETRIC_NO_HARDWARE; } + if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) { + return BIOMETRIC_HARDWARE_NOT_DETECTED; + } + final boolean wasStrongEnough = Utils.isAtLeastStrength(sensor.oemStrength, requestedStrength); final boolean isStrongEnough = @@ -191,12 +198,10 @@ class PreAuthInfo { && !ignoreEnrollmentState) { return BIOMETRIC_NOT_ENROLLED; } - final SensorPrivacyManager sensorPrivacyManager = context - .getSystemService(SensorPrivacyManager.class); - if (sensorPrivacyManager != null && sensor.modality == TYPE_FACE) { - if (sensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId)) { + if (biometricCameraManager != null && sensor.modality == TYPE_FACE) { + if (biometricCameraManager.isCameraPrivacyEnabled()) { + //Camera privacy is enabled as the access is disabled return BIOMETRIC_SENSOR_PRIVACY_ENABLED; } } @@ -266,17 +271,30 @@ class PreAuthInfo { } private Pair<BiometricSensor, Integer> calculateErrorByPriority() { - // If the caller requested STRONG, and the device contains both STRONG and non-STRONG - // sensors, prioritize BIOMETRIC_NOT_ENROLLED over the weak sensor's - // BIOMETRIC_INSUFFICIENT_STRENGTH error. Pretty sure we can always prioritize - // BIOMETRIC_NOT_ENROLLED over any other error (unless of course its calculation is - // wrong, in which case we should fix that instead). + Pair<BiometricSensor, Integer> sensorNotEnrolled = null; + Pair<BiometricSensor, Integer> sensorLockout = null; for (Pair<BiometricSensor, Integer> pair : ineligibleSensors) { + int status = pair.second; + if (status == BIOMETRIC_LOCKOUT_TIMED || status == BIOMETRIC_LOCKOUT_PERMANENT) { + sensorLockout = pair; + } if (pair.second == BIOMETRIC_NOT_ENROLLED) { - return pair; + sensorNotEnrolled = pair; } } + // If there is a sensor locked out, prioritize lockout over other sensor's error. + // See b/286923477. + if (sensorLockout != null) { + return sensorLockout; + } + + // If the caller requested STRONG, and the device contains both STRONG and non-STRONG + // sensors, prioritize BIOMETRIC_NOT_ENROLLED over the weak sensor's + // BIOMETRIC_INSUFFICIENT_STRENGTH error. + if (sensorNotEnrolled != null) { + return sensorNotEnrolled; + } return ineligibleSensors.get(0); } @@ -292,13 +310,9 @@ class PreAuthInfo { @AuthenticatorStatus final int status; @BiometricAuthenticator.Modality int modality = TYPE_NONE; - final SensorPrivacyManager sensorPrivacyManager = context - .getSystemService(SensorPrivacyManager.class); - boolean cameraPrivacyEnabled = false; - if (sensorPrivacyManager != null) { - cameraPrivacyEnabled = sensorPrivacyManager - .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId); + if (mBiometricCameraManager != null) { + cameraPrivacyEnabled = mBiometricCameraManager.isCameraPrivacyEnabled(); } if (mBiometricRequested && credentialRequested) { @@ -315,7 +329,7 @@ class PreAuthInfo { // and the face sensor privacy is enabled then return // BIOMETRIC_SENSOR_PRIVACY_ENABLED. // - // Note: This sensor will still be eligible for calls to authenticate. + // Note: This sensor will not be eligible for calls to authenticate. status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; } else { status = AUTHENTICATOR_OK; @@ -340,7 +354,7 @@ class PreAuthInfo { // If the only modality requested is face and the privacy is enabled // then return BIOMETRIC_SENSOR_PRIVACY_ENABLED. // - // Note: This sensor will still be eligible for calls to authenticate. + // Note: This sensor will not be eligible for calls to authenticate. status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; } else { status = AUTHENTICATOR_OK; diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index 46c77e8a82f2..aa6a0f1bb55f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -210,4 +210,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement public boolean isInterruptable() { return true; } + + public boolean isAlreadyCancelled() { + return mAlreadyCancelled; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index 05ca6e4554fb..6ac163121d8c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -266,8 +266,12 @@ public abstract class AuthenticationClient<T, O extends AuthenticateOptions> } } else { if (isBackgroundAuth) { - Slog.e(TAG, "cancelling due to background auth"); - cancel(); + Slog.e(TAG, "Sending cancel to client(Due to background auth)"); + if (mTaskStackListener != null) { + mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); + } + sendCancelOnly(getListener()); + mCallback.onClientFinished(this, false); } else { // Allow system-defined limit of number of attempts before giving up if (mShouldUseLockoutTracker) { diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index 7fa4d6ce4d49..78c38089e803 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -268,6 +268,14 @@ public class BiometricScheduler { return; } + if (mCurrentOperation.isAcquisitionOperation()) { + AcquisitionClient client = (AcquisitionClient) mCurrentOperation.getClientMonitor(); + if (client.isAlreadyCancelled()) { + mCurrentOperation.cancel(mHandler, mInternalCallback); + return; + } + } + if (mGestureAvailabilityDispatcher != null && mCurrentOperation.isAcquisitionOperation()) { mGestureAvailabilityDispatcher.markSensorActive( mCurrentOperation.getSensorId(), true /* active */); diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java index 2e1a363bcc68..1a682a9ffefa 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java @@ -170,6 +170,12 @@ public class ClientMonitorCallbackConverter { } } + public void onUdfpsOverlayShown() throws RemoteException { + if (mFingerprintServiceReceiver != null) { + mFingerprintServiceReceiver.onUdfpsOverlayShown(); + } + } + // Face-specific callbacks for FaceManager only /** diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index 50d375c56f4a..35fc43ae5f74 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -43,7 +43,6 @@ import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.OperationContextExt; import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.AuthenticationClient; -import com.android.server.biometrics.sensors.BiometricNotificationUtils; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; @@ -242,9 +241,6 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession, FaceAut vendorCode, getTargetUserId())); - if (error == BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL) { - BiometricNotificationUtils.showReEnrollmentNotification(getContext()); - } super.onError(error, vendorCode); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index ece35c522ec7..3d6a156d6022 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -929,17 +929,19 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override - public void onUiReady(long requestId, int sensorId) { - super.onUiReady_enforcePermission(); + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event, long requestId, + int sensorId) { + super.onUdfpsUiEvent_enforcePermission(); final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); if (provider == null) { - Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId); + Slog.w(TAG, "No matching provider for onUdfpsUiEvent, sensorId: " + sensorId); return; } - provider.onUiReady(requestId, sensorId); + provider.onUdfpsUiEvent(event, requestId, sensorId); } + @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) { diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index 004af2c2ad62..26701c110c39 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -130,7 +130,7 @@ public interface ServiceProvider extends void onPointerUp(long requestId, int sensorId, PointerContext pc); - void onUiReady(long requestId, int sensorId); + void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event, long requestId, int sensorId); void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java index da7163a2a678..dce0175ca593 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java @@ -17,6 +17,7 @@ package com.android.server.biometrics.sensors.fingerprint; import android.hardware.biometrics.fingerprint.PointerContext; +import android.hardware.fingerprint.FingerprintManager; import com.android.server.biometrics.sensors.BaseClientMonitor; @@ -28,6 +29,6 @@ import com.android.server.biometrics.sensors.BaseClientMonitor; public interface Udfps { void onPointerDown(PointerContext pc); void onPointerUp(PointerContext pc); - void onUiReady(); + void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event); boolean isPointerDown(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java index 135eccf9026a..ec1eeb138505 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java @@ -114,6 +114,11 @@ class BiometricTestSessionImpl extends ITestSession.Stub { public void onUdfpsPointerUp(int sensorId) { } + + @Override + public void onUdfpsOverlayShown() { + + } }; BiometricTestSessionImpl(@NonNull Context context, int sensorId, diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 2bfc2391b948..3fc36b6df92d 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -27,6 +27,7 @@ import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.FingerprintAuthenticateOptions; +import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlay; @@ -363,9 +364,11 @@ class FingerprintAuthenticationClient } @Override - public void onUiReady() { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) { try { - getFreshDaemon().getSession().onUiReady(); + if (event == FingerprintManager.UDFPS_UI_READY) { + getFreshDaemon().getSession().onUiReady(); + } } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index c2ca78e91fe3..d35469c4655c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -265,11 +265,20 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps } @Override - public void onUiReady() { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) { try { - getFreshDaemon().getSession().onUiReady(); + switch (event) { + case FingerprintManager.UDFPS_UI_OVERLAY_SHOWN: + getListener().onUdfpsOverlayShown(); + break; + case FingerprintManager.UDFPS_UI_READY: + getFreshDaemon().getSession().onUiReady(); + break; + default: + Slog.w(TAG, "No matching event for onUdfpsUiEvent"); + } } catch (RemoteException e) { - Slog.e(TAG, "Unable to send UI ready", e); + Slog.e(TAG, "Unable to send onUdfpsUiEvent", e); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 58ece898a9fe..3e33ef63c7d7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -669,14 +669,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public void onUiReady(long requestId, int sensorId) { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event, long requestId, + int sensorId) { mFingerprintSensors.get(sensorId).getScheduler().getCurrentClientIfMatches( requestId, (client) -> { if (!(client instanceof Udfps)) { - Slog.e(getTag(), "onUiReady received during client: " + client); + Slog.e(getTag(), "onUdfpsUiEvent received during client: " + client); return; } - ((Udfps) client).onUiReady(); + ((Udfps) client).onUdfpsUiEvent(event); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java index 86a9f7998398..c20a9eb958c4 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java @@ -115,6 +115,11 @@ public class BiometricTestSessionImpl extends ITestSession.Stub { public void onUdfpsPointerUp(int sensorId) { } + + @Override + public void onUdfpsOverlayShown() { + + } }; BiometricTestSessionImpl(@NonNull Context context, int sensorId, diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 9e6f4e4f13f3..1cbbf89e052a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -829,13 +829,14 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public void onUiReady(long requestId, int sensorId) { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event, long requestId, + int sensorId) { mScheduler.getCurrentClientIfMatches(requestId, (client) -> { if (!(client instanceof Udfps)) { - Slog.w(TAG, "onUiReady received during client: " + client); + Slog.w(TAG, "onUdfpsUiEvent received during client: " + client); return; } - ((Udfps) client).onUiReady(); + ((Udfps) client).onUdfpsUiEvent(event); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java index d22aef8b3971..2a6233824c2e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java @@ -27,6 +27,7 @@ import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; import android.hardware.fingerprint.FingerprintAuthenticateOptions; +import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlay; @@ -273,7 +274,7 @@ class FingerprintAuthenticationClient } @Override - public void onUiReady() { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) { // Unsupported in HIDL. } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java index 362c820b9e8d..ed0a2015a461 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java @@ -25,6 +25,7 @@ import android.hardware.biometrics.BiometricOverlayConstants; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; import android.hardware.fingerprint.FingerprintAuthenticateOptions; +import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IUdfpsOverlay; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; @@ -130,7 +131,7 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint> } @Override - public void onUiReady() { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) { // Unsupported in HIDL. } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java index 78039ef99986..c2b7944eac35 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java @@ -186,7 +186,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint } @Override - public void onUiReady() { + public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) { // Unsupported in HIDL. } } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index e85eee817d29..e3262cfbd30b 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -22,7 +22,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; @@ -280,15 +279,22 @@ public class Vpn { private static final int VPN_DEFAULT_SCORE = 101; /** - * The reset session timer for data stall. If a session has not successfully revalidated after - * the delay, the session will be torn down and restarted in an attempt to recover. Delay + * The recovery timer for data stall. If a session has not successfully revalidated after + * the delay, the session will perform MOBIKE or be restarted in an attempt to recover. Delay * counter is reset on successful validation only. * + * <p>The first {@code MOBIKE_RECOVERY_ATTEMPT} timers are used for performing MOBIKE. + * System will perform session reset for the remaining timers. * <p>If retries have exceeded the length of this array, the last entry in the array will be * used as a repeating interval. */ - private static final long[] DATA_STALL_RESET_DELAYS_SEC = {30L, 60L, 120L, 240L, 480L, 960L}; - + // TODO: use ms instead to speed up the test. + private static final long[] DATA_STALL_RECOVERY_DELAYS_SEC = + {1L, 5L, 30L, 60L, 120L, 240L, 480L, 960L}; + /** + * Maximum attempts to perform MOBIKE when the network is bad. + */ + private static final int MAX_MOBIKE_RECOVERY_ATTEMPT = 2; /** * The initial token value of IKE session. */ @@ -380,6 +386,7 @@ public class Vpn { private final INetworkManagementService mNms; private final INetd mNetd; @VisibleForTesting + @GuardedBy("this") protected VpnConfig mConfig; private final NetworkProvider mNetworkProvider; @VisibleForTesting @@ -392,7 +399,6 @@ public class Vpn { private final UserManager mUserManager; private final VpnProfileStore mVpnProfileStore; - protected boolean mDataStallSuspected = false; @VisibleForTesting VpnProfileStore getVpnProfileStore() { @@ -685,14 +691,14 @@ public class Vpn { } /** - * Get the length of time to wait before resetting the ike session when a data stall is - * suspected. + * Get the length of time to wait before perform data stall recovery when the validation + * result is bad. */ - public long getDataStallResetSessionSeconds(int count) { - if (count >= DATA_STALL_RESET_DELAYS_SEC.length) { - return DATA_STALL_RESET_DELAYS_SEC[DATA_STALL_RESET_DELAYS_SEC.length - 1]; + public long getValidationFailRecoverySeconds(int count) { + if (count >= DATA_STALL_RECOVERY_DELAYS_SEC.length) { + return DATA_STALL_RECOVERY_DELAYS_SEC[DATA_STALL_RECOVERY_DELAYS_SEC.length - 1]; } else { - return DATA_STALL_RESET_DELAYS_SEC[count]; + return DATA_STALL_RECOVERY_DELAYS_SEC[count]; } } @@ -1598,6 +1604,8 @@ public class Vpn { return network; } + // TODO : this is not synchronized(this) but reads from mConfig, which is dangerous + // This file makes an effort to avoid partly initializing mConfig, but this is still not great private LinkProperties makeLinkProperties() { // The design of disabling IPv6 is only enabled for IKEv2 VPN because it needs additional // logic to handle IPv6 only VPN, and the IPv6 only VPN may be restarted when its MTU @@ -1679,6 +1687,7 @@ public class Vpn { * registering a new NetworkAgent. This is not always possible if the new VPN configuration * has certain changes, in which case this method would just return {@code false}. */ + // TODO : this method is not synchronized(this) but reads from mConfig private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) { // NetworkAgentConfig cannot be updated without registering a new NetworkAgent. // Strictly speaking, bypassability is affected by lockdown and therefore it's possible @@ -2269,7 +2278,12 @@ public class Vpn { */ public synchronized VpnConfig getVpnConfig() { enforceControlPermission(); - return mConfig; + // Constructor of VpnConfig cannot take a null parameter. Return null directly if mConfig is + // null + if (mConfig == null) return null; + // mConfig is guarded by "this" and can be modified by another thread as soon as + // this method returns, so this method must return a copy. + return new VpnConfig(mConfig); } @Deprecated @@ -2315,6 +2329,7 @@ public class Vpn { } }; + @GuardedBy("this") private void cleanupVpnStateLocked() { mStatusIntent = null; resetNetworkCapabilities(); @@ -2837,9 +2852,7 @@ public class Vpn { } final boolean isLegacyVpn = mVpnRunner instanceof LegacyVpnRunner; - mVpnRunner.exit(); - mVpnRunner = null; // LegacyVpn uses daemons that must be shut down before new ones are brought up. // The same limitation does not apply to Platform VPNs. @@ -3044,7 +3057,6 @@ public class Vpn { @Nullable private IkeSessionWrapper mSession; @Nullable private IkeSessionConnectionInfo mIkeConnectionInfo; - @Nullable private VpnConnectivityDiagnosticsCallback mDiagnosticsCallback; // mMobikeEnabled can only be updated after IKE AUTH is finished. private boolean mMobikeEnabled = false; @@ -3055,7 +3067,7 @@ public class Vpn { * <p>This variable controls the retry delay, and is reset when the VPN pass network * validation. */ - private int mDataStallRetryCount = 0; + private int mValidationFailRetryCount = 0; /** * The number of attempts since the last successful connection. @@ -3084,6 +3096,7 @@ public class Vpn { } }; + // GuardedBy("Vpn.this") (annotation can't be applied to constructor) IkeV2VpnRunner( @NonNull Ikev2VpnProfile profile, @NonNull ScheduledThreadPoolExecutor executor) { super(TAG); @@ -3136,15 +3149,6 @@ public class Vpn { mConnectivityManager.registerSystemDefaultNetworkCallback(mNetworkCallback, new Handler(mLooper)); } - - // DiagnosticsCallback may return more than one alive VPNs, but VPN will filter based on - // Network object. - final NetworkRequest diagRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_VPN) - .removeCapability(NET_CAPABILITY_NOT_VPN).build(); - mDiagnosticsCallback = new VpnConnectivityDiagnosticsCallback(); - mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback( - diagRequest, mExecutor, mDiagnosticsCallback); } private boolean isActiveNetwork(@Nullable Network network) { @@ -3710,11 +3714,14 @@ public class Vpn { } public void updateVpnTransportInfoAndNetCap(int keepaliveDelaySec) { - final VpnTransportInfo info = new VpnTransportInfo( - getActiveVpnType(), - mConfig.session, - mConfig.allowBypass && !mLockdown, - areLongLivedTcpConnectionsExpensive(keepaliveDelaySec)); + final VpnTransportInfo info; + synchronized (Vpn.this) { + info = new VpnTransportInfo( + getActiveVpnType(), + mConfig.session, + mConfig.allowBypass && !mLockdown, + areLongLivedTcpConnectionsExpensive(keepaliveDelaySec)); + } final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo()); if (ncUpdateRequired) { mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) @@ -3875,39 +3882,12 @@ public class Vpn { } } - class VpnConnectivityDiagnosticsCallback - extends ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback { - // The callback runs in the executor thread. - @Override - public void onDataStallSuspected( - ConnectivityDiagnosticsManager.DataStallReport report) { - synchronized (Vpn.this) { - // Ignore stale runner. - if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return; - - // Handle the report only for current VPN network. If data stall is already - // reported, ignoring the other reports. It means that the stall is not - // recovered by MOBIKE and should be on the way to reset the ike session. - if (mNetworkAgent != null - && mNetworkAgent.getNetwork().equals(report.getNetwork()) - && !mDataStallSuspected) { - Log.d(TAG, "Data stall suspected"); - - // Trigger MOBIKE. - maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); - mDataStallSuspected = true; - } - } - } - } - public void onValidationStatus(int status) { mEventChanges.log("[Validation] validation status " + status); if (status == NetworkAgent.VALIDATION_STATUS_VALID) { // No data stall now. Reset it. mExecutor.execute(() -> { - mDataStallSuspected = false; - mDataStallRetryCount = 0; + mValidationFailRetryCount = 0; if (mScheduledHandleDataStallFuture != null) { Log.d(TAG, "Recovered from stall. Cancel pending reset action."); mScheduledHandleDataStallFuture.cancel(false /* mayInterruptIfRunning */); @@ -3918,8 +3898,21 @@ public class Vpn { // Skip other invalid status if the scheduled recovery exists. if (mScheduledHandleDataStallFuture != null) return; + if (mValidationFailRetryCount < MAX_MOBIKE_RECOVERY_ATTEMPT) { + Log.d(TAG, "Validation failed"); + + // Trigger MOBIKE to recover first. + mExecutor.schedule(() -> { + maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); + }, mDeps.getValidationFailRecoverySeconds(mValidationFailRetryCount++), + TimeUnit.SECONDS); + return; + } + + // Data stall is not recovered by MOBIKE. Try to reset session to recover it. mScheduledHandleDataStallFuture = mExecutor.schedule(() -> { - if (mDataStallSuspected) { + // Only perform the recovery when the network is still bad. + if (mValidationFailRetryCount > 0) { Log.d(TAG, "Reset session to recover stalled network"); // This will reset old state if it exists. startIkeSession(mActiveNetwork); @@ -3928,7 +3921,9 @@ public class Vpn { // Reset mScheduledHandleDataStallFuture since it's already run on executor // thread. mScheduledHandleDataStallFuture = null; - }, mDeps.getDataStallResetSessionSeconds(mDataStallRetryCount++), TimeUnit.SECONDS); + // TODO: compute the delay based on the last recovery timestamp + }, mDeps.getValidationFailRecoverySeconds(mValidationFailRetryCount++), + TimeUnit.SECONDS); } } @@ -4220,7 +4215,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ private void disconnectVpnRunner() { - mEventChanges.log("[VPNRunner] Disconnect runner, underlying network" + mActiveNetwork); + mEventChanges.log("[VPNRunner] Disconnect runner, underlying net " + mActiveNetwork); mActiveNetwork = null; mUnderlyingNetworkCapabilities = null; mUnderlyingLinkProperties = null; @@ -4231,8 +4226,6 @@ public class Vpn { mCarrierConfigManager.unregisterCarrierConfigChangeListener( mCarrierConfigChangeListener); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); - mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback( - mDiagnosticsCallback); clearVpnNetworkPreference(mSessionKey); mExecutor.shutdown(); @@ -4293,6 +4286,7 @@ public class Vpn { } }; + // GuardedBy("Vpn.this") (annotation can't be applied to constructor) LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { super(TAG); if (racoon == null && mtpd == null) { @@ -4500,46 +4494,46 @@ public class Vpn { } // Set the interface and the addresses in the config. - mConfig.interfaze = parameters[0].trim(); + synchronized (Vpn.this) { + mConfig.interfaze = parameters[0].trim(); - mConfig.addLegacyAddresses(parameters[1]); - // Set the routes if they are not set in the config. - if (mConfig.routes == null || mConfig.routes.isEmpty()) { - mConfig.addLegacyRoutes(parameters[2]); - } + mConfig.addLegacyAddresses(parameters[1]); + // Set the routes if they are not set in the config. + if (mConfig.routes == null || mConfig.routes.isEmpty()) { + mConfig.addLegacyRoutes(parameters[2]); + } - // Set the DNS servers if they are not set in the config. - if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { - String dnsServers = parameters[3].trim(); - if (!dnsServers.isEmpty()) { - mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); + // Set the DNS servers if they are not set in the config. + if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { + String dnsServers = parameters[3].trim(); + if (!dnsServers.isEmpty()) { + mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); + } } - } - // Set the search domains if they are not set in the config. - if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { - String searchDomains = parameters[4].trim(); - if (!searchDomains.isEmpty()) { - mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); + // Set the search domains if they are not set in the config. + if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { + String searchDomains = parameters[4].trim(); + if (!searchDomains.isEmpty()) { + mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); + } } - } - // Add a throw route for the VPN server endpoint, if one was specified. - if (endpointAddress instanceof Inet4Address) { - mConfig.routes.add(new RouteInfo( - new IpPrefix(endpointAddress, 32), null /*gateway*/, - null /*iface*/, RTN_THROW)); - } else if (endpointAddress instanceof Inet6Address) { - mConfig.routes.add(new RouteInfo( - new IpPrefix(endpointAddress, 128), null /*gateway*/, - null /*iface*/, RTN_THROW)); - } else { - Log.e(TAG, "Unknown IP address family for VPN endpoint: " - + endpointAddress); - } + // Add a throw route for the VPN server endpoint, if one was specified. + if (endpointAddress instanceof Inet4Address) { + mConfig.routes.add(new RouteInfo( + new IpPrefix(endpointAddress, 32), null /*gateway*/, + null /*iface*/, RTN_THROW)); + } else if (endpointAddress instanceof Inet6Address) { + mConfig.routes.add(new RouteInfo( + new IpPrefix(endpointAddress, 128), null /*gateway*/, + null /*iface*/, RTN_THROW)); + } else { + Log.e(TAG, "Unknown IP address family for VPN endpoint: " + + endpointAddress); + } - // Here is the last step and it must be done synchronously. - synchronized (Vpn.this) { + // Here is the last step and it must be done synchronously. // Set the start time mConfig.startTime = SystemClock.elapsedRealtime(); @@ -4773,25 +4767,26 @@ public class Vpn { try { // Build basic config - mConfig = new VpnConfig(); + final VpnConfig config = new VpnConfig(); if (VpnConfig.LEGACY_VPN.equals(packageName)) { - mConfig.legacy = true; - mConfig.session = profile.name; - mConfig.user = profile.key; + config.legacy = true; + config.session = profile.name; + config.user = profile.key; // TODO: Add support for configuring meteredness via Settings. Until then, use a // safe default. - mConfig.isMetered = true; + config.isMetered = true; } else { - mConfig.user = packageName; - mConfig.isMetered = profile.isMetered; + config.user = packageName; + config.isMetered = profile.isMetered; } - mConfig.startTime = SystemClock.elapsedRealtime(); - mConfig.proxyInfo = profile.proxy; - mConfig.requiresInternetValidation = profile.requiresInternetValidation; - mConfig.excludeLocalRoutes = profile.excludeLocalRoutes; - mConfig.allowBypass = profile.isBypassable; - mConfig.disallowedApplications = getAppExclusionList(mPackage); + config.startTime = SystemClock.elapsedRealtime(); + config.proxyInfo = profile.proxy; + config.requiresInternetValidation = profile.requiresInternetValidation; + config.excludeLocalRoutes = profile.excludeLocalRoutes; + config.allowBypass = profile.isBypassable; + config.disallowedApplications = getAppExclusionList(mPackage); + mConfig = config; switch (profile.type) { case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: @@ -4805,6 +4800,7 @@ public class Vpn { mVpnRunner.start(); break; default: + mConfig = null; updateState(DetailedState.FAILED, "Invalid platform VPN type"); Log.d(TAG, "Unknown VPN profile type: " + profile.type); break; @@ -5216,7 +5212,7 @@ public class Vpn { pw.println("MOBIKE " + (runner.mMobikeEnabled ? "enabled" : "disabled")); pw.println("Profile: " + runner.mProfile); pw.println("Token: " + runner.mCurrentToken); - if (mDataStallSuspected) pw.println("Data stall suspected"); + pw.println("Validation failed retry count:" + runner.mValidationFailRetryCount); if (runner.mScheduledHandleDataStallFuture != null) { pw.println("Reset session scheduled"); } diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 75709fbb365a..d647757442e0 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -223,11 +223,11 @@ public class AutomaticBrightnessController { private final ShortTermModel mShortTermModel; private final ShortTermModel mPausedShortTermModel; - // Controls High Brightness Mode. - private HighBrightnessModeController mHbmController; + // Controls Brightness range (including High Brightness Mode). + private final BrightnessRangeController mBrightnessRangeController; // Throttles (caps) maximum allowed brightness - private BrightnessThrottler mBrightnessThrottler; + private final BrightnessThrottler mBrightnessThrottler; private boolean mIsBrightnessThrottled; // Context-sensitive brightness configurations require keeping track of the foreground app's @@ -257,7 +257,8 @@ public class AutomaticBrightnessController { HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, - HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler, + BrightnessRangeController brightnessModeController, + BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userBrightness) { this(new Injector(), callbacks, looper, sensorManager, lightSensor, @@ -267,7 +268,7 @@ public class AutomaticBrightnessController { darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context, - hbmController, brightnessThrottler, idleModeBrightnessMapper, + brightnessModeController, brightnessThrottler, idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong, userLux, userBrightness ); } @@ -283,7 +284,8 @@ public class AutomaticBrightnessController { HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, - HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler, + BrightnessRangeController brightnessModeController, + BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userBrightness) { mInjector = injector; @@ -326,7 +328,7 @@ public class AutomaticBrightnessController { mPendingForegroundAppPackageName = null; mForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED; mPendingForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED; - mHbmController = hbmController; + mBrightnessRangeController = brightnessModeController; mBrightnessThrottler = brightnessThrottler; mInteractiveModeBrightnessMapper = interactiveModeBrightnessMapper; mIdleModeBrightnessMapper = idleModeBrightnessMapper; @@ -607,10 +609,11 @@ public class AutomaticBrightnessController { pw.println(); pw.println(" mInteractiveMapper="); - mInteractiveModeBrightnessMapper.dump(pw, mHbmController.getNormalBrightnessMax()); + mInteractiveModeBrightnessMapper.dump(pw, + mBrightnessRangeController.getNormalBrightnessMax()); if (mIdleModeBrightnessMapper != null) { pw.println(" mIdleMapper="); - mIdleModeBrightnessMapper.dump(pw, mHbmController.getNormalBrightnessMax()); + mIdleModeBrightnessMapper.dump(pw, mBrightnessRangeController.getNormalBrightnessMax()); } pw.println(); @@ -736,7 +739,7 @@ public class AutomaticBrightnessController { mAmbientDarkeningThreshold = mAmbientBrightnessThresholds.getDarkeningThreshold(lux); } - mHbmController.onAmbientLuxChange(mAmbientLux); + mBrightnessRangeController.onAmbientLuxChange(mAmbientLux); // If the short term model was invalidated and the change is drastic enough, reset it. @@ -976,9 +979,9 @@ public class AutomaticBrightnessController { // Clamps values with float range [0.0-1.0] private float clampScreenBrightness(float value) { - final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(), + final float minBrightness = Math.min(mBrightnessRangeController.getCurrentBrightnessMin(), mBrightnessThrottler.getBrightnessCap()); - final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(), + final float maxBrightness = Math.min(mBrightnessRangeController.getCurrentBrightnessMax(), mBrightnessThrottler.getBrightnessCap()); return MathUtils.constrain(value, minBrightness, maxBrightness); } diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java new file mode 100644 index 000000000000..00564963fac3 --- /dev/null +++ b/services/core/java/com/android/server/display/BrightnessRangeController.java @@ -0,0 +1,127 @@ +/* + * 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.server.display; + +import android.hardware.display.BrightnessInfo; +import android.os.IBinder; + +import java.io.PrintWriter; +import java.util.function.BooleanSupplier; + +class BrightnessRangeController { + + private static final boolean NBM_FEATURE_FLAG = false; + + private final HighBrightnessModeController mHbmController; + private final NormalBrightnessModeController mNormalBrightnessModeController = + new NormalBrightnessModeController(); + + private final Runnable mModeChangeCallback; + + BrightnessRangeController(HighBrightnessModeController hbmController, + Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig) { + mHbmController = hbmController; + mModeChangeCallback = modeChangeCallback; + mNormalBrightnessModeController.resetNbmData(displayDeviceConfig.getLuxThrottlingData()); + } + + + void dump(PrintWriter pw) { + mHbmController.dump(pw); + } + + void onAmbientLuxChange(float ambientLux) { + applyChanges( + () -> mNormalBrightnessModeController.onAmbientLuxChange(ambientLux), + () -> mHbmController.onAmbientLuxChange(ambientLux) + ); + } + + float getNormalBrightnessMax() { + return mHbmController.getNormalBrightnessMax(); + } + + void loadFromConfig(HighBrightnessModeMetadata hbmMetadata, IBinder token, + DisplayDeviceInfo info, DisplayDeviceConfig displayDeviceConfig) { + applyChanges( + () -> mNormalBrightnessModeController.resetNbmData( + displayDeviceConfig.getLuxThrottlingData()), + () -> { + mHbmController.setHighBrightnessModeMetadata(hbmMetadata); + mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId, + displayDeviceConfig.getHighBrightnessModeData(), + displayDeviceConfig::getHdrBrightnessFromSdr); + } + ); + } + + void stop() { + mHbmController.stop(); + } + + void setAutoBrightnessEnabled(int state) { + applyChanges( + () -> mNormalBrightnessModeController.setAutoBrightnessState(state), + () -> mHbmController.setAutoBrightnessEnabled(state) + ); + } + + void onBrightnessChanged(float brightness, float unthrottledBrightness, + @BrightnessInfo.BrightnessMaxReason int throttlingReason) { + mHbmController.onBrightnessChanged(brightness, unthrottledBrightness, throttlingReason); + } + + float getCurrentBrightnessMin() { + return mHbmController.getCurrentBrightnessMin(); + } + + + float getCurrentBrightnessMax() { + if (NBM_FEATURE_FLAG && mHbmController.getHighBrightnessMode() + == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF) { + return Math.min(mHbmController.getCurrentBrightnessMax(), + mNormalBrightnessModeController.getCurrentBrightnessMax()); + } + return mHbmController.getCurrentBrightnessMax(); + } + + int getHighBrightnessMode() { + return mHbmController.getHighBrightnessMode(); + } + + float getHdrBrightnessValue() { + return mHbmController.getHdrBrightnessValue(); + } + + float getTransitionPoint() { + return mHbmController.getTransitionPoint(); + } + + private void applyChanges(BooleanSupplier nbmChangesFunc, Runnable hbmChangesFunc) { + if (NBM_FEATURE_FLAG) { + boolean nbmTransitionChanged = nbmChangesFunc.getAsBoolean(); + hbmChangesFunc.run(); + // if nbm transition changed - trigger callback + // HighBrightnessModeController handles sending changes itself + if (nbmTransitionChanged) { + mModeChangeCallback.run(); + } + } else { + hbmChangesFunc.run(); + } + } +} diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 7a797dd2250c..7ccfb448cf61 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -41,6 +41,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.display.BrightnessSynchronizer; import com.android.server.display.config.AutoBrightness; import com.android.server.display.config.BlockingZoneConfig; +import com.android.server.display.config.BrightnessLimitMap; import com.android.server.display.config.BrightnessThresholds; import com.android.server.display.config.BrightnessThrottlingMap; import com.android.server.display.config.BrightnessThrottlingPoint; @@ -51,8 +52,11 @@ import com.android.server.display.config.DisplayQuirks; import com.android.server.display.config.HbmTiming; import com.android.server.display.config.HighBrightnessMode; import com.android.server.display.config.IntegerArray; +import com.android.server.display.config.LuxThrottling; import com.android.server.display.config.NitsMap; +import com.android.server.display.config.NonNegativeFloatToFloatPoint; import com.android.server.display.config.Point; +import com.android.server.display.config.PredefinedBrightnessLimitNames; import com.android.server.display.config.RefreshRateConfigs; import com.android.server.display.config.RefreshRateRange; import com.android.server.display.config.RefreshRateThrottlingMap; @@ -219,6 +223,22 @@ import javax.xml.datatype.DatatypeConfigurationException; * <allowInLowPowerMode>false</allowInLowPowerMode> * </highBrightnessMode> * + * <luxThrottling> + * <brightnessLimitMap> + * <type>default</type> + * <map> + * <point> + * <first>5000</first> + * <second>0.3</second> + * </point> + * <point> + * <first>5000</first> + * <second>0.3</second> + * </point> + * </map> + * </brightnessPeakMap> + * </luxThrottling> + * * <quirks> * <quirk>canSetBrightnessViaHwc</quirk> * </quirks> @@ -693,6 +713,9 @@ public class DisplayDeviceConfig { private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>> mRefreshRateThrottlingMap = new HashMap<>(); + private final Map<BrightnessLimitMapType, Map<Float, Float>> + mLuxThrottlingData = new HashMap<>(); + @Nullable private HostUsiVersion mHostUsiVersion; @@ -1344,6 +1367,11 @@ public class DisplayDeviceConfig { return hbmData; } + @NonNull + public Map<BrightnessLimitMapType, Map<Float, Float>> getLuxThrottlingData() { + return mLuxThrottlingData; + } + public List<RefreshRateLimitation> getRefreshRateLimitations() { return mRefreshRateLimitations; } @@ -1530,6 +1558,7 @@ public class DisplayDeviceConfig { + ", mBrightnessDefault=" + mBrightnessDefault + ", mQuirks=" + mQuirks + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled + + ", mLuxThrottlingData=" + mLuxThrottlingData + ", mHbmData=" + mHbmData + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline + ", mThermalBrightnessThrottlingDataMapByThrottlingId=" @@ -1676,6 +1705,7 @@ public class DisplayDeviceConfig { loadBrightnessMap(config); loadThermalThrottlingConfig(config); loadHighBrightnessModeData(config); + loadLuxThrottling(config); loadQuirks(config); loadBrightnessRamps(config); loadAmbientLightSensorFromDdc(config); @@ -2428,6 +2458,54 @@ public class DisplayDeviceConfig { } } + private void loadLuxThrottling(DisplayConfiguration config) { + LuxThrottling cfg = config.getLuxThrottling(); + if (cfg != null) { + HighBrightnessMode hbm = config.getHighBrightnessMode(); + float hbmTransitionPoint = hbm != null ? hbm.getTransitionPoint_all().floatValue() + : PowerManager.BRIGHTNESS_MAX; + List<BrightnessLimitMap> limitMaps = cfg.getBrightnessLimitMap(); + for (BrightnessLimitMap map : limitMaps) { + PredefinedBrightnessLimitNames type = map.getType(); + BrightnessLimitMapType mappedType = BrightnessLimitMapType.convert(type); + if (mappedType == null) { + Slog.wtf(TAG, "Invalid NBM config: unsupported map type=" + type); + continue; + } + if (mLuxThrottlingData.containsKey(mappedType)) { + Slog.wtf(TAG, "Invalid NBM config: duplicate map type=" + mappedType); + continue; + } + Map<Float, Float> luxToTransitionPointMap = new HashMap<>(); + + List<NonNegativeFloatToFloatPoint> points = map.getMap().getPoint(); + for (NonNegativeFloatToFloatPoint point : points) { + float lux = point.getFirst().floatValue(); + float maxBrightness = point.getSecond().floatValue(); + if (maxBrightness > hbmTransitionPoint) { + Slog.wtf(TAG, + "Invalid NBM config: maxBrightness is greater than hbm" + + ".transitionPoint. type=" + + type + "; lux=" + lux + "; maxBrightness=" + + maxBrightness); + continue; + } + if (luxToTransitionPointMap.containsKey(lux)) { + Slog.wtf(TAG, + "Invalid NBM config: duplicate lux key. type=" + type + "; lux=" + + lux); + continue; + } + luxToTransitionPointMap.put(lux, + mBacklightToBrightnessSpline.interpolate(maxBrightness)); + } + if (!luxToTransitionPointMap.isEmpty()) { + mLuxThrottlingData.put(mappedType, luxToTransitionPointMap); + } + } + } + } + private void loadBrightnessRamps(DisplayConfiguration config) { // Priority 1: Value in the display device config (float) // Priority 2: Value in the config.xml (int) @@ -3155,4 +3233,19 @@ public class DisplayDeviceConfig { } } } + + public enum BrightnessLimitMapType { + DEFAULT, ADAPTIVE; + + @Nullable + private static BrightnessLimitMapType convert(PredefinedBrightnessLimitNames type) { + switch (type) { + case _default: + return DEFAULT; + case adaptive: + return ADAPTIVE; + } + return null; + } + } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 9d31572c7d76..92f6d45fae66 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -445,7 +445,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private final ColorDisplayServiceInternal mCdsi; private float[] mNitsRange; - private final HighBrightnessModeController mHbmController; + private final BrightnessRangeController mBrightnessRangeController; private final HighBrightnessModeMetadata mHighBrightnessModeMetadata; private final BrightnessThrottler mBrightnessThrottler; @@ -654,8 +654,19 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadBrightnessRampRates(); mSkipScreenOnBrightnessRamp = resources.getBoolean( com.android.internal.R.bool.config_skipScreenOnBrightnessRamp); + Runnable modeChangeCallback = () -> { + sendUpdatePowerState(); + postBrightnessChangeRunnable(); + // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern. + if (mAutomaticBrightnessController != null) { + mAutomaticBrightnessController.update(); + } + }; - mHbmController = createHbmControllerLocked(); + HighBrightnessModeController hbmController = createHbmControllerLocked(modeChangeCallback); + + mBrightnessRangeController = new BrightnessRangeController(hbmController, + modeChangeCallback, mDisplayDeviceConfig); mBrightnessThrottler = createBrightnessThrottlerLocked(); @@ -802,7 +813,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) { - mHbmController.onAmbientLuxChange(ambientLux); + mBrightnessRangeController.onAmbientLuxChange(ambientLux); if (nits < 0) { mBrightnessToFollow = leadDisplayBrightness; } else { @@ -1039,17 +1050,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBrightnessRampIncreaseMaxTimeMillis, mBrightnessRampDecreaseMaxTimeMillis); } - mHbmController.setHighBrightnessModeMetadata(hbmMetadata); - mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId, - mDisplayDeviceConfig.getHighBrightnessModeData(), - new HighBrightnessModeController.HdrBrightnessDeviceConfig() { - @Override - public float getHdrBrightnessFromSdr( - float sdrBrightness, float maxDesiredHdrSdrRatio) { - return mDisplayDeviceConfig.getHdrBrightnessFromSdr( - sdrBrightness, maxDesiredHdrSdrRatio); - } - }); + mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig); mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(), mThermalBrightnessThrottlingDataId, mUniqueDisplayId); @@ -1264,7 +1265,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext, - mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper, + mBrightnessRangeController, mBrightnessThrottler, mIdleModeBrightnessMapper, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness); @@ -1364,7 +1365,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call /** Clean up all resources that are accessed via the {@link #mHandler} thread. */ private void cleanupHandlerThreadAfterStop() { setProximitySensorEnabled(false); - mHbmController.stop(); + mBrightnessRangeController.stop(); mBrightnessThrottler.stop(); mHandler.removeCallbacksAndMessages(null); @@ -1647,7 +1648,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mShouldResetShortTermModel); mShouldResetShortTermModel = false; } - mHbmController.setAutoBrightnessEnabled(mUseAutoBrightness + mBrightnessRangeController.setAutoBrightnessEnabled(mUseAutoBrightness ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED); @@ -1820,7 +1821,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // here instead of having HbmController listen to the brightness setting because certain // brightness sources (such as an app override) are not saved to the setting, but should be // reflected in HBM calculations. - mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState, + mBrightnessRangeController.onBrightnessChanged(brightnessState, unthrottledBrightnessState, mBrightnessThrottler.getBrightnessMaxReason()); // Animate the screen brightness when the screen is on or dozing. @@ -1874,13 +1875,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call float sdrAnimateValue = animateValue; // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be // done in HighBrightnessModeController. - if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR + if (mBrightnessRangeController.getHighBrightnessMode() + == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0 && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER) == 0) { // We want to scale HDR brightness level with the SDR level, we also need to restore // SDR brightness immediately when entering dim or low power mode. - animateValue = mHbmController.getHdrBrightnessValue(); + animateValue = mBrightnessRangeController.getHdrBrightnessValue(); } final float currentBrightness = mPowerState.getScreenBrightness(); @@ -1942,8 +1944,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mTempBrightnessEvent.setBrightness(brightnessState); mTempBrightnessEvent.setPhysicalDisplayId(mUniqueDisplayId); mTempBrightnessEvent.setReason(mBrightnessReason); - mTempBrightnessEvent.setHbmMax(mHbmController.getCurrentBrightnessMax()); - mTempBrightnessEvent.setHbmMode(mHbmController.getHighBrightnessMode()); + mTempBrightnessEvent.setHbmMax(mBrightnessRangeController.getCurrentBrightnessMax()); + mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode()); mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags() | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0) | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0)); @@ -2104,9 +2106,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) { synchronized (mCachedBrightnessInfo) { - final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(), + final float minBrightness = Math.min( + mBrightnessRangeController.getCurrentBrightnessMin(), mBrightnessThrottler.getBrightnessCap()); - final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(), + final float maxBrightness = Math.min( + mBrightnessRangeController.getCurrentBrightnessMax(), mBrightnessThrottler.getBrightnessCap()); boolean changed = false; @@ -2124,10 +2128,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call maxBrightness); changed |= mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode, - mHbmController.getHighBrightnessMode()); + mBrightnessRangeController.getHighBrightnessMode()); changed |= mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint, - mHbmController.getTransitionPoint()); + mBrightnessRangeController.getTransitionPoint()); changed |= mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason, mBrightnessThrottler.getBrightnessMaxReason()); @@ -2137,10 +2141,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } void postBrightnessChangeRunnable() { - mHandler.post(mOnBrightnessChangeRunnable); + if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) { + mHandler.post(mOnBrightnessChangeRunnable); + } } - private HighBrightnessModeController createHbmControllerLocked() { + private HighBrightnessModeController createHbmControllerLocked( + Runnable modeChangeCallback) { final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); final IBinder displayToken = @@ -2159,15 +2166,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return mDisplayDeviceConfig.getHdrBrightnessFromSdr( sdrBrightness, maxDesiredHdrSdrRatio); } - }, - () -> { - sendUpdatePowerState(); - postBrightnessChangeRunnable(); - // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern. - if (mAutomaticBrightnessController != null) { - mAutomaticBrightnessController.update(); - } - }, mHighBrightnessModeMetadata, mContext); + }, modeChangeCallback, mHighBrightnessModeMetadata, mContext); } private BrightnessThrottler createBrightnessThrottlerLocked() { @@ -2328,8 +2327,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (Float.isNaN(value)) { value = PowerManager.BRIGHTNESS_MIN; } - return MathUtils.constrain(value, - mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax()); + return MathUtils.constrain(value, mBrightnessRangeController.getCurrentBrightnessMin(), + mBrightnessRangeController.getCurrentBrightnessMax()); } // Checks whether the brightness is within the valid brightness range, not including off. @@ -3003,8 +3002,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mScreenOffBrightnessSensorController.dump(pw); } - if (mHbmController != null) { - mHbmController.dump(pw); + if (mBrightnessRangeController != null) { + mBrightnessRangeController.dump(pw); } if (mBrightnessThrottler != null) { @@ -3471,7 +3470,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, - HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler, + BrightnessRangeController brightnessRangeController, + BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userBrightness) { return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor, @@ -3480,9 +3480,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call brighteningLightDebounceConfig, darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, - screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler, - idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong, - userLux, userBrightness); + screenBrightnessThresholdsIdle, context, brightnessRangeController, + brightnessThrottler, idleModeBrightnessMapper, ambientLightHorizonShort, + ambientLightHorizonLong, userLux, userBrightness); } BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index 41e4671df1a7..e26be6851099 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -376,8 +376,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal private final ColorDisplayServiceInternal mCdsi; private float[] mNitsRange; - private final HighBrightnessModeController mHbmController; - private final HighBrightnessModeMetadata mHighBrightnessModeMetadata; + private final BrightnessRangeController mBrightnessRangeController; private final BrightnessThrottler mBrightnessThrottler; @@ -489,7 +488,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController( mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(), () -> updatePowerState(), mDisplayId, mSensorManager); - mHighBrightnessModeMetadata = hbmMetadata; mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController); mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(context, mDisplayId); mTag = "DisplayPowerController2[" + mDisplayId + "]"; @@ -532,9 +530,22 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mSkipScreenOnBrightnessRamp = resources.getBoolean( R.bool.config_skipScreenOnBrightnessRamp); - mHbmController = createHbmControllerLocked(); + Runnable modeChangeCallback = () -> { + sendUpdatePowerState(); + postBrightnessChangeRunnable(); + // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern. + if (mAutomaticBrightnessController != null) { + mAutomaticBrightnessController.update(); + } + }; + HighBrightnessModeController hbmController = createHbmControllerLocked(hbmMetadata, + modeChangeCallback); mBrightnessThrottler = createBrightnessThrottlerLocked(); + + mBrightnessRangeController = new BrightnessRangeController(hbmController, + modeChangeCallback, mDisplayDeviceConfig); + mDisplayBrightnessController = new DisplayBrightnessController(context, null, mDisplayId, mLogicalDisplay.getDisplayInfoLocked().brightnessDefault, @@ -848,17 +859,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mBrightnessRampIncreaseMaxTimeMillis, mBrightnessRampDecreaseMaxTimeMillis); } - mHbmController.setHighBrightnessModeMetadata(hbmMetadata); - mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId, - mDisplayDeviceConfig.getHighBrightnessModeData(), - new HighBrightnessModeController.HdrBrightnessDeviceConfig() { - @Override - public float getHdrBrightnessFromSdr( - float sdrBrightness, float maxDesiredHdrSdrRatio) { - return mDisplayDeviceConfig.getHdrBrightnessFromSdr( - sdrBrightness, maxDesiredHdrSdrRatio); - } - }); + + mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig); mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(), mThermalBrightnessThrottlingDataId, mUniqueDisplayId); @@ -1076,7 +1078,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext, - mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper, + mBrightnessRangeController, mBrightnessThrottler, mIdleModeBrightnessMapper, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness); mDisplayBrightnessController.setAutomaticBrightnessController( @@ -1180,7 +1182,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal /** Clean up all resources that are accessed via the {@link #mHandler} thread. */ private void cleanupHandlerThreadAfterStop() { mDisplayPowerProximityStateController.cleanup(); - mHbmController.stop(); + mBrightnessRangeController.stop(); mBrightnessThrottler.stop(); mHandler.removeCallbacksAndMessages(null); @@ -1295,7 +1297,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal && (mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged() || userSetBrightnessChanged); - mHbmController.setAutoBrightnessEnabled(mAutomaticBrightnessStrategy + mBrightnessRangeController.setAutoBrightnessEnabled(mAutomaticBrightnessStrategy .shouldUseAutoBrightness() ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED); @@ -1452,7 +1454,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal // here instead of having HbmController listen to the brightness setting because certain // brightness sources (such as an app override) are not saved to the setting, but should be // reflected in HBM calculations. - mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState, + mBrightnessRangeController.onBrightnessChanged(brightnessState, unthrottledBrightnessState, mBrightnessThrottler.getBrightnessMaxReason()); // Animate the screen brightness when the screen is on or dozing. @@ -1509,13 +1511,14 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal float sdrAnimateValue = animateValue; // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be // done in HighBrightnessModeController. - if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR + if (mBrightnessRangeController.getHighBrightnessMode() + == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0 && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER) == 0) { // We want to scale HDR brightness level with the SDR level, we also need to restore // SDR brightness immediately when entering dim or low power mode. - animateValue = mHbmController.getHdrBrightnessValue(); + animateValue = mBrightnessRangeController.getHdrBrightnessValue(); } final float currentBrightness = mPowerState.getScreenBrightness(); @@ -1579,8 +1582,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mTempBrightnessEvent.setBrightness(brightnessState); mTempBrightnessEvent.setPhysicalDisplayId(mUniqueDisplayId); mTempBrightnessEvent.setReason(mBrightnessReason); - mTempBrightnessEvent.setHbmMax(mHbmController.getCurrentBrightnessMax()); - mTempBrightnessEvent.setHbmMode(mHbmController.getHighBrightnessMode()); + mTempBrightnessEvent.setHbmMax(mBrightnessRangeController.getCurrentBrightnessMax()); + mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode()); mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags() | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0) | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0)); @@ -1750,9 +1753,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) { synchronized (mCachedBrightnessInfo) { - final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(), + final float minBrightness = Math.min( + mBrightnessRangeController.getCurrentBrightnessMin(), mBrightnessThrottler.getBrightnessCap()); - final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(), + final float maxBrightness = Math.min( + mBrightnessRangeController.getCurrentBrightnessMax(), mBrightnessThrottler.getBrightnessCap()); boolean changed = false; @@ -1770,10 +1775,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal maxBrightness); changed |= mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode, - mHbmController.getHighBrightnessMode()); + mBrightnessRangeController.getHighBrightnessMode()); changed |= mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint, - mHbmController.getTransitionPoint()); + mBrightnessRangeController.getTransitionPoint()); changed |= mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason, mBrightnessThrottler.getBrightnessMaxReason()); @@ -1783,10 +1788,13 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal } void postBrightnessChangeRunnable() { - mHandler.post(mOnBrightnessChangeRunnable); + if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) { + mHandler.post(mOnBrightnessChangeRunnable); + } } - private HighBrightnessModeController createHbmControllerLocked() { + private HighBrightnessModeController createHbmControllerLocked( + HighBrightnessModeMetadata hbmMetadata, Runnable modeChangeCallback) { final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); final IBinder displayToken = @@ -1798,22 +1806,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); return new HighBrightnessModeController(mHandler, info.width, info.height, displayToken, displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData, - new HighBrightnessModeController.HdrBrightnessDeviceConfig() { - @Override - public float getHdrBrightnessFromSdr( - float sdrBrightness, float maxDesiredHdrSdrRatio) { - return mDisplayDeviceConfig.getHdrBrightnessFromSdr( - sdrBrightness, maxDesiredHdrSdrRatio); - } - }, - () -> { - sendUpdatePowerState(); - postBrightnessChangeRunnable(); - // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern. - if (mAutomaticBrightnessController != null) { - mAutomaticBrightnessController.update(); - } - }, mHighBrightnessModeMetadata, mContext); + (sdrBrightness, maxDesiredHdrSdrRatio) -> + mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness, + maxDesiredHdrSdrRatio), modeChangeCallback, hbmMetadata, mContext); } private BrightnessThrottler createBrightnessThrottlerLocked() { @@ -1960,8 +1955,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal if (Float.isNaN(value)) { value = PowerManager.BRIGHTNESS_MIN; } - return MathUtils.constrain(value, - mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax()); + return MathUtils.constrain(value, mBrightnessRangeController.getCurrentBrightnessMin(), + mBrightnessRangeController.getCurrentBrightnessMax()); } private void animateScreenBrightness(float target, float sdrTarget, float rate) { @@ -2195,7 +2190,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal @Override public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) { - mHbmController.onAmbientLuxChange(ambientLux); + mBrightnessRangeController.onAmbientLuxChange(ambientLux); if (nits < 0) { mDisplayBrightnessController.setBrightnessToFollow(leadDisplayBrightness); } else { @@ -2374,8 +2369,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal dumpRbcEvents(pw); - if (mHbmController != null) { - mHbmController.dump(pw); + if (mBrightnessRangeController != null) { + mBrightnessRangeController.dump(pw); } if (mBrightnessThrottler != null) { @@ -2840,7 +2835,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, - HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler, + BrightnessRangeController brightnessModeController, + BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userBrightness) { return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor, @@ -2849,9 +2845,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal brighteningLightDebounceConfig, darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, - screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler, - idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong, - userLux, userBrightness); + screenBrightnessThresholdsIdle, context, brightnessModeController, + brightnessThrottler, idleModeBrightnessMapper, ambientLightHorizonShort, + ambientLightHorizonLong, userLux, userBrightness); } BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources, diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index c7c0fab6140d..7701bc6271ae 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -701,11 +701,15 @@ final class LocalDisplayAdapter extends DisplayAdapter { maxDisplayMode == null ? mInfo.width : maxDisplayMode.getPhysicalWidth(); final int maxHeight = maxDisplayMode == null ? mInfo.height : maxDisplayMode.getPhysicalHeight(); - mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res, - mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height); - mInfo.roundedCorners = RoundedCorners.fromResources( - res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height); + // We cannot determine cutouts and rounded corners of external displays. + if (mStaticDisplayInfo.isInternal) { + mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res, + mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height); + mInfo.roundedCorners = RoundedCorners.fromResources( + res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height); + } + mInfo.installOrientation = mStaticDisplayInfo.installOrientation; mInfo.displayShape = DisplayShape.fromResources( diff --git a/services/core/java/com/android/server/display/NormalBrightnessModeController.java b/services/core/java/com/android/server/display/NormalBrightnessModeController.java new file mode 100644 index 000000000000..dbabc2441224 --- /dev/null +++ b/services/core/java/com/android/server/display/NormalBrightnessModeController.java @@ -0,0 +1,94 @@ +/* + * 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.server.display; + +import android.annotation.NonNull; +import android.os.PowerManager; + +import com.android.server.display.DisplayDeviceConfig.BrightnessLimitMapType; + +import java.util.HashMap; +import java.util.Map; + +/** + * Limits brightness for normal-brightness mode, based on ambient lux + **/ +class NormalBrightnessModeController { + @NonNull + private Map<BrightnessLimitMapType, Map<Float, Float>> mMaxBrightnessLimits = new HashMap<>(); + private float mAmbientLux = Float.MAX_VALUE; + private boolean mAutoBrightnessEnabled = false; + + // brightness limit in normal brightness mode, based on ambient lux. + private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX; + + boolean onAmbientLuxChange(float ambientLux) { + mAmbientLux = ambientLux; + return recalculateMaxBrightness(); + } + + boolean setAutoBrightnessState(int state) { + boolean isEnabled = state == AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED; + if (isEnabled != mAutoBrightnessEnabled) { + mAutoBrightnessEnabled = isEnabled; + return recalculateMaxBrightness(); + } + return false; + } + + float getCurrentBrightnessMax() { + return mMaxBrightness; + } + + boolean resetNbmData( + @NonNull Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessLimits) { + mMaxBrightnessLimits = maxBrightnessLimits; + return recalculateMaxBrightness(); + } + + private boolean recalculateMaxBrightness() { + float foundAmbientBoundary = Float.MAX_VALUE; + float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX; + + Map<Float, Float> maxBrightnessPoints = null; + + if (mAutoBrightnessEnabled) { + maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.ADAPTIVE); + } + + if (maxBrightnessPoints == null) { + maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.DEFAULT); + } + + if (maxBrightnessPoints != null) { + for (Map.Entry<Float, Float> brightnessPoint : maxBrightnessPoints.entrySet()) { + float ambientBoundary = brightnessPoint.getKey(); + // find ambient lux upper boundary closest to current ambient lux + if (ambientBoundary > mAmbientLux && ambientBoundary < foundAmbientBoundary) { + foundMaxBrightness = brightnessPoint.getValue(); + foundAmbientBoundary = ambientBoundary; + } + } + } + + if (mMaxBrightness != foundMaxBrightness) { + mMaxBrightness = foundMaxBrightness; + return true; + } + return false; + } +} diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java index b4613a76c751..efb36227c7bd 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java @@ -171,7 +171,7 @@ public class BatterySaverPolicy extends ContentObserver implements true, /* disableAod */ true, /* disableLaunchBoost */ true, /* disableOptionalSensors */ - true, /* disableVibration */ + false, /* disableVibration */ false, /* enableAdjustBrightness */ false, /* enableDataSaver */ true, /* enableFirewall */ diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index 27329e20bc8d..6821c40ec5d3 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -16244,7 +16244,7 @@ public class BatteryStatsImpl extends BatteryStats { } NP = in.readInt(); - if (NP > 1000) { + if (NP > 10000) { throw new ParcelFormatException("File corrupt: too many processes " + NP); } for (int ip = 0; ip < NP; ip++) { diff --git a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java index d8e6c262359d..d770792dffec 100644 --- a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java +++ b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java @@ -17,6 +17,7 @@ package com.android.server.powerstats; import android.content.Context; +import android.util.IndentingPrintWriter; import android.util.Slog; import com.android.internal.util.FileRotator; @@ -27,6 +28,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; +import java.util.Date; import java.util.concurrent.locks.ReentrantLock; /** @@ -266,4 +268,51 @@ public class PowerStatsDataStorage { mLock.unlock(); } } + + /** + * Dump stats about stored data. + */ + public void dump(IndentingPrintWriter ipw) { + mLock.lock(); + try { + final int versionDot = mDataStorageFilename.lastIndexOf('.'); + final String beforeVersionDot = mDataStorageFilename.substring(0, versionDot); + final File[] files = mDataStorageDir.listFiles(); + + int number = 0; + int dataSize = 0; + long earliestLogEpochTime = Long.MAX_VALUE; + for (int i = 0; i < files.length; i++) { + // Check that the stems before the version match. + final File file = files[i]; + final String fileName = file.getName(); + if (files[i].getName().startsWith(beforeVersionDot)) { + number++; + dataSize += file.length(); + final int firstTimeChar = fileName.lastIndexOf('.') + 1; + final int endChar = fileName.lastIndexOf('-'); + try { + final Long startTime = + Long.parseLong(fileName.substring(firstTimeChar, endChar)); + if (startTime != null && startTime < earliestLogEpochTime) { + earliestLogEpochTime = startTime; + } + } catch (NumberFormatException nfe) { + Slog.e(TAG, + "Failed to extract start time from file : " + fileName, nfe); + } + } + } + + if (earliestLogEpochTime != Long.MAX_VALUE) { + ipw.println("Earliest data time : " + new Date(earliestLogEpochTime)); + } else { + ipw.println("Failed to parse earliest data time!!!"); + } + ipw.println("# files : " + number); + ipw.println("Total data size (B) : " + dataSize); + } finally { + mLock.unlock(); + } + } } diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java index 39ead13b03fe..e80a86d73f90 100644 --- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java +++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java @@ -30,6 +30,7 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.util.AtomicFile; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; @@ -354,4 +355,23 @@ public final class PowerStatsLogger extends Handler { updateCacheFile(residencyCacheFilename, powerEntityBytes); } } + + /** + * Dump stats about stored data. + */ + public void dump(IndentingPrintWriter ipw) { + ipw.println("PowerStats Meter Data:"); + ipw.increaseIndent(); + mPowerStatsMeterStorage.dump(ipw); + ipw.decreaseIndent(); + ipw.println("PowerStats Model Data:"); + ipw.increaseIndent(); + mPowerStatsModelStorage.dump(ipw); + ipw.decreaseIndent(); + ipw.println("PowerStats State Residency Data:"); + ipw.increaseIndent(); + mPowerStatsResidencyStorage.dump(ipw); + ipw.decreaseIndent(); + } + } diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java index 2638f34fe7df..ffc9a0178971 100644 --- a/services/core/java/com/android/server/powerstats/PowerStatsService.java +++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java @@ -31,6 +31,7 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.UserHandle; import android.power.PowerStatsInternal; +import android.util.IndentingPrintWriter; import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -176,18 +177,31 @@ public class PowerStatsService extends SystemService { } else if ("residency".equals(args[1])) { mPowerStatsLogger.writeResidencyDataToFile(fd); } - } else if (args.length == 0) { - pw.println("PowerStatsService dumpsys: available PowerEntities"); + } else { + IndentingPrintWriter ipw = new IndentingPrintWriter(pw); + ipw.println("PowerStatsService dumpsys: available PowerEntities"); PowerEntity[] powerEntity = getPowerStatsHal().getPowerEntityInfo(); - PowerEntityUtils.dumpsys(powerEntity, pw); + ipw.increaseIndent(); + PowerEntityUtils.dumpsys(powerEntity, ipw); + ipw.decreaseIndent(); - pw.println("PowerStatsService dumpsys: available Channels"); + ipw.println("PowerStatsService dumpsys: available Channels"); Channel[] channel = getPowerStatsHal().getEnergyMeterInfo(); - ChannelUtils.dumpsys(channel, pw); + ipw.increaseIndent(); + ChannelUtils.dumpsys(channel, ipw); + ipw.decreaseIndent(); - pw.println("PowerStatsService dumpsys: available EnergyConsumers"); + ipw.println("PowerStatsService dumpsys: available EnergyConsumers"); EnergyConsumer[] energyConsumer = getPowerStatsHal().getEnergyConsumerInfo(); - EnergyConsumerUtils.dumpsys(energyConsumer, pw); + ipw.increaseIndent(); + EnergyConsumerUtils.dumpsys(energyConsumer, ipw); + ipw.decreaseIndent(); + + ipw.println("PowerStatsService dumpsys: PowerStatsLogger stats"); + ipw.increaseIndent(); + mPowerStatsLogger.dump(ipw); + ipw.decreaseIndent(); + } } } diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index f96ca582c28f..7104a80c668d 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -46,6 +46,8 @@ <xs:annotation name="nonnull"/> <xs:annotation name="final"/> </xs:element> + <xs:element type="luxThrottling" name="luxThrottling" minOccurs="0" + maxOccurs="1"/> <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0" maxOccurs="1"/> <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1"/> @@ -137,6 +139,39 @@ </xs:sequence> </xs:complexType> + <xs:complexType name="luxThrottling"> + <xs:sequence> + <xs:element name="brightnessLimitMap" type="brightnessLimitMap" + maxOccurs="unbounded"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="brightnessLimitMap"> + <xs:sequence> + <xs:element name="type" type="PredefinedBrightnessLimitNames"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + <!-- lux level from light sensor to screen brightness recommended max value map. + Screen brightness recommended max value is to highBrightnessMode.transitionPoint and must be below that --> + <xs:element name="map" type="nonNegativeFloatToFloatMap"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + </xs:sequence> + </xs:complexType> + + <!-- Predefined type names as defined by DisplayDeviceConfig.BrightnessLimitMapType --> + <xs:simpleType name="PredefinedBrightnessLimitNames"> + <xs:restriction base="xs:string"> + <xs:enumeration value="default"/> + <xs:enumeration value="adaptive"/> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="highBrightnessMode"> <xs:all> <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1" @@ -575,4 +610,27 @@ <xs:annotation name="final"/> </xs:element> </xs:complexType> + + <!-- generic types --> + <xs:complexType name="nonNegativeFloatToFloatPoint"> + <xs:sequence> + <xs:element name="first" type="nonNegativeDecimal"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + <xs:element name="second" type="nonNegativeDecimal"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="nonNegativeFloatToFloatMap"> + <xs:sequence> + <xs:element name="point" type="nonNegativeFloatToFloatPoint" maxOccurs="unbounded"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + </xs:sequence> + </xs:complexType> </xs:schema> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index ad6434e0c545..507c9dccda59 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -26,6 +26,14 @@ package com.android.server.display.config { method public final java.util.List<com.android.server.display.config.DisplayBrightnessPoint> getDisplayBrightnessPoint(); } + public class BrightnessLimitMap { + ctor public BrightnessLimitMap(); + method @NonNull public final com.android.server.display.config.NonNegativeFloatToFloatMap getMap(); + method @NonNull public final com.android.server.display.config.PredefinedBrightnessLimitNames getType(); + method public final void setMap(@NonNull com.android.server.display.config.NonNegativeFloatToFloatMap); + method public final void setType(@NonNull com.android.server.display.config.PredefinedBrightnessLimitNames); + } + public class BrightnessThresholds { ctor public BrightnessThresholds(); method public final com.android.server.display.config.ThresholdPoints getBrightnessThresholdPoints(); @@ -89,6 +97,7 @@ package com.android.server.display.config { method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle(); method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode(); method public final com.android.server.display.config.SensorDetails getLightSensor(); + method public com.android.server.display.config.LuxThrottling getLuxThrottling(); method @Nullable public final String getName(); method public final com.android.server.display.config.SensorDetails getProxSensor(); method public com.android.server.display.config.DisplayQuirks getQuirks(); @@ -115,6 +124,7 @@ package com.android.server.display.config { method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds); method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode); method public final void setLightSensor(com.android.server.display.config.SensorDetails); + method public void setLuxThrottling(com.android.server.display.config.LuxThrottling); method public final void setName(@Nullable String); method public final void setProxSensor(com.android.server.display.config.SensorDetails); method public void setQuirks(com.android.server.display.config.DisplayQuirks); @@ -173,6 +183,11 @@ package com.android.server.display.config { method public java.util.List<java.math.BigInteger> getItem(); } + public class LuxThrottling { + ctor public LuxThrottling(); + method @NonNull public final java.util.List<com.android.server.display.config.BrightnessLimitMap> getBrightnessLimitMap(); + } + public class NitsMap { ctor public NitsMap(); method public String getInterpolation(); @@ -180,6 +195,19 @@ package com.android.server.display.config { method public void setInterpolation(String); } + public class NonNegativeFloatToFloatMap { + ctor public NonNegativeFloatToFloatMap(); + method @NonNull public final java.util.List<com.android.server.display.config.NonNegativeFloatToFloatPoint> getPoint(); + } + + public class NonNegativeFloatToFloatPoint { + ctor public NonNegativeFloatToFloatPoint(); + method @NonNull public final java.math.BigDecimal getFirst(); + method @NonNull public final java.math.BigDecimal getSecond(); + method public final void setFirst(@NonNull java.math.BigDecimal); + method public final void setSecond(@NonNull java.math.BigDecimal); + } + public class Point { ctor public Point(); method @NonNull public final java.math.BigDecimal getNits(); @@ -188,6 +216,12 @@ package com.android.server.display.config { method public final void setValue(@NonNull java.math.BigDecimal); } + public enum PredefinedBrightnessLimitNames { + method public String getRawName(); + enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames _default; + enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames adaptive; + } + public class RefreshRateConfigs { ctor public RefreshRateConfigs(); method public final java.math.BigInteger getDefaultPeakRefreshRate(); diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java index 32243f04f6e8..212a243c6a9e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java @@ -2221,7 +2221,7 @@ public class GameManagerServiceTests { String[] packages = {mPackageName}; when(mMockPackageManager.getPackagesForUid(DEFAULT_PACKAGE_UID)).thenReturn(packages); gameManagerService.mUidObserver.onUidStateChanged( - DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); + DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TOP, 0, 0); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME, true); } @@ -2238,12 +2238,12 @@ public class GameManagerServiceTests { doAnswer(inv -> powerState.put(inv.getArgument(0), inv.getArgument(1))) .when(mMockPowerManager).setPowerMode(anyInt(), anyBoolean()); gameManagerService.mUidObserver.onUidStateChanged( - DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); + DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TOP, 0, 0); assertTrue(powerState.get(Mode.GAME)); gameManagerService.mUidObserver.onUidStateChanged( DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); gameManagerService.mUidObserver.onUidStateChanged( - somePackageId, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); + somePackageId, ActivityManager.PROCESS_STATE_TOP, 0, 0); assertTrue(powerState.get(Mode.GAME)); gameManagerService.mUidObserver.onUidStateChanged( somePackageId, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); @@ -2260,13 +2260,13 @@ public class GameManagerServiceTests { int somePackageId = DEFAULT_PACKAGE_UID + 1; when(mMockPackageManager.getPackagesForUid(somePackageId)).thenReturn(packages2); gameManagerService.mUidObserver.onUidStateChanged( - DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); + DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TOP, 0, 0); gameManagerService.mUidObserver.onUidStateChanged( - somePackageId, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); + somePackageId, ActivityManager.PROCESS_STATE_TOP, 0, 0); gameManagerService.mUidObserver.onUidStateChanged( - DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); + DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); gameManagerService.mUidObserver.onUidStateChanged( - somePackageId, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); + somePackageId, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME, true); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME, false); } @@ -2277,9 +2277,9 @@ public class GameManagerServiceTests { String[] packages = {mPackageName}; when(mMockPackageManager.getPackagesForUid(DEFAULT_PACKAGE_UID)).thenReturn(packages); gameManagerService.mUidObserver.onUidStateChanged( - DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); + DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TOP, 0, 0); gameManagerService.mUidObserver.onUidStateChanged( - DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); + DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME, false); } diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java index 170076098b7d..4f98dca660df 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java @@ -815,7 +815,7 @@ public final class DisplayPowerController2Test { any(HysteresisLevels.class), any(HysteresisLevels.class), eq(mContext), - any(HighBrightnessModeController.class), + any(BrightnessRangeController.class), any(BrightnessThrottler.class), isNull(), anyInt(), @@ -1064,7 +1064,7 @@ public final class DisplayPowerController2Test { HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, - HighBrightnessModeController hbmController, + BrightnessRangeController brightnessRangeController, BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java index 5c0810fdca44..a93640b592cd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -819,7 +819,7 @@ public final class DisplayPowerControllerTest { any(HysteresisLevels.class), any(HysteresisLevels.class), eq(mContext), - any(HighBrightnessModeController.class), + any(BrightnessRangeController.class), any(BrightnessThrottler.class), isNull(), anyInt(), @@ -1038,7 +1038,7 @@ public final class DisplayPowerControllerTest { HysteresisLevels screenBrightnessThresholds, HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, - HighBrightnessModeController hbmController, + BrightnessRangeController brightnessRangeController, BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index b7dbaf93b9e2..f89f73c98cfd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Rect; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -1009,6 +1010,72 @@ public class LocalDisplayAdapterTest { 0.001f); } + @Test + public void test_getDisplayDeviceInfoLocked_internalDisplay_usesCutoutAndCorners() + throws Exception { + setupCutoutAndRoundedCorners(); + FakeDisplay display = new FakeDisplay(PORT_A); + display.info.isInternal = true; + setUpDisplay(display); + updateAvailableDisplays(); + mAdapter.registerLocked(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + assertThat(mListener.addedDisplays.size()).isEqualTo(1); + DisplayDevice displayDevice = mListener.addedDisplays.get(0); + + // Turn on / initialize + Runnable changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0, + 0); + changeStateRunnable.run(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + mListener.changedDisplays.clear(); + + DisplayDeviceInfo info = displayDevice.getDisplayDeviceInfoLocked(); + + assertThat(info.displayCutout).isNotNull(); + assertThat(info.displayCutout.getBoundingRectTop()).isEqualTo(new Rect(507, 33, 573, 99)); + assertThat(info.roundedCorners).isNotNull(); + assertThat(info.roundedCorners.getRoundedCorner(0).getRadius()).isEqualTo(5); + } + + @Test public void test_getDisplayDeviceInfoLocked_externalDisplay_doesNotUseCutoutOrCorners() + throws Exception { + setupCutoutAndRoundedCorners(); + FakeDisplay display = new FakeDisplay(PORT_A); + display.info.isInternal = false; + setUpDisplay(display); + updateAvailableDisplays(); + mAdapter.registerLocked(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + assertThat(mListener.addedDisplays.size()).isEqualTo(1); + DisplayDevice displayDevice = mListener.addedDisplays.get(0); + + // Turn on / initialize + Runnable changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0, + 0); + changeStateRunnable.run(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + mListener.changedDisplays.clear(); + + DisplayDeviceInfo info = displayDevice.getDisplayDeviceInfoLocked(); + + assertThat(info.displayCutout).isNull(); + assertThat(info.roundedCorners).isNull(); + } + + private void setupCutoutAndRoundedCorners() { + String sampleCutout = "M 507,66\n" + + "a 33,33 0 1 0 66,0 33,33 0 1 0 -66,0\n" + + "Z\n" + + "@left\n"; + // Setup some default cutout + when(mMockedResources.getString( + com.android.internal.R.string.config_mainBuiltInDisplayCutout)) + .thenReturn(sampleCutout); + when(mMockedResources.getDimensionPixelSize( + com.android.internal.R.dimen.rounded_corner_radius)).thenReturn(5); + } + private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort, float expectedXdpi, float expectedYDpi, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java index 662477ddbbe9..0cfddd30d721 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java @@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGAT import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING; +import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -48,6 +49,7 @@ import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustManager; import android.content.Context; import android.content.res.Resources; +import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.ComponentInfoInternal; @@ -104,6 +106,7 @@ public class AuthSessionTest { @Mock private KeyStore mKeyStore; @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver; @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger; + @Mock private BiometricCameraManager mBiometricCameraManager; private Random mRandom; private IBinder mToken; @@ -210,6 +213,40 @@ public class AuthSessionTest { } @Test + public void testOnErrorReceived_lockoutError() throws RemoteException { + setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR); + setupFace(1 /* id */, false /* confirmationAlwaysRequired */, + mock(IBiometricAuthenticator.class)); + final AuthSession session = createAuthSession(mSensors, + false /* checkDevicePolicyManager */, + Authenticators.BIOMETRIC_STRONG, + TEST_REQUEST_ID, + 0 /* operationId */, + 0 /* userId */); + session.goToInitialState(); + for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { + assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); + session.onCookieReceived( + session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); + } + assertTrue(session.allCookiesReceived()); + assertEquals(STATE_AUTH_STARTED, session.getState()); + + // Either of strong sensor's lockout should cancel both sensors. + final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie(); + session.onErrorReceived(0, cookie1, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 0); + for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { + assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState()); + } + assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState()); + + // If the sensor is STATE_CANCELING, delayed onAuthenticationRejected() shouldn't change the + // session state to STATE_AUTH_PAUSED. + session.onAuthenticationRejected(1); + assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState()); + } + + @Test public void testCancelReducesAppetiteForCookies() throws Exception { setupFace(0 /* id */, false /* confirmationAlwaysRequired */, mock(IBiometricAuthenticator.class)); @@ -571,7 +608,8 @@ public class AuthSessionTest { promptInfo, TEST_PACKAGE, checkDevicePolicyManager, - mContext); + mContext, + mBiometricCameraManager); } private AuthSession createAuthSession(List<BiometricSensor> sensors, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index 67be37616d5f..fc62e75b7d59 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -16,9 +16,9 @@ package com.android.server.biometrics; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricManager.Authenticators; -import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI; @@ -114,6 +114,10 @@ public class BiometricServiceTest { private static final String ERROR_UNABLE_TO_PROCESS = "error_unable_to_process"; private static final String ERROR_USER_CANCELED = "error_user_canceled"; private static final String ERROR_LOCKOUT = "error_lockout"; + private static final String FACE_SUBTITLE = "face_subtitle"; + private static final String FINGERPRINT_SUBTITLE = "fingerprint_subtitle"; + private static final String DEFAULT_SUBTITLE = "default_subtitle"; + private static final String FINGERPRINT_ACQUIRED_SENSOR_DIRTY = "sensor_dirty"; @@ -152,6 +156,8 @@ public class BiometricServiceTest { private AuthSessionCoordinator mAuthSessionCoordinator; @Mock private UserManager mUserManager; + @Mock + private BiometricCameraManager mBiometricCameraManager; BiometricContextProvider mBiometricContextProvider; @@ -178,13 +184,24 @@ public class BiometricServiceTest { when(mInjector.getDevicePolicyManager(any())).thenReturn(mDevicePolicyManager); when(mInjector.getRequestGenerator()).thenReturn(() -> TEST_REQUEST_ID); when(mInjector.getUserManager(any())).thenReturn(mUserManager); + when(mInjector.getBiometricCameraManager(any())).thenReturn(mBiometricCameraManager); when(mResources.getString(R.string.biometric_error_hw_unavailable)) .thenReturn(ERROR_HW_UNAVAILABLE); when(mResources.getString(R.string.biometric_not_recognized)) .thenReturn(ERROR_NOT_RECOGNIZED); + when(mResources.getString(R.string.biometric_face_not_recognized)) + .thenReturn(ERROR_NOT_RECOGNIZED); + when(mResources.getString(R.string.fingerprint_error_not_match)) + .thenReturn(ERROR_NOT_RECOGNIZED); when(mResources.getString(R.string.biometric_error_user_canceled)) .thenReturn(ERROR_USER_CANCELED); + when(mContext.getString(R.string.biometric_dialog_face_subtitle)) + .thenReturn(FACE_SUBTITLE); + when(mContext.getString(R.string.biometric_dialog_fingerprint_subtitle)) + .thenReturn(FINGERPRINT_SUBTITLE); + when(mContext.getString(R.string.biometric_dialog_default_subtitle)) + .thenReturn(DEFAULT_SUBTITLE); when(mWindowManager.getDefaultDisplay()).thenReturn( new Display(DisplayManagerGlobal.getInstance(), Display.DEFAULT_DISPLAY, @@ -205,7 +222,7 @@ public class BiometricServiceTest { @Test public void testClientBinderDied_whenPaused() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, true /* requireConfirmation */, null /* authenticators */); @@ -232,7 +249,7 @@ public class BiometricServiceTest { @Test public void testClientBinderDied_whenAuthenticating() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, true /* requireConfirmation */, null /* authenticators */); @@ -368,7 +385,7 @@ public class BiometricServiceTest { final int[] modalities = new int[] { TYPE_FINGERPRINT, - BiometricAuthenticator.TYPE_FACE, + TYPE_FACE, }; final int[] strengths = new int[] { @@ -421,9 +438,56 @@ public class BiometricServiceTest { } @Test + public void testAuthenticateFace_shouldShowSubtitleForFace() throws Exception { + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + + invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + false /* requireConfirmation */, + null); + waitForIdle(); + + assertEquals(FACE_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle()); + } + + @Test + public void testAuthenticateFingerprint_shouldShowSubtitleForFingerprint() throws Exception { + setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); + + invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + false /* requireConfirmation */, + null); + waitForIdle(); + + assertEquals(FINGERPRINT_SUBTITLE, + mBiometricService.mAuthSession.mPromptInfo.getSubtitle()); + } + + @Test + public void testAuthenticateBothFpAndFace_shouldShowDefaultSubtitle() throws Exception { + final int[] modalities = new int[] { + TYPE_FINGERPRINT, + TYPE_FACE, + }; + + final int[] strengths = new int[] { + Authenticators.BIOMETRIC_WEAK, + Authenticators.BIOMETRIC_STRONG, + }; + + setupAuthForMultiple(modalities, strengths); + + invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + false /* requireConfirmation */, + null); + waitForIdle(); + + assertEquals(DEFAULT_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle()); + } + + @Test public void testAuthenticateFace_respectsUserSetting() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); // Disabled in user settings receives onError when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); @@ -562,7 +626,7 @@ public class BiometricServiceTest { @Test public void testAuthenticate_noBiometrics_credentialAllowed() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) .thenReturn(true); @@ -589,13 +653,13 @@ public class BiometricServiceTest { @Test public void testAuthenticate_happyPathWithConfirmation_strongBiometric() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); testAuthenticate_happyPathWithConfirmation(true /* isStrongBiometric */); } @Test public void testAuthenticate_happyPathWithConfirmation_weakBiometric() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_WEAK); testAuthenticate_happyPathWithConfirmation(false /* isStrongBiometric */); } @@ -631,7 +695,7 @@ public class BiometricServiceTest { @Test public void testAuthenticate_no_Biometrics_noCredential() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) .thenReturn(false); @@ -649,7 +713,7 @@ public class BiometricServiceTest { @Test public void testRejectFace_whenAuthenticating_notifiesSystemUIAndClient_thenPaused() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, null /* authenticators */); @@ -657,7 +721,7 @@ public class BiometricServiceTest { waitForIdle(); verify(mBiometricService.mStatusBarService).onBiometricError( - eq(BiometricAuthenticator.TYPE_FACE), + eq(TYPE_FACE), eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED), eq(0 /* vendorCode */)); verify(mReceiver1).onAuthenticationFailed(); @@ -685,7 +749,7 @@ public class BiometricServiceTest { @Test public void testRequestAuthentication_whenAlreadyAuthenticating() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, null /* authenticators */); @@ -694,7 +758,7 @@ public class BiometricServiceTest { waitForIdle(); verify(mReceiver1).onError( - eq(BiometricAuthenticator.TYPE_FACE), + eq(TYPE_FACE), eq(BiometricPrompt.BIOMETRIC_ERROR_CANCELED), eq(0) /* vendorCode */); verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID)); @@ -704,7 +768,7 @@ public class BiometricServiceTest { @Test public void testErrorHalTimeout_whenAuthenticating_entersPausedState() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, null /* authenticators */); @@ -717,7 +781,7 @@ public class BiometricServiceTest { assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState()); verify(mBiometricService.mStatusBarService).onBiometricError( - eq(BiometricAuthenticator.TYPE_FACE), + eq(TYPE_FACE), eq(BiometricConstants.BIOMETRIC_ERROR_TIMEOUT), eq(0 /* vendorCode */)); // Timeout does not count as fail as per BiometricPrompt documentation. @@ -753,7 +817,7 @@ public class BiometricServiceTest { @Test public void testErrorFromHal_whenPaused_notifiesSystemUIAndClient() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, null /* authenticators */); @@ -771,7 +835,7 @@ public class BiometricServiceTest { // Client receives error immediately verify(mReceiver1).onError( - eq(BiometricAuthenticator.TYPE_FACE), + eq(TYPE_FACE), eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED), eq(0 /* vendorCode */)); // Dialog is hidden immediately @@ -903,6 +967,45 @@ public class BiometricServiceTest { } @Test + public void testMultiBiometricAuth_whenLockoutTimed_sendsErrorAndModality() + throws Exception { + testMultiBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_TIMED, + BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT); + } + + @Test + public void testMultiBiometricAuth_whenLockoutPermanent_sendsErrorAndModality() + throws Exception { + testMultiBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_PERMANENT, + BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT); + } + + private void testMultiBiometricAuth_whenLockout(@LockoutTracker.LockoutMode int lockoutMode, + int biometricPromptError) throws Exception { + final int[] modalities = new int[] { + TYPE_FINGERPRINT, + TYPE_FACE, + }; + + final int[] strengths = new int[] { + Authenticators.BIOMETRIC_STRONG, + Authenticators.BIOMETRIC_STRONG, + }; + setupAuthForMultiple(modalities, strengths); + + when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) + .thenReturn(lockoutMode); + when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); + invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + false /* requireConfirmation */, null /* authenticators */); + waitForIdle(); + + // The lockout error should be sent, instead of ERROR_NONE_ENROLLED. See b/286923477. + verify(mReceiver1).onError(eq(TYPE_FINGERPRINT), + eq(biometricPromptError), eq(0) /* vendorCode */); + } + + @Test public void testBiometricOrCredentialAuth_whenBiometricLockout_showsCredential() throws Exception { when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true); @@ -1078,7 +1181,7 @@ public class BiometricServiceTest { @Test public void testDismissedReasonNegative_whilePaused_invokeHalCancel() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, null /* authenticators */); @@ -1097,7 +1200,7 @@ public class BiometricServiceTest { @Test public void testDismissedReasonUserCancel_whilePaused_invokesHalCancel() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, null /* authenticators */); @@ -1116,7 +1219,7 @@ public class BiometricServiceTest { @Test public void testDismissedReasonUserCancel_whenPendingConfirmation() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, true /* requireConfirmation */, null /* authenticators */); @@ -1130,7 +1233,7 @@ public class BiometricServiceTest { verify(mBiometricService.mSensors.get(0).impl) .cancelAuthenticationFromService(any(), any(), anyLong()); verify(mReceiver1).onError( - eq(BiometricAuthenticator.TYPE_FACE), + eq(TYPE_FACE), eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), eq(0 /* vendorCode */)); verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class)); @@ -1251,7 +1354,7 @@ public class BiometricServiceTest { @Test public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) .thenReturn(true); @@ -1545,7 +1648,7 @@ public class BiometricServiceTest { @Test public void testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mDevicePolicyManager .getKeyguardDisabledFeatures(any() /* admin*/, anyInt() /* userHandle */)) .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FACE); @@ -1638,7 +1741,7 @@ public class BiometricServiceTest { mFingerprintAuthenticator); } - if ((modality & BiometricAuthenticator.TYPE_FACE) != 0) { + if ((modality & TYPE_FACE) != 0) { when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(enrolled); when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true); when(mFaceAuthenticator.getLockoutModeForUser(anyInt())) @@ -1670,7 +1773,7 @@ public class BiometricServiceTest { strength, mFingerprintAuthenticator); } - if ((modality & BiometricAuthenticator.TYPE_FACE) != 0) { + if ((modality & TYPE_FACE) != 0) { when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true); mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, @@ -1753,6 +1856,7 @@ public class BiometricServiceTest { boolean checkDevicePolicy) { final PromptInfo promptInfo = new PromptInfo(); promptInfo.setConfirmationRequested(requireConfirmation); + promptInfo.setUseDefaultSubtitle(true); if (authenticators != null) { promptInfo.setAuthenticators(authenticators); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java new file mode 100644 index 000000000000..c2bdf501198e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java @@ -0,0 +1,167 @@ +/* + * 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.server.biometrics; + +import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; + +import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import android.app.admin.DevicePolicyManager; +import android.app.trust.ITrustManager; +import android.content.Context; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.IBiometricAuthenticator; +import android.hardware.biometrics.PromptInfo; +import android.os.RemoteException; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.List; + +@Presubmit +@SmallTest +public class PreAuthInfoTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + private static final int SENSOR_ID_FACE = 1; + private static final String TEST_PACKAGE_NAME = "PreAuthInfoTestPackage"; + + @Mock + IBiometricAuthenticator mFaceAuthenticator; + @Mock + Context mContext; + @Mock + ITrustManager mTrustManager; + @Mock + DevicePolicyManager mDevicePolicyManager; + @Mock + BiometricService.SettingObserver mSettingObserver; + @Mock + BiometricCameraManager mBiometricCameraManager; + + @Before + public void setup() throws RemoteException { + when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true); + when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt())) + .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE); + when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); + when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); + when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true); + when(mFaceAuthenticator.getLockoutModeForUser(anyInt())) + .thenReturn(LOCKOUT_NONE); + when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(false); + when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(false); + } + + @Test + public void testFaceAuthentication_whenCameraPrivacyIsEnabled() throws Exception { + when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(true); + + BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, + BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + @Override + boolean confirmationAlwaysRequired(int userId) { + return false; + } + + @Override + boolean confirmationSupported() { + return false; + } + }; + PromptInfo promptInfo = new PromptInfo(); + promptInfo.setConfirmationRequested(false /* requireConfirmation */); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */); + PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), + 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.eligibleSensors).isEmpty(); + } + + @Test + public void testFaceAuthentication_whenCameraPrivacyIsDisabledAndCameraIsAvailable() + throws Exception { + BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, + BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + @Override + boolean confirmationAlwaysRequired(int userId) { + return false; + } + + @Override + boolean confirmationSupported() { + return false; + } + }; + PromptInfo promptInfo = new PromptInfo(); + promptInfo.setConfirmationRequested(false /* requireConfirmation */); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */); + PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), + 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.eligibleSensors).hasSize(1); + } + + @Test + public void testFaceAuthentication_whenCameraIsUnavailable() throws RemoteException { + when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(true); + BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, + BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + @Override + boolean confirmationAlwaysRequired(int userId) { + return false; + } + + @Override + boolean confirmationSupported() { + return false; + } + }; + PromptInfo promptInfo = new PromptInfo(); + promptInfo.setConfirmationRequested(false /* requireConfirmation */); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */); + PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), + 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.eligibleSensors).hasSize(0); + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index e9d82696affc..89299002a227 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -19,6 +19,8 @@ package com.android.server.biometrics.sensors; import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS; +import static com.google.common.truth.Truth.assertThat; + import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -405,6 +407,59 @@ public class BiometricSchedulerTest { testCancelsEnrollWhenRequestId(10L, 20, false /* started */); } + @Test + public void testCancelAuthenticationClientWithoutStarting() { + final Supplier<Object> lazyDaemon = () -> mock(Object.class); + final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon); + final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); + final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon, + mToken, callback, mBiometricContext); + + //Schedule authentication client to the pending queue + mScheduler.scheduleClientMonitor(client1); + mScheduler.scheduleClientMonitor(client2); + waitForIdle(); + + assertThat(mScheduler.getCurrentClient()).isEqualTo(client1); + + client2.cancel(); + waitForIdle(); + + assertThat(client2.isAlreadyCancelled()).isTrue(); + + client1.getCallback().onClientFinished(client1, false); + waitForIdle(); + + assertThat(mScheduler.getCurrentClient()).isNull(); + } + + @Test + public void testCancelAuthenticationClientWithoutStarting_whenAppCrashes() { + final Supplier<Object> lazyDaemon = () -> mock(Object.class); + final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon); + final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); + final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon, + mToken, callback, mBiometricContext); + + //Schedule authentication client to the pending queue + mScheduler.scheduleClientMonitor(client1); + mScheduler.scheduleClientMonitor(client2); + waitForIdle(); + + assertThat(mScheduler.getCurrentClient()).isEqualTo(client1); + + //App crashes + client2.binderDied(); + waitForIdle(); + + assertThat(client2.isAlreadyCancelled()).isTrue(); + + client1.getCallback().onClientFinished(client1, false); + waitForIdle(); + + assertThat(mScheduler.getCurrentClient()).isNull(); + } + private void testCancelsEnrollWhenRequestId(@Nullable Long requestId, long cancelRequestId, boolean started) { final Supplier<Object> lazyDaemon = () -> mock(Object.class); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java index d5d06d3b4eb8..046b01c831b5 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java @@ -16,8 +16,10 @@ package com.android.server.biometrics.sensors.face.aidl; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT; import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -205,7 +207,9 @@ public class FaceAuthenticationClientTest { client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */), true /* authenticated */, new ArrayList<>()); - verify(mCancellationSignal).cancel(); + verify(mCancellationSignal, never()).cancel(); + verify(mClientMonitorCallbackConverter) + .onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt()); } private FaceAuthenticationClient createClient() throws RemoteException { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java index f8f40fe44457..c383a96d5de3 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -399,7 +401,9 @@ public class FingerprintAuthenticationClientTest { mLooper.moveTimeForward(10); mLooper.dispatchAll(); - verify(mCancellationSignal).cancel(); + verify(mCancellationSignal, never()).cancel(); + verify(mClientMonitorCallbackConverter) + .onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt()); } private FingerprintAuthenticationClient createClient() throws RemoteException { diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 962e86776ea2..a6acd60f3bd7 100644 --- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -85,7 +85,7 @@ public class AutomaticBrightnessControllerTest { @Mock HysteresisLevels mAmbientBrightnessThresholdsIdle; @Mock HysteresisLevels mScreenBrightnessThresholdsIdle; @Mock Handler mNoOpHandler; - @Mock HighBrightnessModeController mHbmController; + @Mock BrightnessRangeController mBrightnessRangeController; @Mock BrightnessThrottler mBrightnessThrottler; @Before @@ -134,12 +134,15 @@ public class AutomaticBrightnessControllerTest { DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mAmbientBrightnessThresholdsIdle, mScreenBrightnessThresholdsIdle, - mContext, mHbmController, mBrightnessThrottler, mIdleBrightnessMappingStrategy, - AMBIENT_LIGHT_HORIZON_SHORT, AMBIENT_LIGHT_HORIZON_LONG, userLux, userBrightness + mContext, mBrightnessRangeController, mBrightnessThrottler, + mIdleBrightnessMappingStrategy, AMBIENT_LIGHT_HORIZON_SHORT, + AMBIENT_LIGHT_HORIZON_LONG, userLux, userBrightness ); - when(mHbmController.getCurrentBrightnessMax()).thenReturn(BRIGHTNESS_MAX_FLOAT); - when(mHbmController.getCurrentBrightnessMin()).thenReturn(BRIGHTNESS_MIN_FLOAT); + when(mBrightnessRangeController.getCurrentBrightnessMax()).thenReturn( + BRIGHTNESS_MAX_FLOAT); + when(mBrightnessRangeController.getCurrentBrightnessMin()).thenReturn( + BRIGHTNESS_MIN_FLOAT); // Disable brightness throttling by default. Individual tests can enable it as needed. when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); when(mBrightnessThrottler.isThrottled()).thenReturn(false); diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java index 5837b21b89fd..708421d2a431 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -52,6 +52,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; @SmallTest @RunWith(AndroidJUnit4.class) @@ -376,6 +377,116 @@ public final class DisplayDeviceConfigTest { assertEquals(90, testMap.get(Temperature.THROTTLING_EMERGENCY).max, SMALL_DELTA); } + @Test + public void testValidLuxThrottling() throws Exception { + setupDisplayDeviceConfigFromDisplayConfigFile(); + + Map<DisplayDeviceConfig.BrightnessLimitMapType, Map<Float, Float>> luxThrottlingData = + mDisplayDeviceConfig.getLuxThrottlingData(); + assertEquals(2, luxThrottlingData.size()); + + Map<Float, Float> adaptiveOnBrightnessPoints = luxThrottlingData.get( + DisplayDeviceConfig.BrightnessLimitMapType.ADAPTIVE); + assertEquals(2, adaptiveOnBrightnessPoints.size()); + assertEquals(0.3f, adaptiveOnBrightnessPoints.get(1000f), SMALL_DELTA); + assertEquals(0.5f, adaptiveOnBrightnessPoints.get(5000f), SMALL_DELTA); + + Map<Float, Float> adaptiveOffBrightnessPoints = luxThrottlingData.get( + DisplayDeviceConfig.BrightnessLimitMapType.DEFAULT); + assertEquals(2, adaptiveOffBrightnessPoints.size()); + assertEquals(0.35f, adaptiveOffBrightnessPoints.get(1500f), SMALL_DELTA); + assertEquals(0.55f, adaptiveOffBrightnessPoints.get(5500f), SMALL_DELTA); + } + + @Test + public void testInvalidLuxThrottling() throws Exception { + setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getInvalidLuxThrottling())); + + Map<DisplayDeviceConfig.BrightnessLimitMapType, Map<Float, Float>> luxThrottlingData = + mDisplayDeviceConfig.getLuxThrottlingData(); + assertEquals(1, luxThrottlingData.size()); + + Map<Float, Float> adaptiveOnBrightnessPoints = luxThrottlingData.get( + DisplayDeviceConfig.BrightnessLimitMapType.ADAPTIVE); + assertEquals(1, adaptiveOnBrightnessPoints.size()); + assertEquals(0.3f, adaptiveOnBrightnessPoints.get(1000f), SMALL_DELTA); + } + + private String getValidLuxThrottling() { + return "<luxThrottling>\n" + + " <brightnessLimitMap>\n" + + " <type>adaptive</type>\n" + + " <map>\n" + + " <point>" + + " <first>1000</first>\n" + + " <second>0.3</second>\n" + + " </point>" + + " <point>" + + " <first>5000</first>\n" + + " <second>0.5</second>\n" + + " </point>" + + " </map>\n" + + " </brightnessLimitMap>\n" + + " <brightnessLimitMap>\n" + + " <type>default</type>\n" + + " <map>\n" + + " <point>" + + " <first>1500</first>\n" + + " <second>0.35</second>\n" + + " </point>" + + " <point>" + + " <first>5500</first>\n" + + " <second>0.55</second>\n" + + " </point>" + + " </map>\n" + + " </brightnessLimitMap>\n" + + "</luxThrottling>"; + } + + private String getInvalidLuxThrottling() { + return "<luxThrottling>\n" + + " <brightnessLimitMap>\n" + + " <type>adaptive</type>\n" + + " <map>\n" + + " <point>" + + " <first>1000</first>\n" + + " <second>0.3</second>\n" + + " </point>" + + " <point>" // second > hbm.transitionPoint, skipped + + " <first>1500</first>\n" + + " <second>0.9</second>\n" + + " </point>" + + " <point>" // same lux value, skipped + + " <first>1000</first>\n" + + " <second>0.5</second>\n" + + " </point>" + + " </map>\n" + + " </brightnessLimitMap>\n" + + " <brightnessLimitMap>\n" // Same type, skipped + + " <type>adaptive</type>\n" + + " <map>\n" + + " <point>" + + " <first>2000</first>\n" + + " <second>0.35</second>\n" + + " </point>" + + " <point>" + + " <first>6000</first>\n" + + " <second>0.55</second>\n" + + " </point>" + + " </map>\n" + + " </brightnessLimitMap>\n" + + " <brightnessLimitMap>\n" // Invalid points only, skipped + + " <type>default</type>\n" + + " <map>\n" + + " <point>" + + " <first>2500</first>\n" + + " <second>0.99</second>\n" + + " </point>" + + " </map>\n" + + " </brightnessLimitMap>\n" + + "</luxThrottling>"; + } + private String getRefreshThermalThrottlingMaps() { return "<refreshRateThrottlingMap>\n" + " <refreshRateThrottlingPoint>\n" @@ -405,6 +516,10 @@ public final class DisplayDeviceConfigTest { } private String getContent() { + return getContent(getValidLuxThrottling()); + } + + private String getContent(String brightnessCapConfig) { return "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<displayConfiguration>\n" + "<name>Example Display</name>" @@ -462,6 +577,7 @@ public final class DisplayDeviceConfigTest { + "</point>\n" + "</sdrHdrRatioMap>\n" + "</highBrightnessMode>\n" + + brightnessCapConfig + "<screenOffBrightnessSensor>\n" + "<type>sensor_12345</type>\n" + "<name>Sensor 12345</name>\n" @@ -731,8 +847,12 @@ public final class DisplayDeviceConfigTest { } private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException { + setupDisplayDeviceConfigFromDisplayConfigFile(getContent()); + } + + private void setupDisplayDeviceConfigFromDisplayConfigFile(String content) throws IOException { Path tempFile = Files.createTempFile("display_config", ".tmp"); - Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8)); + Files.write(tempFile, content.getBytes(StandardCharsets.UTF_8)); mDisplayDeviceConfig = new DisplayDeviceConfig(mContext); mDisplayDeviceConfig.initFromFile(tempFile.toFile()); } diff --git a/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java new file mode 100644 index 000000000000..c379d6b79ee7 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java @@ -0,0 +1,116 @@ +/* + * 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.server.display; + +import static org.junit.Assert.assertEquals; + +import android.os.PowerManager; + +import androidx.test.filters.SmallTest; + +import com.android.internal.annotations.Keep; +import com.android.server.display.DisplayDeviceConfig.BrightnessLimitMapType; + +import com.google.common.collect.ImmutableMap; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.HashMap; +import java.util.Map; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; + +@SmallTest +@RunWith(JUnitParamsRunner.class) +public class NormalBrightnessModeControllerTest { + private static final float FLOAT_TOLERANCE = 0.001f; + + private final NormalBrightnessModeController mController = new NormalBrightnessModeController(); + + @Keep + private static Object[][] brightnessData() { + return new Object[][]{ + // no brightness config + {0, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, new HashMap<>(), + PowerManager.BRIGHTNESS_MAX}, + {0, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, new HashMap<>(), + PowerManager.BRIGHTNESS_MAX}, + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, new HashMap<>(), + PowerManager.BRIGHTNESS_MAX}, + // Auto brightness - on, config only for default + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of( + BrightnessLimitMapType.DEFAULT, + ImmutableMap.of(99f, 0.1f, 101f, 0.2f) + ), 0.2f}, + // Auto brightness - off, config only for default + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of( + BrightnessLimitMapType.DEFAULT, + ImmutableMap.of(99f, 0.1f, 101f, 0.2f) + ), 0.2f}, + // Auto brightness - off, config only for adaptive + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of( + BrightnessLimitMapType.ADAPTIVE, + ImmutableMap.of(99f, 0.1f, 101f, 0.2f) + ), PowerManager.BRIGHTNESS_MAX}, + // Auto brightness - on, config only for adaptive + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of( + BrightnessLimitMapType.ADAPTIVE, + ImmutableMap.of(99f, 0.1f, 101f, 0.2f) + ), 0.2f}, + // Auto brightness - on, config for both + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of( + BrightnessLimitMapType.DEFAULT, + ImmutableMap.of(99f, 0.1f, 101f, 0.2f), + BrightnessLimitMapType.ADAPTIVE, + ImmutableMap.of(99f, 0.3f, 101f, 0.4f) + ), 0.4f}, + // Auto brightness - off, config for both + {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of( + BrightnessLimitMapType.DEFAULT, + ImmutableMap.of(99f, 0.1f, 101f, 0.2f), + BrightnessLimitMapType.ADAPTIVE, + ImmutableMap.of(99f, 0.3f, 101f, 0.4f) + ), 0.2f}, + // Auto brightness - on, config for both, ambient high + {1000, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of( + BrightnessLimitMapType.DEFAULT, + ImmutableMap.of(1000f, 0.1f, 2000f, 0.2f), + BrightnessLimitMapType.ADAPTIVE, + ImmutableMap.of(99f, 0.3f, 101f, 0.4f) + ), PowerManager.BRIGHTNESS_MAX}, + }; + } + + @Test + @Parameters(method = "brightnessData") + public void testReturnsCorrectMaxBrightness(float ambientLux, int autoBrightnessState, + Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessConfig, + float expectedBrightness) { + setupController(ambientLux, autoBrightnessState, maxBrightnessConfig); + + assertEquals(expectedBrightness, mController.getCurrentBrightnessMax(), FLOAT_TOLERANCE); + } + + private void setupController(float ambientLux, int autoBrightnessState, + Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessConfig) { + mController.onAmbientLuxChange(ambientLux); + mController.setAutoBrightnessState(autoBrightnessState); + mController.resetNbmData(maxBrightnessConfig); + } +} diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java index aa6ee09e0179..0b13f9a35c1f 100644 --- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java +++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java @@ -52,7 +52,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase { private static final int SOUND_TRIGGER_MODE = 0; // SOUND_TRIGGER_MODE_ALL_ENABLED private static final int DEFAULT_SOUND_TRIGGER_MODE = PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY; - private static final String BATTERY_SAVER_CONSTANTS = "disable_vibration=true," + private static final String BATTERY_SAVER_CONSTANTS = "disable_vibration=false," + "advertise_is_enabled=true," + "disable_animation=false," + "enable_firewall=true," @@ -117,7 +117,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase { @SmallTest public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() { - testServiceDefaultValue_On(ServiceType.VIBRATION); + testServiceDefaultValue_Off(ServiceType.VIBRATION); } @SmallTest @@ -211,7 +211,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase { private void verifyBatterySaverConstantsUpdated() { final PowerSaveState vibrationState = mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION); - assertThat(vibrationState.batterySaverEnabled).isTrue(); + assertThat(vibrationState.batterySaverEnabled).isFalse(); final PowerSaveState animationState = mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION); diff --git a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java index 6a1674b7df8e..63b8e1710b50 100644 --- a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java +++ b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java @@ -38,13 +38,16 @@ import android.os.BatteryStatsInternal; import android.os.Process; import android.os.RemoteException; +import androidx.test.filters.FlakyTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.util.FakeLatencyTracker; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.Timeout; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; @@ -52,8 +55,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(JUnit4.class) +@FlakyTest(bugId = 275746222) public class SoundTriggerMiddlewareLoggingLatencyTest { + @Rule + public Timeout mGlobalTimeout = Timeout.seconds(30); + private FakeLatencyTracker mLatencyTracker; @Mock private BatteryStatsInternal mBatteryStatsInternal; diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp index 90e61c52da68..0d2f2ef46cab 100644 --- a/tests/UiBench/Android.bp +++ b/tests/UiBench/Android.bp @@ -24,6 +24,5 @@ android_test { "androidx.recyclerview_recyclerview", "androidx.leanback_leanback", ], - certificate: "platform", test_suites: ["device-tests"], } diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml index 47211c5fbad1..4fc6ec71f29c 100644 --- a/tests/UiBench/AndroidManifest.xml +++ b/tests/UiBench/AndroidManifest.xml @@ -18,7 +18,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.android.test.uibench"> - <uses-permission android:name="android.permission.INJECT_EVENTS" /> <application android:allowBackup="false" android:theme="@style/Theme.AppCompat.Light.DarkActionBar" diff --git a/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java b/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java index 1b2c3c60ffd4..06b65a7f9bbf 100644 --- a/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java @@ -15,15 +15,11 @@ */ package com.android.test.uibench; -import android.app.Instrumentation; +import android.content.Intent; import android.os.Bundle; -import android.os.Looper; -import android.os.MessageQueue; -import androidx.appcompat.app.AppCompatActivity; -import android.view.KeyEvent; import android.widget.EditText; -import java.util.concurrent.Semaphore; +import androidx.appcompat.app.AppCompatActivity; /** * Note: currently incomplete, complexity of input continuously grows, instead of looping @@ -32,7 +28,13 @@ import java.util.concurrent.Semaphore; * Simulates typing continuously into an EditText. */ public class EditTextTypeActivity extends AppCompatActivity { - Thread mThread; + + /** + * Broadcast action: Used to notify UiBenchEditTextTypingMicrobenchmark test when the + * test activity was paused. + */ + private static final String ACTION_CANCEL_TYPING_CALLBACK = + "com.android.uibench.action.CANCEL_TYPING_CALLBACK"; private static String sSeedText = ""; static { @@ -46,9 +48,6 @@ public class EditTextTypeActivity extends AppCompatActivity { sSeedText = builder.toString(); } - final Object mLock = new Object(); - boolean mShouldStop = false; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -56,55 +55,13 @@ public class EditTextTypeActivity extends AppCompatActivity { EditText editText = new EditText(this); editText.setText(sSeedText); setContentView(editText); - - final Instrumentation instrumentation = new Instrumentation(); - final Semaphore sem = new Semaphore(0); - MessageQueue.IdleHandler handler = new MessageQueue.IdleHandler() { - @Override - public boolean queueIdle() { - // TODO: consider other signaling approaches - sem.release(); - return true; - } - }; - Looper.myQueue().addIdleHandler(handler); - synchronized (mLock) { - mShouldStop = false; - } - mThread = new Thread(new Runnable() { - int codes[] = { KeyEvent.KEYCODE_H, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_L, - KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_SPACE }; - int i = 0; - @Override - public void run() { - while (true) { - try { - sem.acquire(); - } catch (InterruptedException e) { - // TODO, maybe - } - int code = codes[i % codes.length]; - if (i % 100 == 99) code = KeyEvent.KEYCODE_ENTER; - - synchronized (mLock) { - if (mShouldStop) break; - } - - // TODO: bit of a race here, since the event can arrive after pause/stop. - // (Can't synchronize on key send, since it's synchronous.) - instrumentation.sendKeyDownUpSync(code); - i++; - } - } - }); - mThread.start(); } @Override protected void onPause() { - synchronized (mLock) { - mShouldStop = true; - } + // Cancel the typing when the test activity was paused. + sendBroadcast(new Intent(ACTION_CANCEL_TYPING_CALLBACK).addFlags( + Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY)); super.onPause(); } } diff --git a/wifi/java/src/android/net/wifi/nl80211/InstantWifi.java b/wifi/java/src/android/net/wifi/nl80211/InstantWifi.java new file mode 100644 index 000000000000..433e88c58851 --- /dev/null +++ b/wifi/java/src/android/net/wifi/nl80211/InstantWifi.java @@ -0,0 +1,318 @@ +/* + * 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 android.net.wifi.nl80211; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.AlarmManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.PowerManager; +import android.os.SystemClock; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +/** + * @hide + */ +public class InstantWifi { + private static final String INSTANT_WIFI_TAG = "InstantWifi"; + private static final int OVERRIDED_SCAN_CONNECTION_TIMEOUT_MS = 1000; + private static final int WIFI_NETWORK_EXPIRED_MS = 7 * 24 * 60 * 60 * 1000; // a week + private static final String NO_CONNECTION_TIMEOUT_ALARM_TAG = + INSTANT_WIFI_TAG + " No Connection Timeout"; + + private Context mContext; + private AlarmManager mAlarmManager; + private Handler mEventHandler; + private ConnectivityManager mConnectivityManager; + private WifiManager mWifiManager; + private PowerManager mPowerManager; + private long mLastWifiOnSinceBootMs; + private long mLastScreenOnSinceBootMs; + private boolean mIsWifiConnected = false; + private boolean mScreenOn = false; + private boolean mWifiEnabled = false; + private boolean mIsNoConnectionAlarmSet = false; + private ArrayList<WifiNetwork> mConnectedWifiNetworkList = new ArrayList<>(); + private AlarmManager.OnAlarmListener mNoConnectionTimeoutCallback = + new AlarmManager.OnAlarmListener() { + public void onAlarm() { + Log.i(INSTANT_WIFI_TAG, "Timed out waiting for wifi connection"); + mIsNoConnectionAlarmSet = false; + mWifiManager.startScan(); + } + }; + + public InstantWifi(Context context, AlarmManager alarmManager, Handler eventHandler) { + mContext = context; + mAlarmManager = alarmManager; + mEventHandler = eventHandler; + mWifiManager = mContext.getSystemService(WifiManager.class); + mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); + mConnectivityManager.registerNetworkCallback( + new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .build(), new WifiNetworkCallback()); + // System power service was initialized before wifi nl80211 service. + mPowerManager = mContext.getSystemService(PowerManager.class); + IntentFilter screenEventfilter = new IntentFilter(); + screenEventfilter.addAction(Intent.ACTION_SCREEN_ON); + screenEventfilter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver( + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(Intent.ACTION_SCREEN_ON)) { + if (!mScreenOn) { + mLastScreenOnSinceBootMs = getMockableElapsedRealtime(); + } + mScreenOn = true; + } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { + mScreenOn = false; + } + Log.d(INSTANT_WIFI_TAG, "mScreenOn is changed to " + mScreenOn); + } + }, screenEventfilter, null, mEventHandler); + mScreenOn = mPowerManager.isInteractive(); + mContext.registerReceiver( + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_UNKNOWN); + mWifiEnabled = state == WifiManager.WIFI_STATE_ENABLED; + if (mWifiEnabled) { + mLastWifiOnSinceBootMs = getMockableElapsedRealtime(); + } + Log.d(INSTANT_WIFI_TAG, "mWifiEnabled is changed to " + mWifiEnabled); + } + }, + new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION), + null, mEventHandler); + } + + @VisibleForTesting + protected long getMockableElapsedRealtime() { + return SystemClock.elapsedRealtime(); + } + + private class WifiNetwork { + private final int mNetId; + private Set<Integer> mConnectedFrequencies = new HashSet<Integer>(); + private int[] mLastTwoConnectedFrequencies = new int[2]; + private long mLastConnectedTimeMillis; + WifiNetwork(int netId) { + mNetId = netId; + } + + public int getNetId() { + return mNetId; + } + + public boolean addConnectedFrequency(int channelFrequency) { + mLastConnectedTimeMillis = getMockableElapsedRealtime(); + if (mLastTwoConnectedFrequencies[0] != channelFrequency + && mLastTwoConnectedFrequencies[1] != channelFrequency) { + mLastTwoConnectedFrequencies[0] = mLastTwoConnectedFrequencies[1]; + mLastTwoConnectedFrequencies[1] = channelFrequency; + } + return mConnectedFrequencies.add(channelFrequency); + } + + public Set<Integer> getConnectedFrequencies() { + return mConnectedFrequencies; + } + + public int[] getLastTwoConnectedFrequencies() { + if ((getMockableElapsedRealtime() - mLastConnectedTimeMillis) + > WIFI_NETWORK_EXPIRED_MS) { + return new int[0]; + } + return mLastTwoConnectedFrequencies; + } + + public long getLastConnectedTimeMillis() { + return mLastConnectedTimeMillis; + } + } + + private class WifiNetworkCallback extends NetworkCallback { + @Override + public void onAvailable(@NonNull Network network) { + } + + @Override + public void onCapabilitiesChanged(Network network, + NetworkCapabilities networkCapabilities) { + if (networkCapabilities != null && network != null) { + WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo(); + if (wifiInfo == null || mWifiManager == null) { + return; + } + WifiConfiguration config = mWifiManager.getPrivilegedConnectedNetwork(); + if (config == null) { + return; + } + final int currentNetworkId = config.networkId; + final int connectecFrequency = wifiInfo.getFrequency(); + if (connectecFrequency < 0 || currentNetworkId < 0) { + return; + } + mIsWifiConnected = true; + if (mIsNoConnectionAlarmSet) { + mAlarmManager.cancel(mNoConnectionTimeoutCallback); + } + Log.d(INSTANT_WIFI_TAG, "Receive Wifi is connected, freq = " + connectecFrequency + + " and currentNetworkId : " + currentNetworkId + + ", wifiinfo = " + wifiInfo); + boolean isExist = false; + for (WifiNetwork wifiNetwork : mConnectedWifiNetworkList) { + if (wifiNetwork.getNetId() == currentNetworkId) { + if (wifiNetwork.addConnectedFrequency(connectecFrequency)) { + Log.d(INSTANT_WIFI_TAG, "Update connected frequency: " + + connectecFrequency + " to Network currentNetworkId : " + + currentNetworkId); + } + isExist = true; + } + } + if (!isExist) { + WifiNetwork currentNetwork = new WifiNetwork(currentNetworkId); + currentNetwork.addConnectedFrequency(connectecFrequency); + if (mConnectedWifiNetworkList.size() < 5) { + mConnectedWifiNetworkList.add(currentNetwork); + } else { + ArrayList<WifiNetwork> lastConnectedWifiNetworkList = new ArrayList<>(); + WifiNetwork legacyNetwork = mConnectedWifiNetworkList.get(0); + for (WifiNetwork connectedNetwork : mConnectedWifiNetworkList) { + if (connectedNetwork.getNetId() == legacyNetwork.getNetId()) { + continue; + } + // Keep the used recently network in the last connected list + if (connectedNetwork.getLastConnectedTimeMillis() + > legacyNetwork.getLastConnectedTimeMillis()) { + lastConnectedWifiNetworkList.add(connectedNetwork); + } else { + lastConnectedWifiNetworkList.add(legacyNetwork); + legacyNetwork = connectedNetwork; + } + } + mConnectedWifiNetworkList = lastConnectedWifiNetworkList; + } + } + } + } + + @Override + public void onLost(@NonNull Network network) { + mIsWifiConnected = false; + } + } + + /** + * Returns whether or not the scan freqs should be overrided by using predicted channels. + */ + public boolean isUsePredictedScanningChannels() { + if (mIsWifiConnected || mConnectedWifiNetworkList.size() == 0 + || !mWifiManager.isWifiEnabled() || !mPowerManager.isInteractive()) { + return false; + } + if (!mWifiEnabled || !mScreenOn) { + Log.d(INSTANT_WIFI_TAG, "WiFi/Screen State mis-match, run instant Wifi anyway!"); + return true; + } + return (((getMockableElapsedRealtime() - mLastWifiOnSinceBootMs) + < OVERRIDED_SCAN_CONNECTION_TIMEOUT_MS) + || ((getMockableElapsedRealtime() - mLastScreenOnSinceBootMs) + < OVERRIDED_SCAN_CONNECTION_TIMEOUT_MS)); + } + + /** + * Overrides the frequenies in SingleScanSetting + * + * @param settings the SingleScanSettings will be overrided. + * @param freqs new frequencies of SingleScanSettings + */ + @Nullable + public void overrideFreqsForSingleScanSettingsIfNecessary( + @Nullable SingleScanSettings settings, @Nullable Set<Integer> freqs) { + if (!isUsePredictedScanningChannels() || settings == null || freqs == null + || freqs.size() == 0) { + return; + } + if (settings.channelSettings == null) { + settings.channelSettings = new ArrayList<>(); + } else { + settings.channelSettings.clear(); + } + for (int freq : freqs) { + if (freq > 0) { + ChannelSettings channel = new ChannelSettings(); + channel.frequency = freq; + settings.channelSettings.add(channel); + } + } + // Monitor connection after last override scan request. + if (mIsNoConnectionAlarmSet) { + mAlarmManager.cancel(mNoConnectionTimeoutCallback); + } + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + getMockableElapsedRealtime() + OVERRIDED_SCAN_CONNECTION_TIMEOUT_MS, + NO_CONNECTION_TIMEOUT_ALARM_TAG, mNoConnectionTimeoutCallback, mEventHandler); + mIsNoConnectionAlarmSet = true; + } + + /** + * Returns the predicted scanning chcnnels set. + */ + @NonNull + public Set<Integer> getPredictedScanningChannels() { + Set<Integer> predictedScanChannels = new HashSet<>(); + if (!isUsePredictedScanningChannels()) { + Log.d(INSTANT_WIFI_TAG, "Drop, size: " + mConnectedWifiNetworkList.size()); + return predictedScanChannels; + } + for (WifiNetwork network : mConnectedWifiNetworkList) { + for (int connectedFrequency : network.getLastTwoConnectedFrequencies()) { + if (connectedFrequency > 0) { + predictedScanChannels.add(connectedFrequency); + Log.d(INSTANT_WIFI_TAG, "Add channel: " + connectedFrequency + + " to predicted channel"); + } + } + } + return predictedScanChannels; + } +} diff --git a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java index 2a199d27a60e..ca12c4cb2020 100644 --- a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java +++ b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java @@ -105,6 +105,8 @@ public class WifiNl80211Manager { // Cached wificond binder handlers. private IWificond mWificond; + private Context mContext; + private InstantWifi mInstantWifi; private WificondEventHandler mWificondEventHandler = new WificondEventHandler(); private HashMap<String, IClientInterface> mClientInterfaces = new HashMap<>(); private HashMap<String, IApInterface> mApInterfaces = new HashMap<>(); @@ -174,6 +176,12 @@ public class WifiNl80211Manager { /** @hide */ @VisibleForTesting + protected InstantWifi getInstantWifiMockable() { + return mInstantWifi; + } + + /** @hide */ + @VisibleForTesting public class WificondEventHandler extends IWificondEventCallback.Stub { private Map<CountryCodeChangedListener, Executor> mCountryCodeChangedListenerHolder = new HashMap<>(); @@ -419,6 +427,7 @@ public class WifiNl80211Manager { public WifiNl80211Manager(Context context) { mAlarmManager = context.getSystemService(AlarmManager.class); mEventHandler = new Handler(context.getMainLooper()); + mContext = context; } /** @@ -434,6 +443,7 @@ public class WifiNl80211Manager { if (mWificond == null) { Log.e(TAG, "Failed to get reference to wificond"); } + mContext = context; } /** @hide */ @@ -441,6 +451,7 @@ public class WifiNl80211Manager { public WifiNl80211Manager(Context context, IWificond wificond) { this(context); mWificond = wificond; + mContext = context; } /** @hide */ @@ -744,6 +755,9 @@ public class WifiNl80211Manager { Log.e(TAG, "Failed to refresh wificond scanner due to remote exception"); } + if (getInstantWifiMockable() == null) { + mInstantWifi = new InstantWifi(mContext, mAlarmManager, mEventHandler); + } return true; } @@ -1071,6 +1085,10 @@ public class WifiNl80211Manager { if (settings == null) { return false; } + if (getInstantWifiMockable() != null) { + getInstantWifiMockable().overrideFreqsForSingleScanSettingsIfNecessary(settings, + getInstantWifiMockable().getPredictedScanningChannels()); + } try { return scannerImpl.scan(settings); } catch (RemoteException e1) { @@ -1115,6 +1133,10 @@ public class WifiNl80211Manager { if (settings == null) { return WifiScanner.REASON_INVALID_ARGS; } + if (getInstantWifiMockable() != null) { + getInstantWifiMockable().overrideFreqsForSingleScanSettingsIfNecessary(settings, + getInstantWifiMockable().getPredictedScanningChannels()); + } try { int status = scannerImpl.scanRequest(settings); return toFrameworkScanStatusCode(status); diff --git a/wifi/tests/src/android/net/wifi/nl80211/InstantWifiTest.java b/wifi/tests/src/android/net/wifi/nl80211/InstantWifiTest.java new file mode 100644 index 000000000000..ebff0e28082e --- /dev/null +++ b/wifi/tests/src/android/net/wifi/nl80211/InstantWifiTest.java @@ -0,0 +1,256 @@ +/* + * 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 android.net.wifi.nl80211; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.AlarmManager; +import android.app.test.TestAlarmManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.IPowerManager; +import android.os.IThermalService; +import android.os.PowerManager; +import android.os.test.TestLooper; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.HashSet; +import java.util.Set; + +/** + * Unit tests for {@link android.net.wifi.nl80211.InstantWifi}. + */ +@SmallTest +public class InstantWifiTest { + @Mock private Context mContext; + @Mock private ConnectivityManager mMockConnectivityManager; + @Mock private WifiManager mMockWifiManager; + @Mock private Network mMockWifiNetwork; + @Mock private WifiInfo mMockWifiInfo; + @Mock private WifiConfiguration mMockWifiConfiguration; + @Mock private IPowerManager mPowerManagerService; + private InstantWifi mInstantWifi; + private TestLooper mLooper; + private Handler mHandler; + private TestAlarmManager mTestAlarmManager; + private AlarmManager mAlarmManager; + private PowerManager mMockPowerManager; + + private final ArgumentCaptor<NetworkCallback> mWifiNetworkCallbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + private final ArgumentCaptor<BroadcastReceiver> mScreenBroadcastReceiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + private final ArgumentCaptor<BroadcastReceiver> mWifiStateBroadcastReceiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + + private static final int TEST_NETWORK_ID = 1; + private static final int TEST_24G_FREQUENCY = 2412; + private static final int TEST_5G_FREQUENCY = 5745; + private long mTimeOffsetMs = 0; + + private class InstantWifiSpy extends InstantWifi { + InstantWifiSpy(Context context, AlarmManager alarmManager, Handler handler) { + super(context, alarmManager, handler); + } + + @Override + protected long getMockableElapsedRealtime() { + return mTimeOffsetMs; + } + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mLooper = new TestLooper(); + mHandler = new Handler(mLooper.getLooper()); + + mTestAlarmManager = new TestAlarmManager(); + mAlarmManager = mTestAlarmManager.getAlarmManager(); + when(mContext.getSystemServiceName(AlarmManager.class)).thenReturn(Context.ALARM_SERVICE); + when(mContext.getSystemService(AlarmManager.class)).thenReturn(mAlarmManager); + when(mContext.getSystemServiceName(WifiManager.class)).thenReturn(Context.WIFI_SERVICE); + when(mContext.getSystemService(WifiManager.class)).thenReturn(mMockWifiManager); + when(mContext.getSystemServiceName(ConnectivityManager.class)) + .thenReturn(Context.CONNECTIVITY_SERVICE); + when(mContext.getSystemService(ConnectivityManager.class)) + .thenReturn(mMockConnectivityManager); + mMockPowerManager = new PowerManager(mContext, mPowerManagerService, + mock(IThermalService.class), mHandler); + when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE); + when(mContext.getSystemService(PowerManager.class)).thenReturn(mMockPowerManager); + when(mPowerManagerService.isInteractive()).thenReturn(true); + + doReturn(mMockWifiInfo).when(mMockWifiInfo).makeCopy(anyLong()); + mTimeOffsetMs = 0; + mInstantWifi = new InstantWifiSpy(mContext, mAlarmManager, mHandler); + verifyInstantWifiInitialization(); + } + + private void verifyInstantWifiInitialization() { + verify(mMockConnectivityManager).registerNetworkCallback(any(), + mWifiNetworkCallbackCaptor.capture()); + verify(mContext).registerReceiver(mScreenBroadcastReceiverCaptor.capture(), + argThat((IntentFilter filter) -> + filter.hasAction(Intent.ACTION_SCREEN_ON) + && filter.hasAction(Intent.ACTION_SCREEN_OFF)), eq(null), any()); + + verify(mContext).registerReceiver(mWifiStateBroadcastReceiverCaptor.capture(), + argThat((IntentFilter filter) -> + filter.hasAction(WifiManager.WIFI_STATE_CHANGED_ACTION)), eq(null), any()); + } + + private void mockWifiConnectedEvent(int networkId, int connectedFrequency) { + // Send wifi connected event + NetworkCapabilities mockWifiNetworkCapabilities = + new NetworkCapabilities.Builder().setTransportInfo(mMockWifiInfo).build(); + mMockWifiConfiguration.networkId = networkId; + when(mMockWifiManager.getPrivilegedConnectedNetwork()).thenReturn(mMockWifiConfiguration); + when(mMockWifiInfo.getFrequency()).thenReturn(connectedFrequency); + mWifiNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockWifiNetwork, + mockWifiNetworkCapabilities); + mLooper.dispatchAll(); + } + + private void mockWifiOnScreenOnBroadcast(boolean isWifiOn, boolean isScreenOn) + throws Exception { + // Send Wifi On broadcast + Intent wifiOnIntent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); + wifiOnIntent.putExtra(WifiManager.EXTRA_WIFI_STATE, + isWifiOn ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED); + mWifiStateBroadcastReceiverCaptor.getValue().onReceive(mContext, wifiOnIntent); + mLooper.dispatchAll(); + // Send Screen On broadcast + Intent screenOnIntent = + new Intent(isScreenOn ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF); + mScreenBroadcastReceiverCaptor.getValue().onReceive(mContext, screenOnIntent); + mLooper.dispatchAll(); + when(mMockWifiManager.isWifiEnabled()).thenReturn(isWifiOn); + when(mPowerManagerService.isInteractive()).thenReturn(isScreenOn); + } + + @Test + public void testisUsePredictedScanningChannels() throws Exception { + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + mockWifiOnScreenOnBroadcast(true /* isWifiOn */, false /* isScreenOn */); + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + mockWifiOnScreenOnBroadcast(false /* isWifiOn */, true /* isScreenOn */); + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + mockWifiOnScreenOnBroadcast(true /* isWifiOn */, true /* isScreenOn */); + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + // Send wifi connected event + mockWifiConnectedEvent(TEST_NETWORK_ID, TEST_24G_FREQUENCY); + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + // Send wifi disconnect + mWifiNetworkCallbackCaptor.getValue().onLost(mMockWifiNetwork); + assertTrue(mInstantWifi.isUsePredictedScanningChannels()); + // Shift time to make it expired + mTimeOffsetMs = 1100; + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + } + + @Test + public void testGetPredictedScanningChannels() throws Exception { + mockWifiOnScreenOnBroadcast(true /* isWifiOn */, true /* isScreenOn */); + // Send wifi connected event on T0 + mockWifiConnectedEvent(TEST_NETWORK_ID, TEST_24G_FREQUENCY); + // Send wifi disconnect + mWifiNetworkCallbackCaptor.getValue().onLost(mMockWifiNetwork); + assertTrue(mInstantWifi.isUsePredictedScanningChannels()); + assertTrue(mInstantWifi.getPredictedScanningChannels().contains(TEST_24G_FREQUENCY)); + mTimeOffsetMs += 1000; // T1 = 1000 ms + // Send wifi connected event + mockWifiConnectedEvent(TEST_NETWORK_ID + 1, TEST_5G_FREQUENCY); + // Send wifi disconnect + mWifiNetworkCallbackCaptor.getValue().onLost(mMockWifiNetwork); + // isUsePredictedScanningChannels is false since wifi on & screen on is expired + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + // Override the Wifi On & Screen on time + mockWifiOnScreenOnBroadcast(true /* isWifiOn */, true /* isScreenOn */); + assertTrue(mInstantWifi.getPredictedScanningChannels().contains(TEST_5G_FREQUENCY)); + mTimeOffsetMs += 7 * 24 * 60 * 60 * 1000; // Make T0 expired + // Override the Wifi On & Screen on time + mockWifiOnScreenOnBroadcast(true /* isWifiOn */, true /* isScreenOn */); + assertFalse(mInstantWifi.getPredictedScanningChannels().contains(TEST_24G_FREQUENCY)); + assertTrue(mInstantWifi.getPredictedScanningChannels().contains(TEST_5G_FREQUENCY)); + } + + @Test + public void testOverrideFreqsForSingleScanSettings() throws Exception { + mockWifiOnScreenOnBroadcast(true /* isWifiOn */, true /* isScreenOn */); + // Send wifi connected event + mockWifiConnectedEvent(TEST_NETWORK_ID, TEST_24G_FREQUENCY); + assertFalse(mInstantWifi.isUsePredictedScanningChannels()); + // Send wifi disconnect + mWifiNetworkCallbackCaptor.getValue().onLost(mMockWifiNetwork); + assertTrue(mInstantWifi.isUsePredictedScanningChannels()); + + final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = + ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); + doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), + alarmListenerCaptor.capture(), any()); + Set<Integer> testFreqs = Set.of( + TEST_24G_FREQUENCY, TEST_5G_FREQUENCY); + SingleScanSettings testSingleScanSettings = new SingleScanSettings(); + mInstantWifi.overrideFreqsForSingleScanSettingsIfNecessary( + testSingleScanSettings, new HashSet<Integer>()); + mInstantWifi.overrideFreqsForSingleScanSettingsIfNecessary( + testSingleScanSettings, null); + mInstantWifi.overrideFreqsForSingleScanSettingsIfNecessary(null, null); + verify(mAlarmManager, never()).set(anyInt(), anyLong(), any(), any(), any()); + mInstantWifi.overrideFreqsForSingleScanSettingsIfNecessary(testSingleScanSettings, + testFreqs); + verify(mAlarmManager).set(anyInt(), anyLong(), any(), any(), any()); + Set<Integer> overridedFreqs = new HashSet<Integer>(); + for (ChannelSettings channel : testSingleScanSettings.channelSettings) { + overridedFreqs.add(channel.frequency); + } + assertEquals(testFreqs, overridedFreqs); + alarmListenerCaptor.getValue().onAlarm(); + verify(mMockWifiManager).startScan(); + } +} diff --git a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java b/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java index 362eb1425a30..f12818fa64f9 100644 --- a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java +++ b/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java @@ -18,6 +18,7 @@ package android.net.wifi.nl80211; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -26,6 +27,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -37,6 +39,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.app.AlarmManager; +import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.app.test.TestAlarmManager; import android.content.Context; import android.net.MacAddress; @@ -104,6 +107,9 @@ public class WifiNl80211ManagerTest { private WifiNl80211Manager.CountryCodeChangedListener mCountryCodeChangedListener2; @Mock private Context mContext; + @Mock + private InstantWifi mMockInstantWifi; + private TestLooper mLooper; private TestAlarmManager mTestAlarmManager; private AlarmManager mAlarmManager; @@ -167,6 +173,17 @@ public class WifiNl80211ManagerTest { 0x00, 0x00 }; + private class WifiNl80211ManagerSpy extends WifiNl80211Manager { + WifiNl80211ManagerSpy(Context context, IWificond wificond) { + super(context, wificond); + } + + @Override + protected InstantWifi getInstantWifiMockable() { + return mMockInstantWifi; + } + } + @Before public void setUp() throws Exception { // Setup mocks for successful WificondControl operation. Failure case mocks should be @@ -181,6 +198,8 @@ public class WifiNl80211ManagerTest { mLooper = new TestLooper(); when(mContext.getMainLooper()).thenReturn(mLooper.getLooper()); + doNothing().when(mMockInstantWifi).overrideFreqsForSingleScanSettingsIfNecessary( + any(), any()); when(mWificond.asBinder()).thenReturn(mWifiCondBinder); when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl); when(mWificond.createClientInterface(any())).thenReturn(mClientInterface); @@ -189,7 +208,7 @@ public class WifiNl80211ManagerTest { when(mWificond.tearDownApInterface(any())).thenReturn(true); when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl); when(mClientInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME); - mWificondControl = new WifiNl80211Manager(mContext, mWificond); + mWificondControl = new WifiNl80211ManagerSpy(mContext, mWificond); mWificondEventHandler = mWificondControl.getWificondEventHandler(); assertEquals(true, mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME, Runnable::run, @@ -1159,6 +1178,40 @@ public class WifiNl80211ManagerTest { verify(mWificond).notifyCountryCodeChanged(); } + @Test + public void testInstantWifi() throws Exception { + doAnswer(new AnswerWithArguments() { + public void answer(SingleScanSettings settings, Set<Integer> freqs) { + if (settings.channelSettings == null) { + settings.channelSettings = new ArrayList<>(); + } else { + settings.channelSettings.clear(); + } + for (int freq : freqs) { + if (freq > 0) { + ChannelSettings channel = new ChannelSettings(); + channel.frequency = freq; + settings.channelSettings.add(channel); + } + } + } + }).when(mMockInstantWifi).overrideFreqsForSingleScanSettingsIfNecessary( + any(), any()); + Set<Integer> testPredictedChannelsSet = Set.of(2412, 5745); + assertNotEquals(testPredictedChannelsSet, SCAN_FREQ_SET); + when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true); + when(mMockInstantWifi.getPredictedScanningChannels()).thenReturn(testPredictedChannelsSet); + + // Trigger scan to check scan settings are changed + assertTrue(mWificondControl.startScan( + TEST_INTERFACE_NAME, WifiScanner.SCAN_TYPE_LOW_POWER, + SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)); + verify(mMockInstantWifi).getPredictedScanningChannels(); + verify(mWifiScannerImpl).scan(argThat(new ScanMatcher( + IWifiScannerImpl.SCAN_TYPE_LOW_POWER, + testPredictedChannelsSet, SCAN_HIDDEN_NETWORK_SSID_LIST, false, null))); + } + // Create a ArgumentMatcher which captures a SingleScanSettings parameter and checks if it // matches the provided frequency set and ssid set. private class ScanMatcher implements ArgumentMatcher<SingleScanSettings> { |