diff options
author | Xin Li <delphij@google.com> | 2024-03-06 09:30:12 -0800 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2024-03-06 18:58:26 -0800 |
commit | 0087456bf4387f83a9b6e5844fa6c30f8d8aab51 (patch) | |
tree | 4ab9ff185ba4ce7b2ed4b43736c72740b7e75af8 | |
parent | 5577e4828512373f769e69a4157f4d08d736aee2 (diff) | |
parent | 076f0ca85901b10531065985f57fa36838736aed (diff) | |
download | Telecomm-0087456bf4387f83a9b6e5844fa6c30f8d8aab51.tar.gz |
Merge Android 14 QPR2 to AOSP main
Bug: 319669529
Merged-In: Ide83e390a0f5c8f4bb25665355ff389e990dfa6f
Change-Id: I7ebff191a22f491eb9425d32956cf47c2fd9c7ea
266 files changed, 6630 insertions, 2972 deletions
diff --git a/Android.bp b/Android.bp index 70fa650cf..7a20f085e 100644 --- a/Android.bp +++ b/Android.bp @@ -29,6 +29,7 @@ android_app { static_libs: [ "androidx.annotation_annotation", "androidx.core_core", + "telecom_flags_core_java_lib", ], libs: [ "services", @@ -51,6 +52,7 @@ android_test { name: "TelecomUnitTests", static_libs: [ "android-ex-camera2", + "flag-junit", "guava", "mockito-target-extended", "androidx.test.rules", @@ -61,6 +63,7 @@ android_test { "androidx.fragment_fragment", "androidx.test.ext.junit", "platform-compat-test-rules", + "telecom_flags_core_java_lib", ], srcs: [ "tests/src/**/*.java", diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ab067d918..c6f5e9c69 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -28,7 +28,6 @@ <!-- Prevents the activity manager from delaying any activity-start requests by this package, including requests immediately after the user presses "home". --> - <uses-permission android:name="android.permission.BIND_CONNECTION_SERVICE"/> <uses-permission android:name="android.permission.BIND_INCALL_SERVICE"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> @@ -319,18 +318,6 @@ android:exported="false" android:process=":ui"/> - <service android:name=".components.BluetoothPhoneService" - android:singleUser="true" - android:process="system" - android:exported="true"> - <intent-filter> - <action android:name="android.bluetooth.IBluetoothHeadsetPhone"/> - </intent-filter> - <intent-filter> - <action android:name="android.bluetooth.IBluetoothLeCallControlCallback" /> - </intent-filter> - </service> - <service android:name=".components.TelecomService" android:singleUser="true" android:process="system" diff --git a/flags/Android.bp b/flags/Android.bp new file mode 100644 index 000000000..386831cbb --- /dev/null +++ b/flags/Android.bp @@ -0,0 +1,43 @@ +// +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +aconfig_declarations { + name: "telecom_flags", + package: "com.android.server.telecom.flags", + srcs: [ + "telecom_broadcast_flags.aconfig", + "telecom_ringer_flag_declarations.aconfig", + "telecom_api_flags.aconfig", + "telecom_call_filtering_flags.aconfig", + "telecom_incallservice_flags.aconfig", + "telecom_default_phone_account_flags.aconfig", + "telecom_callaudioroutestatemachine_flags.aconfig", + "telecom_call_flags.aconfig", + "telecom_calls_manager_flags.aconfig", + "telecom_anomaly_report_flags.aconfig", + "telecom_callaudiomodestatemachine_flags.aconfig", + "telecom_calllog_flags.aconfig", + "telecom_resolve_hidden_dependencies.aconfig", + "telecom_bluetoothroutemanager_flags.aconfig", + "telecom_work_profile_flags.aconfig", + "telecom_connection_service_wrapper_flags.aconfig", + ], +} + diff --git a/flags/telecom_anomaly_report_flags.aconfig b/flags/telecom_anomaly_report_flags.aconfig new file mode 100644 index 000000000..dbacc08c2 --- /dev/null +++ b/flags/telecom_anomaly_report_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "gen_anom_report_on_focus_timeout" + namespace: "telecom" + description: "When getCurrentFocusCall times out, generate an anom. report" + bug: "309541253" +} diff --git a/flags/telecom_api_flags.aconfig b/flags/telecom_api_flags.aconfig new file mode 100644 index 000000000..74cb447a4 --- /dev/null +++ b/flags/telecom_api_flags.aconfig @@ -0,0 +1,29 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "voip_app_actions_support" + namespace: "telecom" + description: "When set, Telecom support for additional VOIP application actions is active." + bug: "296934278" +} + +flag { + name: "call_details_id_changes" + namespace: "telecom" + description: "When set, call details/extras id updates to Telecom APIs for Android V are active." + bug: "301713560" +} + +flag { + name: "unbind_timeout_connections" + namespace: "telecom" + description: "When set, Telecom will auto-unbind if a ConnectionService returns no connections after some time." + bug: "293458004" +} + +flag{ + name: "add_call_uri_for_missed_calls" + namespace: "telecom" + description: "The key is used for dialer apps to mark missed calls as read when it gets the notification on reboot." + bug: "292597423" +} diff --git a/flags/telecom_bluetoothroutemanager_flags.aconfig b/flags/telecom_bluetoothroutemanager_flags.aconfig new file mode 100644 index 000000000..ddd8571c1 --- /dev/null +++ b/flags/telecom_bluetoothroutemanager_flags.aconfig @@ -0,0 +1,9 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "use_actual_address_to_enter_connecting_state" + namespace: "telecom" + description: "Fix bugs that may add bluetooth device with null address." + bug: "306113816" +} + diff --git a/flags/telecom_broadcast_flags.aconfig b/flags/telecom_broadcast_flags.aconfig new file mode 100644 index 000000000..348d57473 --- /dev/null +++ b/flags/telecom_broadcast_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "is_new_outgoing_call_broadcast_unblocking" + namespace: "telecom" + description: "When set, the ACTION_NEW_OUTGOING_CALL broadcast is unblocking." + bug: "224550864" +}
\ No newline at end of file diff --git a/flags/telecom_call_filtering_flags.aconfig b/flags/telecom_call_filtering_flags.aconfig new file mode 100644 index 000000000..95e74ce86 --- /dev/null +++ b/flags/telecom_call_filtering_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "skip_filter_phone_account_perform_dnd_filter" + namespace: "telecom" + description: "Gates whether to still perform Dnd filter when phone account has skip_filter call extra." + bug: "222333869" +}
\ No newline at end of file diff --git a/flags/telecom_call_flags.aconfig b/flags/telecom_call_flags.aconfig new file mode 100644 index 000000000..b5ea6a28e --- /dev/null +++ b/flags/telecom_call_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "transactional_cs_verifier" + namespace: "telecom" + description: "verify connection service callbacks via a transaction" + bug: "309541257" +}
\ No newline at end of file diff --git a/flags/telecom_callaudiomodestatemachine_flags.aconfig b/flags/telecom_callaudiomodestatemachine_flags.aconfig new file mode 100644 index 000000000..b26311378 --- /dev/null +++ b/flags/telecom_callaudiomodestatemachine_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "set_audio_mode_before_abandon_focus" + namespace: "telecom" + description: "Set audio mode to MODE_NORMAL before abandon the audio focus." + bug: "281841785" +} diff --git a/flags/telecom_callaudioroutestatemachine_flags.aconfig b/flags/telecom_callaudioroutestatemachine_flags.aconfig new file mode 100644 index 000000000..6f2c7fc7d --- /dev/null +++ b/flags/telecom_callaudioroutestatemachine_flags.aconfig @@ -0,0 +1,64 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "available_routes_never_updated_after_set_system_audio_state" + namespace: "telecom" + description: "Fix supported routes wrongly include bluetooth issue." + bug: "292599751" +} + +flag { + name: "use_refactored_audio_route_switching" + namespace: "telecom" + description: "Refactored audio routing" + bug: "306395598" +} + +flag { + name: "ensure_audio_mode_updates_on_foreground_call_change" + namespace: "telecom" + description: "Ensure that the audio mode is updated anytime the foreground call changes." + bug: "289861657" +} + +flag { + name: "ignore_auto_route_to_watch_device" + namespace: "telecom" + description: "Ignore auto routing to wearable devices." + bug: "294378768" +} + +flag { + name: "transit_route_before_audio_disconnect_bt" + namespace: "telecom" + description: "Fix audio route transition issue on call disconnection when bt audio connected." + bug: "306113816" +} + +flag { + name: "call_audio_communication_device_refactor" + namespace: "telecom" + description: "Refactor call audio set/clear communication device and include unsupported routes." + bug: "308968392" +} + +flag { + name: "communication_device_protected_by_lock" + namespace: "telecom" + description: "Protect set/clear communication device operation with lock to avoid race condition." + bug: "303001133" +} + +flag { + name: "reset_mute_when_entering_quiescent_bt_route" + namespace: "telecom" + description: "Reset mute state when entering quiescent bluetooth route." + bug: "311313250" +} + +flag { + name: "update_route_mask_when_bt_connected" + namespace: "telecom" + description: "Update supported route mask when Bluetooth devices audio connected." + bug: "301695370" +} diff --git a/flags/telecom_calllog_flags.aconfig b/flags/telecom_calllog_flags.aconfig new file mode 100644 index 000000000..3ce7b632a --- /dev/null +++ b/flags/telecom_calllog_flags.aconfig @@ -0,0 +1,15 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "telecom_log_external_wearable_calls" + namespace: "telecom" + description: "log external call if current device is a wearable one" + bug: "292600751" +} + +flag { + name: "telecom_skip_log_based_on_extra" + namespace: "telecom" + description: "skipping logging a call based on passed extra" + bug: "295530944" +} diff --git a/flags/telecom_calls_manager_flags.aconfig b/flags/telecom_calls_manager_flags.aconfig new file mode 100644 index 000000000..1a1948039 --- /dev/null +++ b/flags/telecom_calls_manager_flags.aconfig @@ -0,0 +1,15 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "use_improved_listener_order" + namespace: "telecom" + description: "Make InCallController the first listener to trigger" + bug: "24244713" +} + +flag { + name: "fix_audio_flicker_for_outgoing_calls" + namespace: "telecom" + description: "This fix ensures the MO calls won't switch from Active to Quite b/c setDialing was not called" + bug: "309540769" +} diff --git a/flags/telecom_connection_service_wrapper_flags.aconfig b/flags/telecom_connection_service_wrapper_flags.aconfig new file mode 100644 index 000000000..5f46c272a --- /dev/null +++ b/flags/telecom_connection_service_wrapper_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "updated_rcs_call_count_tracking" + namespace: "telecom" + description: "Ensure that the associatedCallCount of CS and RCS is accurately being tracked." + bug: "286154316" +}
\ No newline at end of file diff --git a/flags/telecom_default_phone_account_flags.aconfig b/flags/telecom_default_phone_account_flags.aconfig new file mode 100644 index 000000000..03f324cf3 --- /dev/null +++ b/flags/telecom_default_phone_account_flags.aconfig @@ -0,0 +1,15 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "only_update_telephony_on_valid_sub_ids" + namespace: "telecom" + description: "For testing purposes, only update Telephony when the default calling subId is non-zero" + bug: "234846282" +} + +flag { + name: "telephony_has_default_but_telecom_does_not" + namespace: "telecom" + description: "Telecom is requesting the user to select a sim account to place the outgoing call on but the user has a default account in the settings" + bug: "302397094" +}
\ No newline at end of file diff --git a/flags/telecom_incallservice_flags.aconfig b/flags/telecom_incallservice_flags.aconfig new file mode 100644 index 000000000..e1a652ba8 --- /dev/null +++ b/flags/telecom_incallservice_flags.aconfig @@ -0,0 +1,15 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "early_binding_to_incall_service" + namespace: "telecom" + description: "Binds to InCallServices when call requires no call filtering on watch" + bug: "282113261" +} + +flag { + name: "ecc_keyguard" + namespace: "telecom" + description: "Ensure that users are able to return to call from keyguard UI for ECC" + bug: "306582821" +}
\ No newline at end of file diff --git a/flags/telecom_resolve_hidden_dependencies.aconfig b/flags/telecom_resolve_hidden_dependencies.aconfig new file mode 100644 index 000000000..ecc01238a --- /dev/null +++ b/flags/telecom_resolve_hidden_dependencies.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "telecom_resolve_hidden_dependencies" + namespace: "android_platform_telecom" + description: "Mainland cleanup for hidden dependencies" + bug: "b/303440370" +} diff --git a/flags/telecom_ringer_flag_declarations.aconfig b/flags/telecom_ringer_flag_declarations.aconfig new file mode 100644 index 000000000..54748d0b0 --- /dev/null +++ b/flags/telecom_ringer_flag_declarations.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "use_device_provided_serialized_ringer_vibration" + namespace: "telecom" + description: "Gates whether to use a serialized, device-specific ring vibration." + bug: "282113261" +}
\ No newline at end of file diff --git a/flags/telecom_work_profile_flags.aconfig b/flags/telecom_work_profile_flags.aconfig new file mode 100644 index 000000000..180af5915 --- /dev/null +++ b/flags/telecom_work_profile_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "associated_user_refactor_for_work_profile" + namespace: "telecom" + description: "Redefines the associated user for calls in the context of work profile support (U+)" + bug: "315035693" +}
\ No newline at end of file diff --git a/proguard.flags b/proguard.flags index 635eba685..7c71a157b 100644 --- a/proguard.flags +++ b/proguard.flags @@ -9,17 +9,3 @@ -keep class android.telecom.Log { *; } - -# Keep classes, annotations and members used by Lifecycle. Remove this once aapt2 is enabled --keepattributes *Annotation* - --keep class * implements android.arch.lifecycle.LifecycleObserver { -} - --keep class * implements android.arch.lifecycle.GeneratedAdapter { - <init>(...); -} - --keepclassmembers class ** { - @android.arch.lifecycle.OnLifecycleEvent *; -} diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index 61381aeb4..50bead54c 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Agtergrondoproepe"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Oproepe is ontkoppel"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Omgevalde foonprogramme"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Oproepstroming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"As jy hierdie oproep maak, sal dit jou <xliff:g id="OTHER_APP">%1$s</xliff:g>-oproep beëindig."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Kies hoe om hierdie oproep te maak"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Herlei oproep deur <xliff:g id="OTHER_APP">%1$s</xliff:g> te gebruik"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Luidspreker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ekstern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Onbekend"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Stroom oudio na ander toestel"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Beëindig oproep"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Skakel hier oor"</string> </resources> diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index fc36464b8..f0923d5ca 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -90,7 +90,7 @@ <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"መመለስ እየተካሄደ ያለ የቪዲዮ ጥሪዎን ይጨርሳል"</string> <string name="answer_incoming_call" msgid="2045888814782215326">"ይመልሱ"</string> <string name="decline_incoming_call" msgid="922147089348451310">"አትቀበል"</string> - <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"የዚህን አይነት ጥሪዎች የሚደግፉ መደወያ መለያዎች ስለሌሉ ጥሪ መደረግ አይችልም።"</string> + <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"የዚህን ዓይነት ጥሪዎች የሚደግፉ መደወያ መለያዎች ስለሌሉ ጥሪ መደረግ አይችልም።"</string> <string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"በ<xliff:g id="OTHER_CALL">%1$s</xliff:g> ጥሪዎ ምክንያት ጥሪ መደረግ አይችልም።"</string> <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"በ<xliff:g id="OTHER_CALL">%1$s</xliff:g> ጥሪዎችዎ ምክንያት ጥሪዎች መደረግ አይችሉም።"</string> <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"በሌላ መተግበሪያ ውስጥ ባለ ጥሪ ምክንያት ጥሪ መደረግ አይችልም።"</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"የጀርባ ጥሪዎች"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"የተቋረጡ ጥሪዎች"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"የተበላሹ የስልክ መተግበሪያዎች"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"የጥሪ ዥረት"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ይህን ጥሪ ማድረግ የ<xliff:g id="OTHER_APP">%1$s</xliff:g> ጥሪዎን ያቋርጣል።"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ይህን ጥሪ እንዴት እንደሚያደርጉ ይምረጡ"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g>ን በመጠቀም አዘዋውር"</string> @@ -127,7 +128,10 @@ <string name="callendpoint_name_earpiece" msgid="7047285080319678594">"ማዳመጫ"</string> <string name="callendpoint_name_bluetooth" msgid="210210953208913172">"ብሉቱዝ"</string> <string name="callendpoint_name_wiredheadset" msgid="6860787176412079742">"ባለገመድ ማዳመጫ"</string> - <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ድምጽ ማውጫ"</string> + <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ድምፅ ማውጫ"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ውጫዊ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"ያልታወቀ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ኦዲዮን ወደ ሌላ መሣሪያ በመልቀቅ ላይ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ዝጋ"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"እዚህ ቀይር"</string> </resources> diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index b9f8842e0..2a568091b 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"مكالمات في الخلفية"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"المكالمات التي تم قطع الاتصال بها"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"تطبيقات الهواتف المعطّلة"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"بث المكالمات"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"يؤدي إجراء هذه المكالمة إلى إنهاء مكالمة <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"اختيار كيفية إجراء هذه المكالمة"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"إعادة توجيه المكالمة باستخدام <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"مكبّر صوت"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"المصادر الخارجية"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"غير معروف"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"بث الصوت على جهاز آخر"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"قطع الاتصال"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"الانتقال إلى هنا"</string> </resources> diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index 922659925..72ac4dbb9 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"নেপথ্যৰ কলসমূহ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"সংযোগ বিচ্ছিন্ন কৰা কলসমূহ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ক্ৰেশ্ব হোৱা ফ\'ন এপ্সমূহ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"কল ষ্ট্ৰীমিং"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"এই কলটো কৰিলে আপোনাৰ <xliff:g id="OTHER_APP">%1$s</xliff:g> কলটোৰ অন্ত পৰিব।"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"এই কলটো কেনেকৈ কৰা হ’ব সেয়া বাছনি কৰক"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ব্যৱহাৰ কৰি কল ৰিডাইৰেক্ট কৰক"</string> @@ -108,7 +109,7 @@ <string name="phone_settings_call_blocking_txt" msgid="7311523114822507178">"কল অৱৰোধ"</string> <string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"আপোনাৰ সর্ম্পকসূচীত নথকা"</string> <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"আপোনাৰ সর্ম্পকসূচীত নথকা নম্বৰ অৱৰোধ কৰক"</string> - <string name="phone_settings_private_num_txt" msgid="6339272760338475619">"ব্য়ক্তিগত"</string> + <string name="phone_settings_private_num_txt" msgid="6339272760338475619">"ব্যক্তিগত"</string> <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"যিসকল কল কৰোঁতাই তেওঁলোকৰ নম্বৰ প্ৰকাশ নকৰে তেওঁলোকক অৱৰোধ কৰক"</string> <string name="phone_settings_payphone_txt" msgid="5003987966052543965">"পে\'ফ\'ন"</string> <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"পে\'ফ\'নৰ পৰা অহা কল অৱৰোধ কৰক"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"স্পীকাৰ"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"বাহ্যিক"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"অজ্ঞাত"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"অন্য এটা ডিভাইচলৈ অডিঅ’ ষ্ট্ৰীম কৰি থকা হৈছে"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"কলটো কাটি দিয়ক"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ইয়াত সলনি কৰক"</string> </resources> diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index d2368fadf..ead7f5433 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Arxa fon zəngləri"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Kəsilmiş zənglər"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Tətbiq xətaları"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Zəng yayımı"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Bu zəngin yerləşdirilməsi <xliff:g id="OTHER_APP">%1$s</xliff:g> zəngini sonlandıracaq."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Bu zəngi necə etməyi seçin"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> istifadə edərək zəngi yönləndirin"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Dinamik"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Xarici"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Naməlum"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Audio digər cihaza ötürülür"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Zəngi sonlandırın"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Buraya keçin"</string> </resources> diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index f77b0bbbf..d5278427b 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Pozivi u pozadini"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Prekinuti pozivi"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplikacije za telefoniranje koje su otkazale"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Strimovanje poziva"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ako uputite ovaj poziv, završićete <xliff:g id="OTHER_APP">%1$s</xliff:g> poziv."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Izaberite kako želite da uputite ovaj poziv"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Preusmeri poziv pomoću: <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Zvučnik"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Eksterni"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Nepoznato"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Zvuk se strimuje na drugi uređaj"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Prekini vezu"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Prebaci ovde"</string> </resources> diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 8560c9cf2..c5b59bddd 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Фонавыя выклікі"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Перарваныя выклікі"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Збоі ў праграмах \"Тэлефон\""</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Перадача выкліку плынню"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Калі зрабіць гэты выклік, ваш выклік праз праграму <xliff:g id="OTHER_APP">%1$s</xliff:g> скончыцца."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Выберыце, праз які нумар зрабіць выклік"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Перанакіраваць выклік, выкарыстоўваючы нумар \"<xliff:g id="OTHER_APP">%1$s</xliff:g>\""</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Знешні дынамік"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Знешняя прылада"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Невядома"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Перадача аўдыя плынню на іншую прыладу"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Завяршыць выклік"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Пераключыцца"</string> </resources> diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index c99dcd070..fe5d70f56 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Обаждания на заден план"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Прекъснати обаждания"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Приложения за телефон с прекъсната работа"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Поточно предаване на обаждания"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ако извършите това обаждане, обаждането ви през <xliff:g id="OTHER_APP">%1$s</xliff:g> ще прекъсне."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Изберете как да се извърши обаждането"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Пренасочване на обаждането през <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Високоговорител"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Външно"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Неизвестно"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Звукът се предава поточно към друго устройство"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Затваряне"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Превключете тук"</string> </resources> diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 01b67f0a9..49e6ba320 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ব্যাকগ্রাউন্ডের কল"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ডিসকানেক্ট করা কলগুলি"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ক্র্যাশ হওয়া ফোন অ্যাপ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"কল স্ট্রিম করা হচ্ছে"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"এই কলটির উত্তর দেওয়া হলে তা আপনার <xliff:g id="OTHER_APP">%1$s</xliff:g> কলটি কেটে যাবে৷"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"এই কলটি কীভাবে করবেন বেছে নিন"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ব্যবহার করে কল রিডাইরেক্ট করুন"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"স্পিকার"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"এক্সটার্নাল"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"অজানা"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"অন্য ডিভাইসে অডিও স্ট্রিম করা হচ্ছে"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"কল কেটে দিন"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"এখানে পাল্টান"</string> </resources> diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 201d8d12e..61b86db16 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Pozivi u pozadini"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Prekinuti pozivi"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Padovi aplikacija za telefon"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Prijenos poziva"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Upućivanje ovog poziva će prekinuti poziv: <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Odaberite kako želite uputiti ovaj poziv"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Preusmjeri poziv pomoću aplikacije <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Zvučnik"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Vanjski"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Nepoznato"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Prijenos zvuka na drugom uređaju"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Prekini vezu"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Prebaci ovdje"</string> </resources> diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 2c5727d8d..113d14428 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Trucades en segon pla"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Trucades desconnectades"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplicacions del telèfon que han fallat"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Reproducció en directe de trucada"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"En fer aquesta trucada, finalitzarà la de l\'aplicació <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Tria com vols fer aquesta trucada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Desvia la trucada amb <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Altaveu"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Extern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Desconegut"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"S\'està reproduint àudio en continu en un altre dispositiu"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Penja"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Canvia aquí"</string> </resources> diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 2945d28e2..ab74d613a 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Hovory na pozadí"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Odpojené hovory"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplikace, které spadly"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streamování hovoru"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Uskutečněním tohoto hovoru ukončíte hovor <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Vyberte, jak chcete tento hovor provést"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Přesměrovat hovor přes aplikaci <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Reproduktor"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externí"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Není známo"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streamování zvuku do druhého zařízení"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Zavěsit"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Přepnout sem"</string> </resources> diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 366b58483..4eead6668 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -73,7 +73,7 @@ <string name="non_primary_user" msgid="315564589279622098">"Det er kun ejeren af en enhed, der kan se og administrere blokerede numre."</string> <string name="delete_icon_description" msgid="5335959254954774373">"Fjern blokering"</string> <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"Blokering er midlertidigt slået fra"</string> - <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"Når du har ringet eller sendt en sms-besked til alarmcentralen, bliver blokering slået fra for at sikre, at alarmcentralen kan komme i kontakt med dig."</string> + <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"Når du har ringet eller sendt en besked til alarmcentralen, bliver blokering slået fra for at sikre, at alarmcentralen kan komme i kontakt med dig."</string> <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"Genaktiver nu"</string> <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> blev blokeret"</string> <string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"Blokeringen af <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> blev ophævet"</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Opkald i baggrunden"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Afbrudte opkald"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Opkaldsapps, der er gået ned"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Opkaldsstreaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Hvis du foretager dette opkald, afsluttes dit opkald i <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Vælg, hvordan du vil foretage dette opkald"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Omdiriger opkaldet ved hjælp af <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Højttaler"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ekstern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Ukendt"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streamer lyd til en anden enhed"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Læg på"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Skift hertil"</string> </resources> diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 801321bec..dccdb87c0 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Anrufe im Hintergrund"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Beendete Anrufe"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Abgestürzte Telefon-Apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Anrufstreaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Durch diesen Anruf wird der Anruf in <xliff:g id="OTHER_APP">%1$s</xliff:g> beendet."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Wie möchtest du anrufen?"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Mit <xliff:g id="OTHER_APP">%1$s</xliff:g> weiterleiten"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Lautsprecher"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Extern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Unbekannt"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Audio auf einem anderen Gerät streamen"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Anruf beenden"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Auf dieses Gerät wechseln"</string> </resources> diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 7a09f0adc..6b58863e8 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -100,7 +100,8 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Κλήσεις στο παρασκήνιο"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Αποσυνδεδεμένες κλήσεις"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Εφαρμογές τηλεφώνου που αντιμετώπισαν σφάλμα λειτουργίας"</string> - <string name="alert_outgoing_call" msgid="5319895109298927431">"Εάν πραγματοποιήσετε αυτήν την κλήση, η κλήση σας μέσω <xliff:g id="OTHER_APP">%1$s</xliff:g> θα τερματιστεί."</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Ροή κλήσης"</string> + <string name="alert_outgoing_call" msgid="5319895109298927431">"Εάν πραγματοποιήσετε αυτή την κλήση, η κλήση σας μέσω <xliff:g id="OTHER_APP">%1$s</xliff:g> θα τερματιστεί."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Επιλέξτε πώς θα πραγματοποιήσετε την κλήση"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Ανακατεύθυνση της κλήσης μέσω <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> <string name="alert_place_unredirect_outgoing_call" msgid="2467608535225764006">"Κλήση μέσω του αριθμού τηλεφώνου μου"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Ηχείο"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Εξωτερικά"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Άγνωστο"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Ροή ήχου σε άλλη συσκευή"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Απόρριψη"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Εναλλαγή εδώ"</string> </resources> diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 024940155..250ab62ed 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Background calls"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Disconnected calls"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Crashed phone apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Call streaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to make this call"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirect call using <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"External"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Unknown"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio to other device"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Hang up"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Switch here"</string> </resources> diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index 5f857c1e9..e6291f47b 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Background calls"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Disconnected calls"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Crashed phone apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Call streaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to place this call"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirect call using <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"External"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Unknown"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio to other device"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Hang up"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Switch here"</string> </resources> diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 024940155..250ab62ed 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Background calls"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Disconnected calls"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Crashed phone apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Call streaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to make this call"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirect call using <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"External"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Unknown"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio to other device"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Hang up"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Switch here"</string> </resources> diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 024940155..250ab62ed 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Background calls"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Disconnected calls"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Crashed phone apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Call streaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to make this call"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirect call using <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"External"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Unknown"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio to other device"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Hang up"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Switch here"</string> </resources> diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index 2ffae8773..5bd0e25eb 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Background calls"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Disconnected calls"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Crashed phone apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Call streaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to place this call"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirect call using <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"External"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Unknown"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio to other device"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Hang up"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Switch here"</string> </resources> diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index ab8f4547f..c0f4e179a 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Llamadas en segundo plano"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Llamadas desconectadas"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Apps de teléfono con fallas"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Transmisión de llamadas"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Si realizas esta llamada, finalizará la de <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Elige cómo quieres realizar esta llamada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redireccionar la llamada mediante <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Bocina"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externa"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Desconocido"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Transmitiendo el audio a otro dispositivo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Colgar"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Cambiar aquí"</string> </resources> diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 65ab62751..20b80a5e1 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Llamadas en segundo plano"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Llamadas interrumpidas"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplicaciones para teléfonos con fallos"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Transmisión de llamadas"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Si haces esta llamada, se finalizará la de <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Elige cómo quieres hacer esta llamada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirigir llamada con <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Altavoz"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Fuentes externas"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Desconocido"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Transmitiendo audio a otro dispositivo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Colgar"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Cambiar aquí"</string> </resources> diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 7d9ad7b88..cac1fd6d3 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Taustal olevad kõned"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Katkestatud kõned"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Kokkujooksnud telefonirakendused"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Kõne voogesitus"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Selle kõne tegemisel lõpetatakse pooleliolev kõne rakenduses <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Valige, kuidas soovite helistada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Suuna kõne ümber rakenduse <xliff:g id="OTHER_APP">%1$s</xliff:g> abil"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Kõlar"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Välised"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Teadmata"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Heli voogesitamine teise seadmesse"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Lõpeta kõne"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Vaheta siia"</string> </resources> diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 64645a44e..d1aa5457e 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -47,7 +47,7 @@ <string name="respond_via_sms_failure_format" msgid="5198680980054596391">"Ezin izan da bidali mezua <xliff:g id="PHONE_NUMBER">%s</xliff:g> zenbakira."</string> <string name="enable_account_preference_title" msgid="6949224486748457976">"Deiak egiteko kontuak"</string> <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"Larrialdi-deiak bakarrik egin daitezke."</string> - <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"Aplikazioak deitu ahal izan dezan, telefonoaren eginbidea erabiltzeko baimena behar du."</string> + <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"Aplikazioak irteerako deiak egin ahal izan ditzan, telefonoaren eginbidea erabiltzeko baimena behar du."</string> <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"Deitzeko, idatzi balio duen zenbaki bat."</string> <string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"Une honetan ezin da deirik gehitu."</string> <string name="no_vm_number" msgid="2179959110602180844">"Erantzungailuaren zenbakia falta da"</string> @@ -94,12 +94,13 @@ <string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"Ezin da egin deia, beste dei bat abian delako <xliff:g id="OTHER_CALL">%1$s</xliff:g> zerbitzuan."</string> <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"Ezin da egin deia, beste dei batzuk abian direlako <xliff:g id="OTHER_CALL">%1$s</xliff:g> zerbitzuan."</string> <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"Ezin da egin deia, beste dei bat abian delako beste aplikazio batean."</string> - <string name="notification_channel_incoming_call" msgid="5245550964701715662">"Jasotako deiak"</string> + <string name="notification_channel_incoming_call" msgid="5245550964701715662">"Sarrerako deiak"</string> <string name="notification_channel_missed_call" msgid="7168893015283909012">"Dei galduak"</string> <string name="notification_channel_call_blocking" msgid="2028807677868598710">"Deiak blokeatzeko aukera"</string> <string name="notification_channel_background_calls" msgid="7785659903711350506">"Atzeko planoko deiak"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Deskonektatutako deiak"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Huts egin duten telefonoko aplikazioak"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Deiak igortzea"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Dei hau egiten baduzu, amaitu egingo da <xliff:g id="OTHER_APP">%1$s</xliff:g> aplikazioko deia."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Aukeratu dei hau egiteko modua"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Birbideratu deia <xliff:g id="OTHER_APP">%1$s</xliff:g> aplikazioaren bidez"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Bozgorailua"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Kanpokoa"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Ezezaguna"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Audioa beste gailu batera igortzen ari da"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Amaitu deia"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Aldatu hona"</string> </resources> diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 83c80347a..8d562ec30 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"تماسهای پسزمینه"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"تماسهای قطعشده"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"برنامههای تلفن خراب"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"جاریسازی تماس"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"اگر این تماس را برقرار کنید، تماس <xliff:g id="OTHER_APP">%1$s</xliff:g> شما قطع میشود."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"انتخاب نحوه برقراری این تماس"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"هدایت تماس با استفاده از <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"بلندگو"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"خارجی"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"نامشخص"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"درحال جاریسازی صدا به دستگاه دیگر"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"قطع تماس"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"انتقال در اینجا انجام شود"</string> </resources> diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 4ade7d1dd..338e42921 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Taustapuhelut"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Katkaistut puhelut"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Kaatuneet puhelinsovellukset"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Puhelunstriimaus"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Tämän puhelun soittaminen päättää puhelun sovelluksessa <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Valitse, miten puhelu soitetaan"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Uudelleenohjaa puhelu sovelluksella <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Kaiutin"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ulkoinen"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Tuntematon"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Audiota striimataan toiselle laitteelle"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Lopeta puhelu"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Vaihda puhelimeen"</string> </resources> diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 95b2069da..aaf651f9c 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Appels en arrière-plan"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Appels déconnectés"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Applications téléphoniques qui ont planté"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Diffusion en continu d\'appels"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Si vous passez cet appel, vous mettrez fin à l\'appel <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choisissez comment passer cet appel"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Rediriger l\'appel en utilisant <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Haut-parleur"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externe"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Inconnu"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Diffusion audio en continu vers un autre appareil en cours…"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Raccrocher"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Revenir à cet appareil"</string> </resources> diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 03f6d877b..a14cbb13c 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Appels en arrière-plan"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Appels interrompus"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Applications téléphoniques ayant planté"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming de l\'appel"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Si vous passez cet appel, vous mettrez fin à celui qui est en cours dans l\'application <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choisissez comment passer cet appel"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Rediriger l\'appel avec <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Haut-parleur"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externe"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Inconnu"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming de l\'audio sur un autre appareil"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Raccrocher"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Passer ici"</string> </resources> diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index a8443dd58..8e82fcec2 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Chamadas en segundo plano"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Chamadas desconectadas"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Fallaron as aplicacións de teléfono"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Propagación de chamada"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ao facer esta chamada, finalizarase o túa chamada de <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Escolle como facer esta chamada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirixir a chamada con <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Altofalante"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externo"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Descoñecido"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Emitindo audio noutro dispositivo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Colgar"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Volver aquí"</string> </resources> diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 4af6351f5..1b5c5ce5a 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -25,7 +25,7 @@ <string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> ચૂકી ગયેલા કૉલ"</string> <string name="notification_missedCallTicker" msgid="6731461957487087769">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g> નો કૉલ ચૂકી ગયાં"</string> <string name="notification_missedCall_call_back" msgid="7900333283939789732">"કૉલ બેક"</string> - <string name="notification_missedCall_message" msgid="4054698824390076431">"સંદેશ"</string> + <string name="notification_missedCall_message" msgid="4054698824390076431">"મેસેજ"</string> <string name="notification_disconnectedCall_title" msgid="1790131923692416928">"ડિસ્કનેક્ટ કરેલો કૉલ"</string> <string name="notification_disconnectedCall_body" msgid="600491714584417536">"ઇમર્જન્સી કૉલને કારણે <xliff:g id="CALLER">%s</xliff:g>નો કૉલ ડિસ્કનેક્ટ કરવામાં આવ્યો છે."</string> <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ઇમર્જન્સી કૉલને કારણે તમારો કૉલ ડિસ્કનેક્ટ કરવામાં આવ્યો છે."</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"બૅકગ્રાઉન્ડ કૉલ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ડિસ્કનેક્ટ કરેલા કૉલ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ફોન ઍપ ક્રૅશ થઈ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"કૉલ સ્ટ્રીમ કરી રહ્યાં છીએ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"આ કૉલ કરવાથી તમારો <xliff:g id="OTHER_APP">%1$s</xliff:g> કૉલ સમાપ્ત થઈ જશે."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"આ કૉલ કેવી રીતે કરવો તે પસંદ કરો"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g>નો ઉપયોગ કરીને કૉલ રીડાયરેક્ટ કરો"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"સ્પીકર"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"બાહ્ય"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"અજાણ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ઑડિયોને અન્ય ડિવાઇસ પર સ્ટ્રીમ કરી રહ્યાં છીએ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"સમાપ્ત કરો"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"અહીં સ્વિચ કરો"</string> </resources> diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 918051abf..c32f58268 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"बैकग्राउंड कॉल"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"डिसकनेक्ट किए गए कॉल"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"फ़ोन ऐप्लिकेशन जो बंद हो गए"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"कॉल स्ट्रीमिंग"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"इस कॉल को करने से आपका <xliff:g id="OTHER_APP">%1$s</xliff:g> कॉल खत्म हो जाएगा."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"चुनें कि आप इस कॉल को कैसे करना चाहते हैं"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> का इस्तेमाल करके कॉल को दूसरे नंबर पर भेजें"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"स्पीकर"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"बाहरी सोर्स"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"कोई जानकारी नहीं है"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ऑडियो को दूसरे डिवाइस पर स्ट्रीम किया जा रहा है"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"कॉल खत्म करें"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"यहां स्विच करें"</string> </resources> diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 02c91fb1b..d6b209e08 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Pozivi u pozadini"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Prekinuti pozivi"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Rušenja aplikacija telefona"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming poziva"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Upućivanjem ovog poziva prekinut ćete poziv u aplikaciji <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Odaberite kako ćete uputiti poziv"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Preusmjeri poziv putem aplikacije <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Zvučnik"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Vanjski izvori"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Nepoznato"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming zvuka na drugi uređaj"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Prekini vezu"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Promijeni ovdje"</string> </resources> diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index cdda34a20..63f04b653 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Háttérbeli hívások"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Bontott hívások"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Telefonalkalmazások összeomlása"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Hívás átvitele"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ha hívást indít, azzal megszakítja a(z) <xliff:g id="OTHER_APP">%1$s</xliff:g>-hívást."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"A hívás módjának kiválasztása"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Hívás átirányítása a következővel: <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Hangszóró"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Külső"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Ismeretlen"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Hang átvitele másik eszközre"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Hívás befejezése"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Váltás itt"</string> </resources> diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index d85d0377f..169ea3602 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Ֆոնային զանգեր"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Անջատված զանգեր"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Հեռախոսի հավելվածներ, որոնց աշխատանքը սխալի պատճառով խափանվել է"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Զանգի հեռարձակում"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Այս զանգը կատարելու դեպքում <xliff:g id="OTHER_APP">%1$s</xliff:g>-ի ընթացիկ զանգը կընդհատվի"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Ընտրեք, թե ինչպես եք ուզում կատարել այս զանգը"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Վերահասցեավորել զանգը <xliff:g id="OTHER_APP">%1$s</xliff:g> հավելվածով"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Բարձրախոս"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Արտաքին"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Անհայտ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Աուդիոյի հեռարձակում այլ սարքում"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Ավարտել զանգը"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Անցնել այստեղ"</string> </resources> diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 84c0d399e..1e51f7a66 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Panggilan telepon latar belakang"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Panggilan terputus"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplikasi telepon error"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming panggilan"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Melakukan panggilan ini akan mengakhiri panggilan <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Pilih cara melakukan panggilan ini"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Alihkan panggilan menggunakan <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Eksternal"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Tidak diketahui"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio ke perangkat lain"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Akhiri"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Beralih ke sini"</string> </resources> diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index db7dbeb82..7009b7cb9 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Bakgrunnssímtöl"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Aftengd símtöl"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Hrun í símaforritum"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Símtal í streymi"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ef þú hringir mun þessu símtali í <xliff:g id="OTHER_APP">%1$s</xliff:g> ljúka."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Veldu hvernig hringt er"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Framsenda símtal með <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Hátalari"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ytra tæki"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Óþekkt"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streymir hljóði í annað tæki"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Leggja á"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Skipta hingað"</string> </resources> diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index ad070d629..4a17d18c4 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Chiamate in sottofondo"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Chiamate disconnesse"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"App per telefono arrestate in modo anomalo"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming chiamata"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Se effettui questa chiamata, la chiamata di <xliff:g id="OTHER_APP">%1$s</xliff:g> verrà terminata."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Scegli come effettuare questa chiamata"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Reindirizza la chiamata utilizzando <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Vivavoce"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Esterno"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Sconosciuto"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio all\'altro dispositivo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Riaggancia"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Passa qui"</string> </resources> diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index d557599df..05ec712b0 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"שיחות ברקע"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"שיחות שנותקו"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"אפליקציות טלפון שקרסו"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"העברת השיחה"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ביצוע השיחה הזו יסיים את השיחה ב-<xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"איך להתקשר?"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"ניתוב דרך <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"רמקול"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"מכשיר חיצוני"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"לא ידוע"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"הקול מושמע במכשיר אחר"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ניתוק"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"העברת השיחה בחזרה לטלפון"</string> </resources> diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 73b85d977..19387ffb5 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"バックグラウンドでの通話"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"通話の切断"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"通話アプリがクラッシュしたとき"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"通話ストリーミング"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"この通話を発信すると、<xliff:g id="OTHER_APP">%1$s</xliff:g> の通話が終了します。"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"通話の発信方法を選択してください"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> を使用して通話をリダイレクト"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"スピーカー"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"外部"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"不明"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"他のデバイスに音声をストリーミングしています"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"通話を終了"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"このデバイスに切り替える"</string> </resources> diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index 33c5a47e5..d56873f25 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ზარები ფონში"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"გათიშული ზარები"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ავარიულად გათიშული ტელეფონის აპები"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"ზარის სტრიმინგი"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ამ ზარის განხორციელება თქვენს <xliff:g id="OTHER_APP">%1$s</xliff:g> ზარს დაასრულებს."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"აირჩიეთ, როგორ განათავსოთ ეს ზარი"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"ზარის გადამისამართება <xliff:g id="OTHER_APP">%1$s</xliff:g>-ის გამოყენებით"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"დინამიკი"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"გარე"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"უცნობი"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"მიმდინარეობს აუდიოს სტრიმინგი სხვა მოწყობილობაზე"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"გათიშვა"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"გადართვა"</string> </resources> diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 7c0765447..399da2030 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -69,16 +69,16 @@ <string name="unblock_button" msgid="8732021675729981781">"Бөгеуден шығару"</string> <string name="add_blocked_dialog_body" msgid="8599974422407139255">"Қоңыраулары мен мәтіндік хабарлары бөгелетін нөмір"</string> <string name="add_blocked_number_hint" msgid="8769422085658041097">"Телефон нөмірі"</string> - <string name="block_button" msgid="485080149164258770">"Бөгеу"</string> + <string name="block_button" msgid="485080149164258770">"Блоктау"</string> <string name="non_primary_user" msgid="315564589279622098">"Бөгелген нөмірлерді тек құрылғы иесі көре және басқара алады."</string> <string name="delete_icon_description" msgid="5335959254954774373">"Бөгеуді алу"</string> <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"Тыйым уақытша алынды"</string> <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"Төтенше жағдай нөмірін терген немесе мәтіндік хабар жіберген соң, төтенше жағдай қызметтері сізге хабарласа алуы үшін тыйым алынады."</string> <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"Қазір қайта қосу"</string> - <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> бөгелген"</string> + <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> блокталған"</string> <string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> бөгеуден шығарылды"</string> <string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"Жедел қызмет нөмірін бөгеу мүмкін емес."</string> - <string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> бұрыннан бөгелген."</string> + <string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> бұрыннан блокталған."</string> <string name="toast_personal_call_msg" msgid="5817631570381795610">"Қоңырау шалу үшін жеке нөмір тергішті пайдалану"</string> <string name="notification_incoming_call" msgid="1233481138362230894">"<xliff:g id="CALL_VIA">%1$s</xliff:g> қоңырауы: <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string> <string name="notification_incoming_video_call" msgid="5795968314037063900">"<xliff:g id="CALL_VIA">%1$s</xliff:g> бейне қоңырауы: <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Фондық қоңыраулар"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Ажыратылған қоңыраулар"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Бұзылған телефон қолданбалары"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Қоңырауды трансляциялау"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Жаңа қоңырау шалу <xliff:g id="OTHER_APP">%1$s</xliff:g> қоңырауын тоқтатады."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Қоңырау шалу әдісін таңдаңыз."</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Қоңырау бағытын <xliff:g id="OTHER_APP">%1$s</xliff:g> арқылы ауыстыру"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Динамик"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Сыртқы"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Белгісіз"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Аудионы басқа құрылғыға трансляциялау"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Қоңырауды аяқтау"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Осы жерде ауысу"</string> </resources> diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index 64e47ef94..1c28d3711 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ការហៅនៅផ្ទៃខាងក្រោយ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ការហៅទូរសព្ទដែលបានផ្ដាច់"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"កម្មវិធីទូរសព្ទគាំង"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"មុខងារផ្សាយការហៅទូរសព្ទ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ការហៅទូរសព្ទនេះ នឹងបញ្ចប់ការហៅ <xliff:g id="OTHER_APP">%1$s</xliff:g> របស់អ្នក។"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ជ្រើសរើសរបៀបធ្វើការហៅទូរសព្ទនេះ"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"បញ្ជូនការហៅទូរសព្ទបន្តដោយប្រើប្រាស់ <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ឧបករណ៍បំពងសំឡេង"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ខាងក្រៅ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"មិនស្គាល់"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"កំពុងផ្សាយសំឡេងទៅឧបករណ៍ផ្សេងទៀត"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"បញ្ចប់ការហៅទូរសព្ទ"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ប្ដូរនៅទីនេះ"</string> </resources> diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 8109de26b..cbaa2036b 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -53,7 +53,7 @@ <string name="no_vm_number" msgid="2179959110602180844">"ಧ್ವನಿಮೇಲ್ ಸಂಖ್ಯೆಯು ಕಾಣೆಯಾಗಿದೆ"</string> <string name="no_vm_number_msg" msgid="1339245731058529388">"ಸಿಮ್ ಕಾರ್ಡ್ನಲ್ಲಿ ಯಾವುದೇ ಧ್ವನಿಮೇಲ್ ಸಂಖ್ಯೆಯನ್ನು ಸಂಗ್ರಹಿಸಿಲ್ಲ."</string> <string name="add_vm_number_str" msgid="5179510133063168998">"ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ"</string> - <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"<xliff:g id="NEW_APP">%s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಡಿಫಾಲ್ಟ್ ಫೋನ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿ ಮಾಡುವುದೇ?"</string> + <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"<xliff:g id="NEW_APP">%s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಡಿಫಾಲ್ಟ್ ಫೋನ್ ಆ್ಯಪ್ ಆಗಿ ಮಾಡಬೇಕೆ?"</string> <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"ಡಿಫಾಲ್ಟ್ ಹೊಂದಿಸಿ"</string> <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"ರದ್ದುಮಾಡಿ"</string> <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> ಗೆ ನಿಮ್ಮ ಕರೆಗಳ ಎಲ್ಲಾ ಅಂಶಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ಮತ್ತು ಕರೆಗಳನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ. ನೀವು ವಿಶ್ವಾಸವಿರಿಸಿರುವಂತಹ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಮಾತ್ರ ನಿಮ್ಮ ಡಿಫಾಲ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿ ಹೊಂದಿಸಬೇಕು."</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ಹಿನ್ನೆಲೆ ಕರೆಗಳು"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಲಾದ ಕರೆಗಳು"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ಕ್ರ್ಯಾಶ್ ಆಗಿರುವ ಫೋನ್ ಆ್ಯಪ್ಗಳು"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"ಕರೆ ಸ್ಟ್ರೀಮಿಂಗ್"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ಈ ಕರೆಯನ್ನು ಮಾಡುವುದರಿಂದ ನಿಮ್ಮ <xliff:g id="OTHER_APP">%1$s</xliff:g> ಕರೆಯು ಅಂತ್ಯಗೊಳ್ಳುತ್ತದೆ."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ಈ ಕರೆ ಮಾಡುವುದು ಹೇಗೆ ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ಬಳಸಿಕೊಂಡು ಕರೆಯನ್ನು ಮರುನಿರ್ದೇರ್ಶಿಸಿ"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ಸ್ಪೀಕರ್"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ಬಾಹ್ಯ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"ಅಪರಿಚಿತ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ಇತರ ಸಾಧನಕ್ಕೆ ಆಡಿಯೊವನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ಹ್ಯಾಂಗ್ ಅಪ್"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ಇಲ್ಲಿಗೆ ಬದಲಾಯಿಸಿ"</string> </resources> diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 6b4c2f14b..dc793e320 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"백그라운드 통화"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"연결 해제된 통화"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"다운된 전화 앱"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"통화 스트리밍"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"이 전화를 걸면 현재 <xliff:g id="OTHER_APP">%1$s</xliff:g>에서 진행 중인 통화가 종료됩니다."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"전화 걸 방법 선택"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> 앱으로 전화 리디렉션"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"스피커"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"외부"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"알 수 없음"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"다른 기기로 오디오 스트리밍"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"전화 끊기"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"현재 기기로 전환"</string> </resources> diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index aa8ce3eae..43def8b66 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Фондогу чалуулар"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Ажыратылган чалуулар"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Катадан улам иштебей калган телефон колдонмолору"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Чалууну берүү"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Эгер чалып баштасаңыз, <xliff:g id="OTHER_APP">%1$s</xliff:g> чалууңуз аяктайт."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Чалуу жолун тандаңыз"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> аркылуу чалуу багытын буруу"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Динамик"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Тышкы"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Белгисиз"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Аудио башка түзмөккө берилүүдө"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Чалууну бүтүрүү"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Бул жерге которулуу"</string> </resources> diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index 45c2b70ff..ff79144c1 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ການໂທໃນພື້ນຫຼັງ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ສາຍຖືກຕັດແລ້ວ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ແອັບໂທລະສັບຂັດຂ້ອງ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"ການສະຕຣີມການໂທ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ການໂທສາຍນີ້ຈະເປັນການສິ້ນສຸດສາຍ <xliff:g id="OTHER_APP">%1$s</xliff:g> ຂອງທ່ານ."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ເລືອກວິທີໂທສາຍນີ້"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"ປ່ຽນເສັ້ນທາງການໂທໂດຍໃຊ້ <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ລຳໂພງ"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ພາຍນອກ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"ບໍ່ຮູ້ຈັກ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ສະຕຣີມສຽງໄປໃສ່ອຸປະກອນອື່ນ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ວາງສາຍ"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ສະຫຼັບບ່ອນນີ້"</string> </resources> diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index 5e8b1f20a..945443122 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Skambučiai fone"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Skambučiai atjungti"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Užstrigusios telefono programos"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Srautinis skambučio perdavimas"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Atliekant šį skambutį bus užbaigtas „<xliff:g id="OTHER_APP">%1$s</xliff:g>“ skambutis."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Pasirinkite, kaip norite skambinti"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Peradresuoti skambutį naudojant programą „<xliff:g id="OTHER_APP">%1$s</xliff:g>“"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Garsiakalbis"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Išoriniai šaltiniai"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Nežinoma"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Srautinis garso perdavimas į kitą įrenginį"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Baigti skambutį"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Perjungti čia"</string> </resources> diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 043303760..5ebdd8eb2 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Sarunas fonā"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Pārtrauktie zvani"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Avarējušās tālruņa lietotnes"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Zvana straumēšana"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Veicot šo zvanu, tiks beigts zvans lietotnē <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Izvēlieties, kā veikt šo zvanu"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Novirzīt zvanu, izmantojot lietotni <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Skaļrunis"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ārēja ierīce"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Nezināma ierīce"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Notiek audio straumēšana uz citu ierīci."</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Beigt zvanu"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Pārslēgties šeit"</string> </resources> diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 487338033..57a3fce6c 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Повици во заднина"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Прекинати повици"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Паднати апликации за телефон"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Стримување повик"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ако се воспостави повиков, вашиот повик на <xliff:g id="OTHER_APP">%1$s</xliff:g> ќе заврши."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Изберете како да се воспостави повиков"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Пренасочи го повикот со <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -109,7 +110,7 @@ <string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"Броеви што не се наведени во „Контакти“"</string> <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"Блокирани броеви што не се наведени во вашите „Контакти“"</string> <string name="phone_settings_private_num_txt" msgid="6339272760338475619">"Приватно"</string> - <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Блокирај повикувачи со сокриен број"</string> + <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Блокирај повикувачи со скриен број"</string> <string name="phone_settings_payphone_txt" msgid="5003987966052543965">"Телефонска говорница"</string> <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"Блокирај повици од телефонски говорници"</string> <string name="phone_settings_unknown_txt" msgid="3577926178354772728">"Непознато"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Звучник"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Надворешно"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Непознато"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Звукот се стримува на друг уред"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Спушти"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Префрли овде"</string> </resources> diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 9e6b8ca62..a6d1626d9 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"പശ്ചാത്തല കോളുകൾ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"വിച്ഛേദിക്കപ്പെട്ട കോളുകൾ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ക്രാഷായ ഫോൺ ആപ്പുകൾ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"കോൾ സ്ട്രീമിംഗ്"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ഈ കോൾ ചെയ്യുന്നത് നിങ്ങളുടെ <xliff:g id="OTHER_APP">%1$s</xliff:g> കോൾ അവസാനിക്കാനിടയാക്കും."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ഈ കോൾ എങ്ങനെ ചെയ്യണമെന്ന് തിരഞ്ഞെടുക്കുക"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ഉപയോഗിച്ച് കോൾ റീഡയറക്റ്റ് ചെയ്യുക"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"സ്പീക്കർ"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"എക്സ്റ്റേണൽ സ്ട്രീമിംഗ്"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"അജ്ഞാതം"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ഓഡിയോ മറ്റൊരു ഉപകരണത്തിലേക്ക് സ്ട്രീം ചെയ്യുന്നു"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"മാറ്റി വയ്ക്കുക"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ഇവിടേക്ക് മാറുക"</string> </resources> diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 2c9099889..70dde8a44 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Арын дуудлагууд"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Салсан дуудлагууд"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Гэмтсэн гар утасны аппууд"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Дуудлага дамжуулах"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Энэ дуудлагыг хийснээр таны <xliff:g id="OTHER_APP">%1$s</xliff:g> дуудлагыг дуусгана."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Энэ дуудлагыг хэрхэн хийхийг сонгох"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g>-г ашиглан дуудлагыг дахин чиглүүлэх"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Чанга яригч"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Гадны"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Тодорхойгүй"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Бусад төхөөрөмж рүү аудио дамжуулж байна"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Таслах"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Ийшээ сэлгэх"</string> </resources> diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 263433ddd..c4438aebc 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"बॅकग्राउंड कॉल"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"डिस्कनेक्ट केलेले कॉल"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"क्रॅश झालेली फोन ॲप्स"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"कॉल स्ट्रीमिंग"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"हा कॉल केल्याने तुमचा <xliff:g id="OTHER_APP">%1$s</xliff:g> कॉल समाप्त होईल."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"हा कॉल कसा करायचा ते निवडा"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> वापरून कॉल रीडिरेक्ट करा"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"स्पीकर"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"बाह्य"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"अज्ञात"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ऑडिओ हा दुसऱ्या डिव्हाइसवर स्ट्रीम करत आहे"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"बंद करा"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"येथे स्विच करा"</string> </resources> diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 4a8d554ad..355502cc4 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Panggilan latar belakang"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Panggilan diputuskan sambungan"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplikasi telefon yang ranap"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Penstriman panggilan"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Membuat panggilan ini akan menamatkan panggilan <xliff:g id="OTHER_APP">%1$s</xliff:g> anda."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Pilih cara untuk membuat panggilan ini"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Ubah hala panggilan menggunakan <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Pembesar suara"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Luaran"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Tidak diketahui"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Penstriman audio pada peranti lain"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Tamatkan panggilan"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Tukar di sini"</string> </resources> diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 3511bca9d..9ead5f410 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"နောက်ခံမှ ခေါ်ဆိုမှုများ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ပြတ်တောက်သွားသည့် ခေါ်ဆိုမှုများ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ရပ်တန့်သွားသော ဖုန်းအက်ပ်များ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"ခေါ်ဆိုမှု တိုက်ရိုက်လွှင့်ခြင်း"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ဤခေါ်ဆိုမှု ပြုလုပ်ပါက <xliff:g id="OTHER_APP">%1$s</xliff:g> သုံးပြီးပြောနေခြင်းကို ဖြတ်ပစ်ပါမည်။"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ဤခေါ်ဆိုမှု ပြုလုပ်ပုံကို ရွေးချယ်ပါ"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"ခေါ်ဆိုမှုကို <xliff:g id="OTHER_APP">%1$s</xliff:g> ဖြင့် တစ်ဆင့်ပြန်ညွှန်ရန်"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"စပီကာ"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ပြင်ပ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"မသိ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"အသံကို အခြားစက်တွင် တိုက်ရိုက်လွှင့်နေသည်"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ဖုန်းချရန်"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ဤနေရာသို့ လွှဲပြောင်းရန်"</string> </resources> diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index fb4dc9749..8bebbff63 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Bakgrunnsanrop"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Frakoblede anrop"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Telefonapper som har krasjet"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Anropsstrømming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Samtalen din i <xliff:g id="OTHER_APP">%1$s</xliff:g> avsluttes hvis du foretar dette anropet."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Velg hvordan du vil ringe"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Viderekoble anropet med <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Høyttaler"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ekstern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Ukjent"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Strømmer lyden til en annen enhet"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Legg på"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Flytt hit"</string> </resources> diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 8c0267670..44645dc8c 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ब्याकग्राउन्डका कलहरू"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"विच्छेद गरिएका कल"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"फोनमा रहेका क्र्यास भएका एपहरू"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"कल स्ट्रिमिङ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"यो कल गर्नुले तपाईंको <xliff:g id="OTHER_APP">%1$s</xliff:g> कल अन्त्य गर्दछ।"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"यो कल गर्ने तरिका छनौट गर्नुहोस्"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> प्रयोग गरी कल रिडाइरेक्ट गर्नुहोस्"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"स्पिकर"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"बाह्य"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"अज्ञात"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"अर्को डिभाइसमा अडियो स्ट्रिम गरिँदै छ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"कल काट्नुहोस्"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"यहाँ गई बदल्नुहोस्"</string> </resources> diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 726ab60dd..8dfee8189 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Achtergrondgesprekken"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Beëindigde gesprekken"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Gecrashte telefoon-apps"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Oproepstreaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Als je dit gesprek start, wordt je <xliff:g id="OTHER_APP">%1$s</xliff:g>-gesprek beëindigd."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Kies hoe je dit gesprek wilt plaatsen"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Gesprek omleiden via <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Extern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Onbekend"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Audio streamen naar ander apparaat"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Ophangen"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Hiernaartoe schakelen"</string> </resources> diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index c25ec86e8..787711b88 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡ କଲ୍ଗୁଡ଼ିକ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ବିଚ୍ଛିନ୍ନ କରାଯାଇଥିବା କଲ୍ଗୁଡ଼ିକ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"କ୍ରାସ୍ ହୋଇଥିବା ଫୋନ୍ ଆପ୍ସ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"କଲ ଷ୍ଟ୍ରିମିଂ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ଏହି କଲ୍କୁ ସ୍ଥାପନ କରିବା ଦ୍ଵାରା ଆପଣଙ୍କର <xliff:g id="OTHER_APP">%1$s</xliff:g> କଲ୍ ସମାପ୍ତ ହୋଇଯିବ।"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ଏହି କଲ୍ କିପରି କରିବାକୁ ଚାହାନ୍ତି ବାଛନ୍ତୁ"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ବ୍ୟବହାର କରି କଲ୍ ରିଡାଇରେକ୍ଟ କରନ୍ତୁ"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ସ୍ପିକର"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ଏକ୍ସଟର୍ନଲ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"ଅଜଣା"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ଅନ୍ୟ ଡିଭାଇସରେ ଅଡିଓ ଷ୍ଟ୍ରିମ କରାଯାଉଛି"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"କଲ ସମାପ୍ତ କରନ୍ତୁ"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ଏଠାରେ ସୁଇଚ କରନ୍ତୁ"</string> </resources> diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 65073e2ab..b96a1dbe4 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"ਬੈਕਗ੍ਰਾਊਂਡ ਕਾਲਾਂ"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ਡਿਸਕਨੈਕਟ ਕੀਤੀਆਂ ਕਾਲਾਂ"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ਕ੍ਰੈਸ਼ ਹੋਈਆਂ ਫ਼ੋਨ ਐਪਾਂ"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"ਕਾਲ ਸਟ੍ਰੀਮਿੰਗ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ਇਹ ਕਾਲ ਕਰਨ ਨਾਲ ਤੁਹਾਡੀ <xliff:g id="OTHER_APP">%1$s</xliff:g> ਕਾਲ ਸਮਾਪਤ ਹੋ ਜਾਵੇਗੀ।"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ਚੁਣੋ ਕਿ ਕਾਲ ਕਿਵੇਂ ਕਰਨੀ ਹੈ"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਕਾਲ ਰੀਡਾਇਰੈਕਟ ਕਰੋ"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ਸਪੀਕਰ"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ਬਾਹਰੀ"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"ਅਗਿਆਤ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ਆਡੀਓ ਨੂੰ ਕਿਸੇ ਹੋਰ ਡੀਵਾਈਸ \'ਤੇ ਸਟ੍ਰੀਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ਕਾਲ ਸਮਾਪਤ ਕਰੋ"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ਇੱਥੇ ਸਵਿੱਚ ਕਰੋ"</string> </resources> diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index a10d29fd9..df5d29eb1 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Połączenia w tle"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Przerwane połączenia"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplikacje telefoniczne po awarii"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Strumieniowanie połączenia"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Jeśli zadzwonisz, połączenie w aplikacji <xliff:g id="OTHER_APP">%1$s</xliff:g> zostanie zakończone."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Wybierz, jak chcesz zadzwonić"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Przekieruj połączenie za pomocą aplikacji <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Głośnik"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Zewnętrzne"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Brak informacji"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Strumieniowanie dźwięku na inne urządzenie"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Rozłącz"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Przełącz tutaj"</string> </resources> diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 0b279b4cb..5fbe1d3aa 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -65,7 +65,7 @@ <string name="blocked_numbers" msgid="8322134197039865180">"Números bloqueados"</string> <string name="blocked_numbers_msg" msgid="2797422132329662697">"Não irá receber chamadas ou mensagens de texto de números bloqueados."</string> <string name="block_number" msgid="3784343046852802722">"Adicionar um número"</string> - <string name="unblock_dialog_body" msgid="2723393535797217261">"Pretende desbloquear <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string> + <string name="unblock_dialog_body" msgid="2723393535797217261">"Quer desbloquear <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string> <string name="unblock_button" msgid="8732021675729981781">"Desbloquear"</string> <string name="add_blocked_dialog_body" msgid="8599974422407139255">"Bloquear chamadas e mensagens de texto de"</string> <string name="add_blocked_number_hint" msgid="8769422085658041097">"Número de telefone"</string> @@ -100,8 +100,9 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Chamadas em segundo plano"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Chamadas desligadas"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Apps Telefone com falhas"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming de chamadas"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ao efetuar esta chamada, irá terminar a chamada na app <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> - <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Escolha como pretende efetuar esta chamada"</string> + <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Escolha como quer efetuar esta chamada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirecionar chamada através de <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> <string name="alert_place_unredirect_outgoing_call" msgid="2467608535225764006">"Ligar com o meu número de telefone"</string> <string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"Não é possível efetuar uma chamada através da app <xliff:g id="OTHER_APP">%1$s</xliff:g>. Experimente utilizar uma app de redirecionamento de chamadas diferente ou contactar o programador para obter ajuda."</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Altifalante"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externo"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Desconhecido"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"A fazer stream de áudio para outro dispositivo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Desligar"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Mudar aqui"</string> </resources> diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index a5628c4fd..a7fc3c741 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -57,7 +57,7 @@ <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"Definir padrão"</string> <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Cancelar"</string> <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"O <xliff:g id="NEW_APP">%s</xliff:g> poderá ligar e controlar todos os aspectos das chamadas. Defina como aplicativo Telefone padrão somente aqueles em que você confia."</string> - <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"Usar o <xliff:g id="NEW_APP">%s</xliff:g> como seu app de seleção de chamadas padrão?"</string> + <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"Usar o <xliff:g id="NEW_APP">%s</xliff:g> como seu app de filtro de ligações padrão?"</string> <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"O <xliff:g id="OLD_APP">%s</xliff:g> não selecionará mais as chamadas."</string> <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"O <xliff:g id="NEW_APP">%s</xliff:g> poderá ver as informações sobre os autores das chamadas que não estão entre seus contatos e bloqueá-los. Defina como app de seleção de chamadas padrão somente aqueles em que você confia."</string> <string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"Definir padrão"</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Chamadas em segundo plano"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Chamadas desconectadas"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Falha com os apps de telefone"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming de ligação"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Se você ligar agora, sua chamada será encerrada no <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Escolha como fazer esta chamada"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirecionar a chamada usando o <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Alto-falante"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externo"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Desconhecido"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Fazendo streaming de áudio para outro dispositivo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Desligar"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Mudar para este dispositivo"</string> </resources> diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 2332d4d98..8e485d019 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Apeluri în fundal"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Apeluri deconectate"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplicații pentru telefon blocate"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streaming de apeluri"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Dacă inițiezi acest apel, cel din <xliff:g id="OTHER_APP">%1$s</xliff:g> va fi încheiat."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Alege cum vrei să inițiezi apelul"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirecționezi apelul folosind <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Difuzor"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Extern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Necunoscut"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streaming audio pe alt dispozitiv"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Încheie apelul"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Treci la alt cont aici"</string> </resources> diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 139108d98..67ab2e904 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Фоновые вызовы"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Прекращенные вызовы"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Приложения для телефона, работа которых прекращена из-за ошибки"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Потоковая передача звонков"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Если вы начнете этот звонок, вызов в <xliff:g id="OTHER_APP">%1$s</xliff:g> будет завершен."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Выберите, как хотите позвонить."</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Перенаправить вызов с использованием <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Динамик"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Внешнее устройство"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Неизвестно"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Потоковая передача аудио на другое устройство"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Завершить"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Переключиться"</string> </resources> diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index e3faf4982..71442e0ea 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"පසුබිම් ඇමතුම්"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"විසන්ධි කළ ඇමතුම්"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"බිඳ වැටුණු දුරකථන යෙදුම්"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"ඇමතුම් ප්රවාහය"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"මෙම ඇමතුම ගැනීම ඔබේ <xliff:g id="OTHER_APP">%1$s</xliff:g> ඇමතුම අවසන් කරනු ඇත."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"මෙම ඇමතුම ගන්නා ආකාරය තෝරන්න"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> භාවිතයෙන් ඇමතුම ප්රතියොමු කරන්න"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ස්පීකරය"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"බාහිර"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"නොදනී"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"වෙනත් උපාංගයකට ශ්රව්ය ප්රවාහ කිරීම"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"විසන්ධි කරන්න"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"මෙතැනට මාරු වෙන්න"</string> </resources> diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index f7606ecb7..a001130b1 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Hovory na pozadí"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Zrušené hovory"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Zrútené telefónne aplikácie"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Streamovanie hovoru"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ak uskutočníte tento hovor, hovor cez <xliff:g id="OTHER_APP">%1$s</xliff:g> bude ukončený."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Vyberte, ako chcete tento hovor uskutočniť"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Presmerovať hovor cez aplikáciu <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Reproduktor"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Externé"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Neznáme"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streamovanie zvuku do iného zariadenia"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Zložiť"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Prepnúť sem"</string> </resources> diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 138524b0c..994bc7e35 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Klici v ozadju"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Prekinjeni klici"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Zrušene aplikacije za klicanje"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Pretočno predvajanje klicev"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Če opravite ta klic, bo končan klic prek aplikacije <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Izberite, kako želite opraviti klic"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Preusmeri klic z aplikacijo <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Zvočnik"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Zunanje"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Neznano"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Pretočno predvajanje zvoka v drugo napravo"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Prekini klic"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Preklopi sem"</string> </resources> diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index 0a36a406e..89ae852a1 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Telefonatat në sfond"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Telefonatat e shkëputura"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplikacionet e telefonit që kanë pësuar ndërprerje aksidentale"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Transmetimi i telefonatave"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Kryerja e kësaj telefonate do të mbyllë telefonatën tënde në <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Zgjidh se si do ta kryesh këtë telefonatë"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Ridrejtoje telefonatën duke përdorur <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Altoparlant"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"E jashtme"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"E panjohur"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Po transmetohet audioja te një pajisje tjetër"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Mbyll"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Ndërro këtu"</string> </resources> diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index b84684189..113438003 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Позиви у позадини"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Прекинути позиви"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Апликације за телефонирање које су отказале"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Стримовање позива"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ако упутите овај позив, завршићете <xliff:g id="OTHER_APP">%1$s</xliff:g> позив."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Изаберите како желите да упутите овај позив"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Преусмери позив помоћу: <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Звучник"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Екстерни"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Непознато"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Звук се стримује на други уређај"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Прекини везу"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Пребаци овде"</string> </resources> diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index acc6dc60d..c6f6ec9e3 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Bakgrundssamtal"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Frånkopplade samtal"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Kraschade telefonappar"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Samtalsstreaming"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ringer du det här samtalet avslutas samtalet i <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Välj hur du vill ringa samtalet"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Omdirigera samtal med <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Högtalare"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Extern"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Okänd"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Streama ljud till en annan enhet"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Lägg på"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Koppla hit"</string> </resources> diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 84f729449..1b499900c 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Simu za chinichini"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Simu zilizokatwa"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Programu za simu zilizoacha kufanya kazi"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Utiririshaji wa simu"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ukipiga simu hii, simu yako kwenye <xliff:g id="OTHER_APP">%1$s</xliff:g> itakatwa."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Chagua jinsi utakavyopiga simu hii"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Elekeza simu ukitumia <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Spika"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Ya nje"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Haijulikani"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Inatiririsha sauti kwenye kifaa kingine"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Kata simu"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Badili hapa"</string> </resources> diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index 18b5861a7..9f37d8760 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"பின்னணி அழைப்புகள்"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"துண்டிக்கப்பட்ட அழைப்புகள்"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"சிதைவடைந்த மொபைல் ஆப்ஸ்"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"அழைப்பு ஸ்ட்ரீமிங்"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"புதிய அழைப்பைச் செய்தால், செயலில் உள்ள <xliff:g id="OTHER_APP">%1$s</xliff:g> அழைப்பு துண்டிக்கப்படும்."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"இந்த அழைப்பை எவ்வாறு மேற்கொள்ள வேண்டும் எனத் தேர்ந்தெடுக்கவும்"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g>ஐப் பயன்படுத்தி அழைப்பைத் திருப்பி விடு"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ஸ்பீக்கர்"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"வெளிப்புறச் சாதனம்"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"தெரியவில்லை"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"வேறு சாதனத்திற்கு ஆடியோவை ஸ்ட்ரீம் செய்கிறது"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"அழைப்பைத் துண்டி"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"இங்கே மாற்று"</string> </resources> diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 5ed2ebef8..8f8a23e4d 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"బ్యాక్గ్రౌండ్ కాల్స్"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"డిస్కనెక్ట్ చేసిన కాల్స్"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"క్రాష్ అయిన ఫోన్ యాప్స్"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"కాల్ స్ట్రీమింగ్"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"ఈ కాల్ చేయడం వలన మీ <xliff:g id="OTHER_APP">%1$s</xliff:g> కాల్ ముగుస్తుంది."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ఈ కాల్ ఎలా చేయాలో ఎంచుకోండి"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ఉపయోగించి కాల్ మళ్లించు"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"స్పీకర్"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"వెలుపలి"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"తెలియదు"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"ఆడియోను ఇతర పరికరానికి స్ట్రీమింగ్ చేయండి"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"ముగించండి"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"ఇక్కడకు స్విచ్ అవ్వండి"</string> </resources> diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 678af2d24..b8dc9f0d2 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"การโทรในเบื้องหลัง"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"สายถูกตัด"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"แอปโทรศัพท์ขัดข้อง"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"การสตรีมการโทร"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"การโทรออกนี้จะวางสายใน <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"เลือกวิธีโทรออก"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"โอนสายโดยใช้ <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"ลำโพง"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"ภายนอก"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"ไม่ทราบ"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"กำลังสตรีมเสียงไปยังอุปกรณ์อื่นๆ"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"วางสาย"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"เปลี่ยนที่นี่"</string> </resources> diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 495c191d0..91e1b3323 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Mga tawag sa background"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Nadiskonektang mga tawag"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Nag-crash na mga phone app"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Pag-stream ng tawag"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Tatapusin ng pagtawag na ito ang iyong tawag sa <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Piliin kung paano gagawin ang tawag na ito"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"I-redirect ang tawag gamit ang <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Speaker"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"External"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Hindi Alam"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Naka-stream ang audio sa ibang device"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Mag-hang up"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Lumipat dito"</string> </resources> diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 130968294..0aa2e20d0 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Arka plandaki aramalar"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Bağlantısı kesilen aramalar"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Kilitlenen telefon uygulamaları"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Görüşme aktarımı"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Bu çağrıyı yaptığınızda <xliff:g id="OTHER_APP">%1$s</xliff:g> çağrınız sona erecek."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Bu aramanın nasıl yapılacağını seçin"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> uygulamasını kullanarak aramayı yönlendir"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Hoparlör"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Harici"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Bilinmiyor"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Ses başka bir cihaza aktarılıyor"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Görüşmeyi bitir"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Buraya dön"</string> </resources> diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 7b81d251b..a4d01d175 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Виклики у фоновому режимі"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Припинені виклики"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Збої в додатках для дзвінків"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Трансляція дзвінків"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Якщо здійснити цей виклик, буде завершено виклик у додатку <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Виберіть, як здійснити цей виклик"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Переспрямувати через додаток <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Гучний зв’язок"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Зовнішні джерела"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Невідомо"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Аудіо транслюється на інший пристрій"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Завершити"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Перевести сюди"</string> </resources> diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index afd8d0a25..6649f4200 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -27,8 +27,8 @@ <string name="notification_missedCall_call_back" msgid="7900333283939789732">"واپس کال کریں"</string> <string name="notification_missedCall_message" msgid="4054698824390076431">"پیغام"</string> <string name="notification_disconnectedCall_title" msgid="1790131923692416928">"کال غیر منسلک کر دیا گیا"</string> - <string name="notification_disconnectedCall_body" msgid="600491714584417536">"ہنگامی کال کی وجہ سے <xliff:g id="CALLER">%s</xliff:g> کی کال کو غیر منسلک کر دیا گیا ہے۔"</string> - <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ہنگامی کال لگائے جانے کی وجہ سے آپ کی کال غیر منسلک ہوگئی ہے۔"</string> + <string name="notification_disconnectedCall_body" msgid="600491714584417536">"ایمرجنسی کال کی وجہ سے <xliff:g id="CALLER">%s</xliff:g> کی کال کو غیر منسلک کر دیا گیا ہے۔"</string> + <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ایمرجنسی کال لگائے جانے کی وجہ سے آپ کی کال غیر منسلک ہوگئی ہے۔"</string> <string name="notification_audioProcessing_title" msgid="1619035039880584575">"پس منظر کی کال"</string> <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> پس منظر میں کال پر کارروائی کر رہی ہے۔ یہ ایپ کال کے دوران آواز تک رسائی حاصل اور چلا سکتی ہے۔"</string> <string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> نے جواب دینا بند کر دیا"</string> @@ -46,7 +46,7 @@ <string name="respond_via_sms_confirmation_format" msgid="2932395476561267842">"پیغام <xliff:g id="PHONE_NUMBER">%s</xliff:g> کو بھیج دیا گیا۔"</string> <string name="respond_via_sms_failure_format" msgid="5198680980054596391">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> پر پیغام نہیں بھیجا جا سکا۔"</string> <string name="enable_account_preference_title" msgid="6949224486748457976">"کالنگ اکاؤنٹس"</string> - <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"صرف ہنگامی کالز کی اجازت ہے۔"</string> + <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"صرف ایمرجنسی کالز کی اجازت ہے۔"</string> <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"یہ ایپلی کیشن فون کی اجازت کے بغیر باہر جانے والی کالیں نہیں کر سکتی۔"</string> <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"کال کرنے کیلئے، ایک درست نمبر درج کریں۔"</string> <string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"اس وقت کال شامل نہیں کی جا سکتی ہے۔"</string> @@ -73,11 +73,11 @@ <string name="non_primary_user" msgid="315564589279622098">"صرف آلہ کا مالک مسدود کردہ نمبرز کو دیکھ سکتا ہے اور ان کا نظم کر سکتا ہے۔"</string> <string name="delete_icon_description" msgid="5335959254954774373">"غیر مسدود کریں"</string> <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"مسدود کرنا عارضی طور پر آف ہے"</string> - <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"جب آپ کوئی ایمرجنسی نمبر ڈائل کرتے یا اسے متن بھیجتے ہیں تو انسداد کو آف کر دیا جاتا ہے تاکہ ہنگامی سروسز آپ سے رابطہ کر سکیں۔"</string> + <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"جب آپ کوئی ایمرجنسی نمبر ڈائل کرتے یا اسے متن بھیجتے ہیں تو انسداد کو آف کر دیا جاتا ہے تاکہ ایمرجنسی سروسز آپ سے رابطہ کر سکیں۔"</string> <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"اب دوبارہ فعال کریں"</string> <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> مسدود کر دیا گیا"</string> <string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> غیر مسدود کر دیا گیا"</string> - <string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"ہنگامی نمبر مسدود کرنے سے قاصر۔"</string> + <string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"ایمرجنسی نمبر مسدود کرنے سے قاصر۔"</string> <string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> پہلے ہی مسدود ہے۔"</string> <string name="toast_personal_call_msg" msgid="5817631570381795610">"کال کرنے کیلئے ذاتی ڈائلر استعمال ہو رہا ہے"</string> <string name="notification_incoming_call" msgid="1233481138362230894">"<xliff:g id="CALL_FROM">%2$s</xliff:g> کی جانب سے <xliff:g id="CALL_VIA">%1$s</xliff:g> کال"</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"پس منظر کی کالز"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"منقطع کالز"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"کریشڈ فون ایپس"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"کال اسٹریمنگ"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"یہ کال کرنے سے <xliff:g id="OTHER_APP">%1$s</xliff:g> کال ختم ہو جائے گی۔"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"یہ کال کرنے کا طریقہ منتخب کریں"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> کے ذریعے کال کو ریڈائریکٹ کریں"</string> @@ -118,10 +119,10 @@ <string name="phone_settings_unavailable_summary_txt" msgid="8221686031038282633">"کالز کو مسدود کریں جہاں یہ نمبر دستیاب نہ ہو"</string> <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"کال مسدود کرنا"</string> <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"کال مسدود کرنا غیر فعال ہو گیا ہے"</string> - <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"ہنگامی کال کی گئی"</string> - <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"ہنگامی حالت میں جواب دہندگان کو آپ سے رابطہ کرنے کی اجازت دینے کیلئے کال مسدود کرنا غیر فعال ہو گیا ہے۔"</string> + <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"ایمرجنسی کال کی گئی"</string> + <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"ایمرجنسی حالت میں جواب دہندگان کو آپ سے رابطہ کرنے کی اجازت دینے کیلئے کال مسدود کرنا غیر فعال ہو گیا ہے۔"</string> <string name="developer_title" msgid="9146088855661672353">"ٹیلی کام ڈویلپر مینیو"</string> - <string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ہنگامی کال کے دوران کالز نہیں لی جائیں گی۔"</string> + <string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ایمرجنسی کال کے دوران کالز نہیں لی جائیں گی۔"</string> <string name="cancel" msgid="6733466216239934756">"منسوخ کریں"</string> <string name="back" msgid="6915955601805550206">"پیچھے"</string> <string name="callendpoint_name_earpiece" msgid="7047285080319678594">"ایئر پیس"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"اسپیکر"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"خارجی"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"نامعلوم"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"دوسرے آلے پر آڈیو کی سلسلہ بندی کی جا رہی ہے"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"منقطع کریں"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"یہاں سوئچ کریں"</string> </resources> diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 688b6a7f6..c6805ea8b 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Orqa fondagi chaqiruvlar"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Tugatilgan chaqiruvlar"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Ishdan chiqqan telefon ilovalari"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Chaqiruv translatsiyasi"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Bu qo‘ng‘iroqni amalga oshirsangiz, <xliff:g id="OTHER_APP">%1$s</xliff:g> qo‘ng‘irog‘i tugatiladi."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Telefon qilish usulini tanlang"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Chaqiruv <xliff:g id="OTHER_APP">%1$s</xliff:g> orqali qayta uzatilsin"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Karnay"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Tashqi"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Noaniq"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Audio translatsiyani boshqa qurilmaga olish"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Tugatish"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Shu yerga olish"</string> </resources> diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 0920d3b98..5ae2e7907 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Cuộc gọi trong nền"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Các cuộc gọi bị ngắt kết nối"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Các ứng dụng điện thoại bị lỗi"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Truyền trực tuyến cuộc gọi"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Thực hiện cuộc gọi này sẽ kết thúc cuộc gọi <xliff:g id="OTHER_APP">%1$s</xliff:g> của bạn."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Chọn cách thực hiện cuộc gọi này"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Chuyển hướng cuộc gọi bằng cách sử dụng <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Loa"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Bên ngoài"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Không xác định"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Đang truyền trực tuyến âm thanh tới thiết bị khác"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Kết thúc"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Chuyển đổi tại đây"</string> </resources> diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index b926e55ed..1ef0a552f 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -45,7 +45,7 @@ <string name="respond_via_sms_edittext_dialog_title" msgid="6579353156073272157">"快速回复"</string> <string name="respond_via_sms_confirmation_format" msgid="2932395476561267842">"讯息已发送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string> <string name="respond_via_sms_failure_format" msgid="5198680980054596391">"未能将信息发送到 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string> - <string name="enable_account_preference_title" msgid="6949224486748457976">"通话帐号"</string> + <string name="enable_account_preference_title" msgid="6949224486748457976">"通话账号"</string> <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"只能拨打紧急呼救电话。"</string> <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"此应用没有电话权限,无法拨出电话。"</string> <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"要拨打电话,请输入有效的电话号码。"</string> @@ -90,7 +90,7 @@ <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"如果接听此来电,您当前的视频通话会中断。"</string> <string name="answer_incoming_call" msgid="2045888814782215326">"接听"</string> <string name="decline_incoming_call" msgid="922147089348451310">"拒接"</string> - <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"无法拨出电话,因为没有通话帐号支持拨打这类电话。"</string> + <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"无法拨出电话,因为没有通话账号支持拨打这类电话。"</string> <string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"由于当前正在进行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通话,因此无法拨打电话。"</string> <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"由于当前正在进行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通话,因此无法拨打电话。"</string> <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"由于当前正在通过其他应用通话,因此无法拨打电话。"</string> @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"后台通话"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"通话中断"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"手机应用崩溃"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"通话流式传输"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"拨打此电话将导致<xliff:g id="OTHER_APP">%1$s</xliff:g>通话结束。"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"选择拨打此电话的方式"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"使用<xliff:g id="OTHER_APP">%1$s</xliff:g>转移呼叫"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"免提"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"外部"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"未知"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"将音频流式传输到其他设备"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"挂断"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"在此处切换"</string> </resources> diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index e7b1a0773..0140f26a7 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -28,11 +28,11 @@ <string name="notification_missedCall_message" msgid="4054698824390076431">"短訊"</string> <string name="notification_disconnectedCall_title" msgid="1790131923692416928">"已中斷的通話"</string> <string name="notification_disconnectedCall_body" msgid="600491714584417536">"因撥打緊急電話緣故,與<xliff:g id="CALLER">%s</xliff:g>的通話已中斷。"</string> - <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"因撥打緊急電話緣故,您的通話已中斷。"</string> + <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"因撥打緊急電話緣故,你的通話已中斷。"</string> <string name="notification_audioProcessing_title" msgid="1619035039880584575">"背景通話"</string> <string name="notification_audioProcessing_body" msgid="8811420157964118913">"「<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>」正在處理背景中的通話。這個應用程式或會存取通話,或是在通話中播放音訊。"</string> <string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>已停止回應"</string> - <string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"您使用了裝置隨付的手機應用程式來通話"</string> + <string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"你使用了裝置隨付的手機應用程式來通話"</string> <string name="accessibility_call_muted" msgid="2968461092554300779">"通話已靜音。"</string> <string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"擴音器已啟用"</string> <string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"我現在不方便通話,有什麼事呢?"</string> @@ -56,14 +56,14 @@ <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"要將<xliff:g id="NEW_APP">%s</xliff:g>設為預設電話應用程式嗎?"</string> <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"設為預設"</string> <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"取消"</string> - <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"「<xliff:g id="NEW_APP">%s</xliff:g>」將可撥打電話並控制所有相關功能。只有您信任的應用程式,才應設為預設手機應用程式。"</string> + <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"「<xliff:g id="NEW_APP">%s</xliff:g>」將可撥打電話並控制所有相關功能。只有你信任的應用程式,才應設為預設手機應用程式。"</string> <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"要將「<xliff:g id="NEW_APP">%s</xliff:g>」設為預設來電過濾應用程式嗎?"</string> <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"「<xliff:g id="OLD_APP">%s</xliff:g>」無法再篩選來電。"</string> - <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"「<xliff:g id="NEW_APP">%s</xliff:g>」將可查看通訊錄以外來電者的相關資訊,並封鎖這些來電。只有您信任的應用程式才適合設為預設來電過濾應用程式。"</string> + <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"「<xliff:g id="NEW_APP">%s</xliff:g>」將可查看通訊錄以外來電者的相關資訊,並封鎖這些來電。只有你信任的應用程式才適合設為預設來電過濾應用程式。"</string> <string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"設為預設"</string> <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"取消"</string> <string name="blocked_numbers" msgid="8322134197039865180">"已封鎖的號碼"</string> - <string name="blocked_numbers_msg" msgid="2797422132329662697">"您不會收到已封鎖號碼的來電或短訊。"</string> + <string name="blocked_numbers_msg" msgid="2797422132329662697">"你不會收到已封鎖號碼的來電或短訊。"</string> <string name="block_number" msgid="3784343046852802722">"新增號碼"</string> <string name="unblock_dialog_body" msgid="2723393535797217261">"要解除封鎖 <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> 嗎?"</string> <string name="unblock_button" msgid="8732021675729981781">"解除封鎖"</string> @@ -73,7 +73,7 @@ <string name="non_primary_user" msgid="315564589279622098">"只有裝置擁有者可查看和管理已封鎖的號碼。"</string> <string name="delete_icon_description" msgid="5335959254954774373">"解除封鎖"</string> <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"暫時關閉封鎖功能"</string> - <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"在您撥打或發短訊至緊急號碼後,封鎖功能會停用,以確保緊急服務可與您聯絡。"</string> + <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"在你撥打或發短訊至緊急號碼後,封鎖功能會停用,以確保緊急服務可與你聯絡。"</string> <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"立即重新啟用"</string> <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"已封鎖 <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>"</string> <string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"已解除對 <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> 的封鎖"</string> @@ -82,17 +82,17 @@ <string name="toast_personal_call_msg" msgid="5817631570381795610">"使用個人撥號器撥打電話"</string> <string name="notification_incoming_call" msgid="1233481138362230894">"來自<xliff:g id="CALL_FROM">%2$s</xliff:g>的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 通話"</string> <string name="notification_incoming_video_call" msgid="5795968314037063900">"來自<xliff:g id="CALL_FROM">%2$s</xliff:g>的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 視像通話"</string> - <string name="answering_ends_other_call" msgid="8653544281903986641">"如果接聽,您的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 通話將會結束"</string> - <string name="answering_ends_other_calls" msgid="3702302838456922535">"如果接聽,您的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 通話將會結束"</string> - <string name="answering_ends_other_video_call" msgid="8572022039304239958">"如果接聽,您的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 視像通話將會結束"</string> - <string name="answering_ends_other_managed_call" msgid="4031778317409881805">"如果接聽,您進行中的通話將會結束"</string> - <string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"如果接聽,您進行中的通話將會結束"</string> - <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"如果接聽,您進行中的視像通話將會結束"</string> + <string name="answering_ends_other_call" msgid="8653544281903986641">"如果接聽,你的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 通話將會結束"</string> + <string name="answering_ends_other_calls" msgid="3702302838456922535">"如果接聽,你的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 通話將會結束"</string> + <string name="answering_ends_other_video_call" msgid="8572022039304239958">"如果接聽,你的 <xliff:g id="CALL_VIA">%1$s</xliff:g> 視像通話將會結束"</string> + <string name="answering_ends_other_managed_call" msgid="4031778317409881805">"如果接聽,你進行中的通話將會結束"</string> + <string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"如果接聽,你進行中的通話將會結束"</string> + <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"如果接聽,你進行中的視像通話將會結束"</string> <string name="answer_incoming_call" msgid="2045888814782215326">"接聽"</string> <string name="decline_incoming_call" msgid="922147089348451310">"拒絕"</string> <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"沒有通話帳戶支援這類通話,因此無法撥打電話。"</string> - <string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"由於您已在進行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通話,因此無法撥打電話。"</string> - <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"由於您已在進行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通話,因此無法撥打電話。"</string> + <string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"由於你已在進行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通話,因此無法撥打電話。"</string> + <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"由於你已在進行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通話,因此無法撥打電話。"</string> <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"由於已在另一個應用程式中進行通話,因此無法撥打電話。"</string> <string name="notification_channel_incoming_call" msgid="5245550964701715662">"來電"</string> <string name="notification_channel_missed_call" msgid="7168893015283909012">"未接來電"</string> @@ -100,11 +100,12 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"背景通話"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"已中斷的通話"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"當機的手機應用程式"</string> - <string name="alert_outgoing_call" msgid="5319895109298927431">"如果撥打此電話,您的 <xliff:g id="OTHER_APP">%1$s</xliff:g> 通話將會結束。"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"串流通話"</string> + <string name="alert_outgoing_call" msgid="5319895109298927431">"如果撥打此電話,你的 <xliff:g id="OTHER_APP">%1$s</xliff:g> 通話將會結束。"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"選擇如何撥打此電話"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"使用「<xliff:g id="OTHER_APP">%1$s</xliff:g>」將通話重新導向"</string> <string name="alert_place_unredirect_outgoing_call" msgid="2467608535225764006">"使用我的電話號碼撥打"</string> - <string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"<xliff:g id="OTHER_APP">%1$s</xliff:g>無法撥打電話。建議您使用其他通話重新導向應用程式,或向開發人員求助。"</string> + <string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"<xliff:g id="OTHER_APP">%1$s</xliff:g>無法撥打電話。建議你使用其他通話重新導向應用程式,或向開發人員求助。"</string> <string name="phone_settings_call_blocking_txt" msgid="7311523114822507178">"來電封鎖"</string> <string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"不在通訊錄中的號碼"</string> <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"封鎖不在通訊錄中的號碼"</string> @@ -119,7 +120,7 @@ <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"來電封鎖"</string> <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"已停用來電封鎖功能"</string> <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"已撥緊急電話"</string> - <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"已停用來電封鎖功能,以便救援人員與您聯絡。"</string> + <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"已停用來電封鎖功能,以便救援人員與你聯絡。"</string> <string name="developer_title" msgid="9146088855661672353">"電信開發商選單"</string> <string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"使用緊急電話期間無法接聽電話。"</string> <string name="cancel" msgid="6733466216239934756">"取消"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"喇叭"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"外部"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"不明"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"正在串流音訊至其他裝置"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"結束通話"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"在這裡切換"</string> </resources> diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 21b8ae912..eeb98b56b 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"背景通話"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"通話中斷"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"通話應用程式異常終止"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"通話串流"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"撥打這通電話將結束你的「<xliff:g id="OTHER_APP">%1$s</xliff:g>」通話。"</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"選擇撥打這通電話的方式"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"使用「<xliff:g id="OTHER_APP">%1$s</xliff:g>」轉接電話"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"喇叭"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"外部"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"不明"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"正在將音訊串流到其他裝置"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"掛斷"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"切換到這部裝置"</string> </resources> diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index fbde58b3f..faee0d9ab 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -100,6 +100,7 @@ <string name="notification_channel_background_calls" msgid="7785659903711350506">"Amakholi angemuva"</string> <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Amakholi anqanyuliwe"</string> <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Izinhlelo zokusebenza ezikhubazekile zefoni"</string> + <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Ukusakaza ikholi"</string> <string name="alert_outgoing_call" msgid="5319895109298927431">"Ukwenza le kholi kuzoqeda enye ikholi yakho ye-<xliff:g id="OTHER_APP">%1$s</xliff:g>."</string> <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Khetha ukuthi uyibeka kanjani le kholi"</string> <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Qondisa kabusha ikholi usebenzisa i-<xliff:g id="OTHER_APP">%1$s</xliff:g>"</string> @@ -130,4 +131,7 @@ <string name="callendpoint_name_speaker" msgid="1971760468695323189">"Isipikha"</string> <string name="callendpoint_name_streaming" msgid="2337595450408275576">"Okungaphandle"</string> <string name="callendpoint_name_unknown" msgid="2199074708477193852">"Akwaziwa"</string> + <string name="call_streaming_notification_body" msgid="502216105683378263">"Sakaza umsindo kwenye idivayisi"</string> + <string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Beka phansi"</string> + <string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Shintsha lapha"</string> </resources> diff --git a/res/values/config.xml b/res/values/config.xml index 15f765bae..c38a6ec4e 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -49,8 +49,10 @@ <bool name="grant_location_permission_enabled">false</bool> <!-- When true, a simple full intensity on/off vibration pattern will be used when calls ring. - When false, a fancy vibration pattern which ramps up and down will be used. - Devices should overlay this value based on the type of vibration hardware they employ. --> + + When false, the vibration effect serialized in the raw `default_ringtone_vibration_effect` + resource (under `frameworks/base/core/res/res/raw/`) is used. Devices should overlay this + value based on the type of vibration hardware they employ. --> <bool name="use_simple_vibration_pattern">false</bool> <!-- Threshold for the X+Y component of gravity needed for the device orientation to be diff --git a/res/values/styles.xml b/res/values/styles.xml index c8b24d3ab..cd608f59c 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -61,6 +61,7 @@ </style> <style name="BlockedNumbersButton" parent="BlockedNumbersTextPrimary2"> + <item name="android:textColor">#202124</item> </style> <style name="BlockedNumbersTextHead1" diff --git a/res/xml/activity_blocked_numbers.xml b/res/xml/activity_blocked_numbers.xml index e77184dea..b6298e96d 100644 --- a/res/xml/activity_blocked_numbers.xml +++ b/res/xml/activity_blocked_numbers.xml @@ -41,8 +41,8 @@ android:layout_height="wrap_content" android:text="@string/non_primary_user" android:paddingTop="@dimen/blocked_numbers_large_padding" - android:paddingLeft="@dimen/blocked_numbers_large_padding" - android:paddingRight="@dimen/blocked_numbers_large_padding" + android:paddingStart="@dimen/blocked_numbers_large_padding" + android:paddingEnd="@dimen/blocked_numbers_large_padding" style="@style/BlockedNumbersTextPrimary2" android:visibility="gone" /> @@ -62,8 +62,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/blocked_numbers_large_padding" - android:paddingLeft="@dimen/blocked_numbers_large_padding" - android:paddingRight="@dimen/blocked_numbers_large_padding"> + android:paddingStart="@dimen/blocked_numbers_large_padding" + android:paddingEnd="@dimen/blocked_numbers_large_padding"> <TextView android:layout_width="wrap_content" diff --git a/res/xml/blocking_suppressed_butterbar.xml b/res/xml/blocking_suppressed_butterbar.xml index 8b941b99e..29473406f 100644 --- a/res/xml/blocking_suppressed_butterbar.xml +++ b/res/xml/blocking_suppressed_butterbar.xml @@ -25,19 +25,19 @@ android:id="@+id/icon" android:layout_height="wrap_content" android:layout_width="wrap_content" - android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:paddingTop="@dimen/blocked_numbers_large_padding" - android:paddingRight="@dimen/blocked_numbers_large_padding" - android:paddingLeft="@dimen/blocked_numbers_large_padding" + android:paddingEnd="@dimen/blocked_numbers_large_padding" + android:paddingStart="@dimen/blocked_numbers_large_padding" android:src="@drawable/ic_status_blocked_orange_40dp"/> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_toRightOf="@id/icon" + android:layout_toEndOf="@id/icon" android:paddingTop="@dimen/blocked_numbers_large_padding" - android:paddingRight="@dimen/blocked_numbers_large_padding" + android:paddingEnd="@dimen/blocked_numbers_large_padding" android:text="@string/blocked_numbers_butter_bar_title" style="@style/BlockedNumbersTextPrimary2" /> @@ -45,11 +45,11 @@ android:id="@+id/description" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_toRightOf="@id/icon" + android:layout_toEndOf="@id/icon" android:layout_below="@id/title" android:paddingTop="@dimen/blocked_numbers_large_padding" android:paddingBottom="@dimen/blocked_numbers_large_padding" - android:paddingRight="@dimen/blocked_numbers_large_padding" + android:paddingEnd="@dimen/blocked_numbers_large_padding" android:text="@string/blocked_numbers_butter_bar_body" style="@style/BlockedNumbersTextSecondary" /> @@ -57,9 +57,9 @@ android:id="@+id/reenable_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_toRightOf="@id/icon" + android:layout_toEndOf="@id/icon" android:layout_below="@id/description" - android:paddingRight="@dimen/blocked_numbers_large_padding" + android:paddingEnd="@dimen/blocked_numbers_large_padding" android:text="@string/blocked_numbers_butter_bar_button" style="@style/BlockedNumbersButton" android:background="?android:attr/selectableItemBackgroundBorderless" /> diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java index dd8e7e8a5..1ec113c68 100644 --- a/src/com/android/server/telecom/Call.java +++ b/src/com/android/server/telecom/Call.java @@ -17,12 +17,13 @@ package com.android.server.telecom; import static android.provider.CallLog.Calls.MISSED_REASON_NOT_MISSED; -import static android.telecom.Call.EVENT_DISPLAY_SOS_MESSAGE; +import static android.telephony.TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -30,6 +31,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.os.OutcomeReceiver; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.RemoteException; @@ -43,6 +45,7 @@ import android.telecom.CallAttributes; import android.telecom.CallAudioState; import android.telecom.CallDiagnosticService; import android.telecom.CallDiagnostics; +import android.telecom.CallException; import android.telecom.CallerInfo; import android.telecom.Conference; import android.telecom.Connection; @@ -70,9 +73,14 @@ import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IVideoProvider; import com.android.internal.util.Preconditions; +import com.android.server.telecom.flags.FeatureFlags; +import com.android.server.telecom.flags.Flags; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import com.android.server.telecom.ui.ToastFactory; +import com.android.server.telecom.voip.TransactionManager; +import com.android.server.telecom.voip.VerifyCallStateChangeTransaction; +import com.android.server.telecom.voip.VoipCallTransactionResult; import java.io.IOException; import java.text.SimpleDateFormat; @@ -118,6 +126,24 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, private static final char NO_DTMF_TONE = '\0'; + + /** + * Listener for CallState changes which can be leveraged by a Transaction. + */ + public interface CallStateListener { + void onCallStateChanged(int newCallState); + } + + public List<CallStateListener> mCallStateListeners = new ArrayList<>(); + + public void addCallStateListener(CallStateListener newListener) { + mCallStateListeners.add(newListener); + } + + public boolean removeCallStateListener(CallStateListener newListener) { + return mCallStateListeners.remove(newListener); + } + /** * Listener for events on the call. */ @@ -283,18 +309,25 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, @Override public void onCallerInfoQueryComplete(Uri handle, CallerInfo callerInfo) { synchronized (mLock) { - Call.this.setCallerInfo(handle, callerInfo); + Call call = Call.this; + if (call != null) { + call.setCallerInfo(handle, callerInfo); + } } } @Override public void onContactPhotoQueryComplete(Uri handle, CallerInfo callerInfo) { synchronized (mLock) { - Call.this.setCallerInfo(handle, callerInfo); + Call call = Call.this; + if (call != null) { + call.setCallerInfo(handle, callerInfo); + } } } }; + private final boolean mIsModifyStatePermissionGranted; /** * One of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING, or CALL_DIRECTION_UNKNOWN */ @@ -406,6 +439,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, private int mCallerDisplayNamePresentation; /** + * The remote connection service which is attempted or already connecting this call. This is set + * to a non-null value only when a connection manager phone account is in use. When set, this + * will correspond to the target phone account of the {@link Call}. + */ + private ConnectionServiceWrapper mRemoteConnectionService; + + /** * The connection service which is attempted or already connecting this call. */ private ConnectionServiceWrapper mConnectionService; @@ -757,6 +797,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, */ private CompletableFuture<Boolean> mDisconnectFuture; + private FeatureFlags mFlags; + /** * Persists the specified parameters and initializes the new instance. * @param context The context. @@ -788,11 +830,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, boolean shouldAttachToExistingConnection, boolean isConference, ClockProxy clockProxy, - ToastFactory toastFactory) { + ToastFactory toastFactory, + FeatureFlags featureFlags) { this(callId, context, callsManager, lock, repository, phoneNumberUtilsAdapter, handle, null, gatewayInfo, connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, shouldAttachToExistingConnection, - isConference, clockProxy, toastFactory); + isConference, clockProxy, toastFactory, featureFlags); } @@ -812,8 +855,9 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, boolean shouldAttachToExistingConnection, boolean isConference, ClockProxy clockProxy, - ToastFactory toastFactory) { - + ToastFactory toastFactory, + FeatureFlags featureFlags) { + mFlags = featureFlags; mId = callId; mConnectionId = callId; mState = (isConference && callDirection != CALL_DIRECTION_INCOMING && @@ -844,6 +888,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mStartRingTime = 0; mCallStateChangedAtomWriter.setExistingCallCount(callsManager.getCalls().size()); + mIsModifyStatePermissionGranted = + isModifyPhoneStatePermissionGranted(getDelegatePhoneAccountHandle()); } /** @@ -863,6 +909,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, * connection, regardless of whether it's incoming or outgoing. * @param connectTimeMillis The connection time of the call. * @param clockProxy + * @param featureFlags The telecom feature flags. */ Call( String callId, @@ -881,11 +928,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, long connectTimeMillis, long connectElapsedTimeMillis, ClockProxy clockProxy, - ToastFactory toastFactory) { + ToastFactory toastFactory, + FeatureFlags featureFlags) { this(callId, context, callsManager, lock, repository, phoneNumberUtilsAdapter, handle, gatewayInfo, connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, - shouldAttachToExistingConnection, isConference, clockProxy, toastFactory); + shouldAttachToExistingConnection, isConference, clockProxy, toastFactory, + featureFlags); mConnectTimeMillis = connectTimeMillis; mConnectElapsedTimeMillis = connectElapsedTimeMillis; @@ -1328,6 +1377,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, Log.addEvent(this, event, stringData); } + if (mFlags.transactionalCsVerifier()) { + for (CallStateListener listener : mCallStateListeners) { + listener.onCallStateChanged(newState); + } + } + mCallStateChangedAtomWriter .setDisconnectCause(getDisconnectCause()) .setSelfManaged(isSelfManaged()) @@ -1733,8 +1788,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, accountHandle.getComponentName().getPackageName(), mContext.getPackageManager()); // Set the associated user for the call for MT calls based on the target phone account. - if (isIncoming() && !accountHandle.getUserHandle().equals(mAssociatedUser)) { - setAssociatedUser(accountHandle.getUserHandle()); + UserHandle associatedUser = UserUtil.getAssociatedUserForCall( + mFlags.associatedUserRefactorForWorkProfile(), + mCallsManager.getPhoneAccountRegistrar(), mCallsManager.getCurrentUserHandle(), + accountHandle); + if (isIncoming() && !associatedUser.equals(mAssociatedUser)) { + setAssociatedUser(associatedUser); } } } @@ -2313,11 +2372,25 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, @VisibleForTesting public void setConnectionService(ConnectionServiceWrapper service) { + setConnectionService(service, null); + } + + @VisibleForTesting + public void setConnectionService( + ConnectionServiceWrapper service, + ConnectionServiceWrapper remoteService + ) { Preconditions.checkNotNull(service); clearConnectionService(); service.incrementAssociatedCallCount(); + + if (mFlags.updatedRcsCallCountTracking() && remoteService != null) { + remoteService.incrementAssociatedCallCount(); + mRemoteConnectionService = remoteService; + } + mConnectionService = service; mAnalytics.setCallConnectionService(service.getComponentName().flattenToShortString()); mConnectionService.addCall(this); @@ -2325,10 +2398,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, /** * Perform an in-place replacement of the {@link ConnectionServiceWrapper} for this Call. - * Removes the call from its former {@link ConnectionServiceWrapper}, ensuring that the - * ConnectionService is NOT unbound if the call count hits zero. - * This is used by the {@link ConnectionServiceWrapper} when handling {@link Connection} and - * {@link Conference} additions via a ConnectionManager. + * Removes the call from its former {@link ConnectionServiceWrapper}, while still ensuring the + * former {@link ConnectionServiceWrapper} is tracked as the mRemoteConnectionService for this + * call so that the associatedCallCount of that {@link ConnectionServiceWrapper} is accurately + * tracked until it is supposed to be unbound. + * This method is used by the {@link ConnectionServiceWrapper} when handling {@link Connection} + * and {@link Conference} additions via a ConnectionManager. * The original {@link android.telecom.ConnectionService} will directly add external calls and * conferences to Telecom as well as the ConnectionManager, which will add to Telecom. In these * cases since its first added to via the original CS, we want to change the CS responsible for @@ -2341,9 +2416,18 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, if (mConnectionService != null) { ConnectionServiceWrapper serviceTemp = mConnectionService; + + if (mFlags.updatedRcsCallCountTracking()) { + // Continue to track the former CS for this call so that it doesn't unbind early: + mRemoteConnectionService = serviceTemp; + } + mConnectionService = null; serviceTemp.removeCall(this); - serviceTemp.decrementAssociatedCallCount(true /*isSuppressingUnbind*/); + + if (!mFlags.updatedRcsCallCountTracking()) { + serviceTemp.decrementAssociatedCallCount(true /*isSuppressingUnbind*/); + } } service.incrementAssociatedCallCount(); @@ -2357,6 +2441,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, void clearConnectionService() { if (mConnectionService != null) { ConnectionServiceWrapper serviceTemp = mConnectionService; + ConnectionServiceWrapper remoteServiceTemp = mRemoteConnectionService; + mRemoteConnectionService = null; mConnectionService = null; serviceTemp.removeCall(this); @@ -2367,6 +2453,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, // necessary, but cleaning up mConnectionService prior to triggering an unbind is good // to do. decrementAssociatedCallCount(serviceTemp); + + if (mFlags.updatedRcsCallCountTracking() && remoteServiceTemp != null) { + decrementAssociatedCallCount(remoteServiceTemp); + } } } @@ -2385,7 +2475,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return; } mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this, - phoneAccountRegistrar, mContext); + phoneAccountRegistrar, mContext, mFlags); mCreateConnectionProcessor.process(); } @@ -2898,11 +2988,19 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, hold(null /* reason */); } + /** + * This method requests the ConnectionService or TransactionalService hosting the call to put + * the call on hold + */ public void hold(String reason) { if (mState == CallState.ACTIVE) { if (mTransactionalService != null) { mTransactionalService.onSetInactive(this); } else if (mConnectionService != null) { + if (mFlags.transactionalCsVerifier()) { + awaitCallStateChangeAndMaybeDisconnectCall(CallState.ON_HOLD, isSelfManaged(), + "hold"); + } mConnectionService.hold(this); } else { Log.e(this, new NullPointerException(), @@ -2913,6 +3011,27 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } /** + * helper that can be used for any callback that requests a call state change and wants to + * verify the change + */ + public void awaitCallStateChangeAndMaybeDisconnectCall(int targetCallState, + boolean shouldDisconnectUponTimeout, String callingMethod) { + TransactionManager tm = TransactionManager.getInstance(); + tm.addTransaction(new VerifyCallStateChangeTransaction(mCallsManager, + this, targetCallState, shouldDisconnectUponTimeout), new OutcomeReceiver<>() { + @Override + public void onResult(VoipCallTransactionResult result) { + } + + @Override + public void onError(CallException e) { + Log.i(this, "awaitCallStateChangeAndMaybeDisconnectCall: %s: onError" + + " due to CallException=[%s]", callingMethod, e); + } + }); + } + + /** * Releases the call from hold if it is currently active. */ @VisibleForTesting @@ -3039,6 +3158,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE)); } + if (mExtras.containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)) { + if (source != SOURCE_CONNECTION_SERVICE || !mIsModifyStatePermissionGranted) { + mExtras.remove(TelecomManager.EXTRA_DO_NOT_LOG_CALL); + } + } + // If the change originated from an InCallService, notify the connection service. if (source == SOURCE_INCALL_SERVICE) { Log.addEvent(this, LogUtils.Events.ICS_EXTRAS_CHANGED); @@ -3053,6 +3178,15 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } } + private boolean isModifyPhoneStatePermissionGranted(PhoneAccountHandle phoneAccountHandle) { + if (phoneAccountHandle == null) { + return false; + } + String packageName = phoneAccountHandle.getComponentName().getPackageName(); + return PackageManager.PERMISSION_GRANTED == mContext.getPackageManager().checkPermission( + android.Manifest.permission.MODIFY_PHONE_STATE, packageName); + } + /** * Removes extras from the extras bundle associated with this {@link Call}. * @@ -3663,7 +3797,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } String newName = callerInfo.getName(); - boolean contactNameChanged = mCallerInfo == null || !mCallerInfo.getName().equals(newName); + boolean contactNameChanged = mCallerInfo == null || + !Objects.equals(mCallerInfo.getName(), newName); mCallerInfo = callerInfo; Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo); @@ -4032,7 +4167,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, * @param associatedUser */ public void setAssociatedUser(UserHandle associatedUser) { - Log.i(this, "Setting associated user for call"); + Log.i(this, "Setting associated user for call: %s", associatedUser); Preconditions.checkNotNull(associatedUser); mAssociatedUser = associatedUser; } @@ -4182,8 +4317,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, l.onReceivedCallQualityReport(this, callQuality); } } else { - if (event.equals(EVENT_DISPLAY_SOS_MESSAGE) && !isEmergencyCall()) { - Log.w(this, "onConnectionEvent: EVENT_DISPLAY_SOS_MESSAGE is sent " + if (event.equals(EVENT_DISPLAY_EMERGENCY_MESSAGE) && !isEmergencyCall()) { + Log.w(this, "onConnectionEvent: EVENT_DISPLAY_EMERGENCY_MESSAGE is sent " + "without an emergency call"); return; } @@ -4504,6 +4639,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } public void setStartFailCause(CallFailureCause cause) { + Log.i(this, "setStartFailCause: cause = %s; callId = %s", cause, this.getId()); mCallStateChangedAtomWriter.setStartFailCause(cause); } diff --git a/src/com/android/server/telecom/CallAudioCommunicationDeviceTracker.java b/src/com/android/server/telecom/CallAudioCommunicationDeviceTracker.java new file mode 100644 index 000000000..5fc241446 --- /dev/null +++ b/src/com/android/server/telecom/CallAudioCommunicationDeviceTracker.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.telecom; + +import android.bluetooth.BluetoothDevice; +import android.content.Context; +import android.media.AudioDeviceInfo; +import android.media.AudioManager; +import android.telecom.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.telecom.bluetooth.BluetoothRouteManager; +import com.android.server.telecom.flags.Flags; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Semaphore; + +/** + * Helper class used to keep track of the requested communication device within Telecom for audio + * use cases. Handles the set/clear communication use case logic for all audio routes (speaker, BT, + * headset, and earpiece). For BT devices, this handles switches between hearing aids, SCO, and LE + * audio (also takes into account switching between multiple LE audio devices). + */ +public class CallAudioCommunicationDeviceTracker { + + // Use -1 indicates device is not set for any communication use case + private static final int sAUDIO_DEVICE_TYPE_INVALID = -1; + // Possible bluetooth audio device types + private static final Set<Integer> sBT_AUDIO_DEVICE_TYPES = Set.of( + AudioDeviceInfo.TYPE_BLE_HEADSET, + AudioDeviceInfo.TYPE_HEARING_AID, + AudioDeviceInfo.TYPE_BLUETOOTH_SCO + ); + private AudioManager mAudioManager; + private BluetoothRouteManager mBluetoothRouteManager; + private int mAudioDeviceType = sAUDIO_DEVICE_TYPE_INVALID; + // Keep track of the locally requested BT audio device if set + private String mBtAudioDevice = null; + private final Semaphore mLock = new Semaphore(1); + + public CallAudioCommunicationDeviceTracker(Context context) { + mAudioManager = context.getSystemService(AudioManager.class); + } + + public void setBluetoothRouteManager(BluetoothRouteManager bluetoothRouteManager) { + mBluetoothRouteManager = bluetoothRouteManager; + } + + public boolean isAudioDeviceSetForType(int audioDeviceType) { + return mAudioDeviceType == audioDeviceType; + } + + public int getCurrentLocallyRequestedCommunicationDevice() { + return mAudioDeviceType; + } + + @VisibleForTesting + public void setTestCommunicationDevice(int audioDeviceType) { + mAudioDeviceType = audioDeviceType; + } + + public void clearBtCommunicationDevice() { + if (mBtAudioDevice == null) { + Log.i(this, "No bluetooth device was set for communication that can be cleared."); + return; + } + // If mBtAudioDevice is set, we know a BT audio device was set for communication so + // mAudioDeviceType corresponds to a BT device type (e.g. hearing aid, SCO, LE). + clearCommunicationDevice(mAudioDeviceType); + } + + /* + * Sets the communication device for the passed in audio device type, if it's available for + * communication use cases. Tries to clear any communication device which was previously + * requested for communication before setting the new device. + * @param audioDeviceTypes The supported audio device types for the device. + * @param btDevice The bluetooth device to connect to (only used for switching between multiple + * LE audio devices). + * @return {@code true} if the device was set for communication, {@code false} if the device + * wasn't set. + */ + public boolean setCommunicationDevice(int audioDeviceType, + BluetoothDevice btDevice) { + if (Flags.communicationDeviceProtectedByLock()) { + mLock.tryAcquire(); + } + // There is only one audio device type associated with each type of BT device. + boolean isBtDevice = sBT_AUDIO_DEVICE_TYPES.contains(audioDeviceType); + Log.i(this, "setCommunicationDevice: type = %s, isBtDevice = %s, btDevice = %s", + audioDeviceType, isBtDevice, btDevice); + + // Account for switching between multiple LE audio devices. + boolean handleLeAudioDeviceSwitch = btDevice != null + && !btDevice.getAddress().equals(mBtAudioDevice); + if ((audioDeviceType == mAudioDeviceType + || isUsbHeadsetType(audioDeviceType, mAudioDeviceType)) + && !handleLeAudioDeviceSwitch) { + Log.i(this, "Communication device is already set for this audio type"); + return false; + } + + AudioDeviceInfo activeDevice = null; + List<AudioDeviceInfo> devices = mAudioManager.getAvailableCommunicationDevices(); + if (devices.size() == 0) { + Log.w(this, "No communication devices available"); + return false; + } + + for (AudioDeviceInfo device : devices) { + Log.i(this, "Available device type: " + device.getType()); + // Ensure that we do not select the same BT LE audio device for communication. + if ((audioDeviceType == device.getType() + || isUsbHeadsetType(audioDeviceType, device.getType())) + && !device.getAddress().equals(mBtAudioDevice)) { + activeDevice = device; + break; + } + } + + if (activeDevice == null) { + Log.i(this, "No active device of type(s) %s available", + audioDeviceType == AudioDeviceInfo.TYPE_WIRED_HEADSET + ? Arrays.asList(AudioDeviceInfo.TYPE_WIRED_HEADSET, + AudioDeviceInfo.TYPE_USB_HEADSET) + : audioDeviceType); + return false; + } + + // Force clear previous communication device, if one was set, before setting the new device. + if (mAudioDeviceType != sAUDIO_DEVICE_TYPE_INVALID) { + clearCommunicationDevice(mAudioDeviceType); + } + + // Turn activeDevice ON. + boolean result = mAudioManager.setCommunicationDevice(activeDevice); + if (!result) { + Log.w(this, "Could not set active device"); + } else { + Log.i(this, "Active device set"); + mAudioDeviceType = activeDevice.getType(); + if (isBtDevice) { + mBtAudioDevice = activeDevice.getAddress(); + if (audioDeviceType == AudioDeviceInfo.TYPE_BLE_HEADSET) { + mBluetoothRouteManager.onAudioOn(mBtAudioDevice); + } + } else if (Flags.communicationDeviceProtectedByLock()) { + // Clear BT device if it's still stored. Handles race condition for when a non-BT + // device is set for communication shortly after a BT (LE) device is set for + // communication but the selection hasn't been cleared yet. + mBtAudioDevice = null; + } + } + if (Flags.communicationDeviceProtectedByLock()) { + mLock.release(); + } + return result; + } + + /* + * Clears the communication device for the passed in audio device types, given that the device + * has previously been set for communication. + * @param audioDeviceTypes The supported audio device types for the device. + */ + public void clearCommunicationDevice(int audioDeviceType) { + if (Flags.communicationDeviceProtectedByLock()) { + mLock.tryAcquire(); + } + // There is only one audio device type associated with each type of BT device. + boolean isBtDevice = sBT_AUDIO_DEVICE_TYPES.contains(audioDeviceType); + Log.i(this, "clearCommunicationDevice: type = %s, isBtDevice = %s", + audioDeviceType, isBtDevice); + + if (audioDeviceType != mAudioDeviceType + && !isUsbHeadsetType(audioDeviceType, mAudioDeviceType)) { + Log.i(this, "Unable to clear communication device of type(s), %s. " + + "Device does not correspond to the locally requested device type.", + audioDeviceType == AudioDeviceInfo.TYPE_WIRED_HEADSET + ? Arrays.asList(AudioDeviceInfo.TYPE_WIRED_HEADSET, + AudioDeviceInfo.TYPE_USB_HEADSET) + : audioDeviceType + ); + return; + } + + if (mAudioManager == null) { + Log.i(this, "clearCommunicationDevice: mAudioManager is null"); + return; + } + + // Clear device and reset locally saved device type. + mAudioManager.clearCommunicationDevice(); + mAudioDeviceType = sAUDIO_DEVICE_TYPE_INVALID; + + if (isBtDevice && mBtAudioDevice != null) { + // Signal that BT audio was lost for device. + mBluetoothRouteManager.onAudioLost(mBtAudioDevice); + mBtAudioDevice = null; + } + if (Flags.communicationDeviceProtectedByLock()) { + mLock.release(); + } + } + + private boolean isUsbHeadsetType(int audioDeviceType, int sourceType) { + return audioDeviceType != AudioDeviceInfo.TYPE_WIRED_HEADSET + ? false : sourceType == AudioDeviceInfo.TYPE_USB_HEADSET; + } +} diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java index ff76b9e89..96bf2c6bc 100644 --- a/src/com/android/server/telecom/CallAudioManager.java +++ b/src/com/android/server/telecom/CallAudioManager.java @@ -23,7 +23,6 @@ import android.media.ToneGenerator; import android.os.UserHandle; import android.telecom.CallAudioState; import android.telecom.Log; -import android.telecom.PhoneAccount; import android.telecom.VideoProfile; import android.util.SparseArray; @@ -31,11 +30,14 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.CallAudioModeStateMachine.MessageArgs.Builder; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; +import com.android.server.telecom.flags.FeatureFlags; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.LinkedHashSet; +import java.util.stream.Collectors; + public class CallAudioManager extends CallsManagerListenerBase { @@ -52,7 +54,7 @@ public class CallAudioManager extends CallsManagerListenerBase { private final Set<Call> mCalls; private final SparseArray<LinkedHashSet<Call>> mCallStateToCalls; - private final CallAudioRouteStateMachine mCallAudioRouteStateMachine; + private final CallAudioRouteAdapter mCallAudioRouteAdapter; private final CallAudioModeStateMachine mCallAudioModeStateMachine; private final BluetoothStateReceiver mBluetoothStateReceiver; private final CallsManager mCallsManager; @@ -60,6 +62,7 @@ public class CallAudioManager extends CallsManagerListenerBase { private final Ringer mRinger; private final RingbackPlayer mRingbackPlayer; private final DtmfLocalTonePlayer mDtmfLocalTonePlayer; + private final FeatureFlags mFeatureFlags; private Call mStreamingCall; private Call mForegroundCall; @@ -67,14 +70,15 @@ public class CallAudioManager extends CallsManagerListenerBase { private boolean mIsDisconnectedTonePlaying = false; private InCallTonePlayer mHoldTonePlayer; - public CallAudioManager(CallAudioRouteStateMachine callAudioRouteStateMachine, + public CallAudioManager(CallAudioRouteAdapter callAudioRouteAdapter, CallsManager callsManager, CallAudioModeStateMachine callAudioModeStateMachine, InCallTonePlayer.Factory playerFactory, Ringer ringer, RingbackPlayer ringbackPlayer, BluetoothStateReceiver bluetoothStateReceiver, - DtmfLocalTonePlayer dtmfLocalTonePlayer) { + DtmfLocalTonePlayer dtmfLocalTonePlayer, + FeatureFlags featureFlags) { mActiveDialingOrConnectingCalls = new LinkedHashSet<>(1); mRingingCalls = new LinkedHashSet<>(1); mHoldingCalls = new LinkedHashSet<>(1); @@ -92,7 +96,7 @@ public class CallAudioManager extends CallsManagerListenerBase { put(CallState.AUDIO_PROCESSING, mAudioProcessingCalls); }}; - mCallAudioRouteStateMachine = callAudioRouteStateMachine; + mCallAudioRouteAdapter = callAudioRouteAdapter; mCallAudioModeStateMachine = callAudioModeStateMachine; mCallsManager = callsManager; mPlayerFactory = playerFactory; @@ -100,10 +104,11 @@ public class CallAudioManager extends CallsManagerListenerBase { mRingbackPlayer = ringbackPlayer; mBluetoothStateReceiver = bluetoothStateReceiver; mDtmfLocalTonePlayer = dtmfLocalTonePlayer; + mFeatureFlags = featureFlags; mPlayerFactory.setCallAudioManager(this); mCallAudioModeStateMachine.setCallAudioManager(this); - mCallAudioRouteStateMachine.setCallAudioManager(this); + mCallAudioRouteAdapter.setCallAudioManager(this); } @Override @@ -116,7 +121,7 @@ public class CallAudioManager extends CallsManagerListenerBase { // State did not change, so no need to do anything. return; } - Log.d(LOG_TAG, "Call state changed for TC@%s: %s -> %s", call.getId(), + Log.i(this, "onCallStateChanged: Call state changed for TC@%s: %s -> %s", call.getId(), CallState.toString(oldState), CallState.toString(newState)); removeCallFromAllBins(call); @@ -220,7 +225,7 @@ public class CallAudioManager extends CallsManagerListenerBase { // When pulling a video call, automatically enable the speakerphone. Log.d(LOG_TAG, "Switching to speaker because external video call %s was pulled." + call.getId()); - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.SWITCH_SPEAKER); } } @@ -302,7 +307,7 @@ public class CallAudioManager extends CallsManagerListenerBase { VideoProfile.isReceptionEnabled(newVideoState); if (isUpgradeRequest) { - mPlayerFactory.createPlayer(InCallTonePlayer.TONE_VIDEO_UPGRADE).startTone(); + mPlayerFactory.createPlayer(call, InCallTonePlayer.TONE_VIDEO_UPGRADE).startTone(); } } @@ -311,7 +316,7 @@ public class CallAudioManager extends CallsManagerListenerBase { // We only play tones for foreground calls. return; } - mPlayerFactory.createPlayer(InCallTonePlayer.TONE_RTT_REQUEST).startTone(); + mPlayerFactory.createPlayer(call, InCallTonePlayer.TONE_RTT_REQUEST).startTone(); } /** @@ -324,7 +329,7 @@ public class CallAudioManager extends CallsManagerListenerBase { */ @Override public void onHoldToneRequested(Call call) { - maybePlayHoldTone(); + maybePlayHoldTone(call); } @Override @@ -372,7 +377,7 @@ public class CallAudioManager extends CallsManagerListenerBase { @Override public void onConnectionServiceChanged(Call call, ConnectionServiceWrapper oldCs, ConnectionServiceWrapper newCs) { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); } @@ -390,13 +395,13 @@ public class CallAudioManager extends CallsManagerListenerBase { Log.d(LOG_TAG, "Switching to speaker because call %s transitioned video state from %s" + " to %s", call.getId(), VideoProfile.videoStateToString(previousVideoState), VideoProfile.videoStateToString(newVideoState)); - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.SWITCH_SPEAKER); } } public CallAudioState getCallAudioState() { - return mCallAudioRouteStateMachine.getCurrentCallAudioState(); + return mCallAudioRouteAdapter.getCurrentCallAudioState(); } public Call getPossiblyHeldForegroundCall() { @@ -417,7 +422,7 @@ public class CallAudioManager extends CallsManagerListenerBase { Log.v(this, "ignoring toggleMute for emergency call"); return; } - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.TOGGLE_MUTE); } @@ -437,7 +442,7 @@ public class CallAudioManager extends CallsManagerListenerBase { Log.v(this, "ignoring mute for emergency call"); } - mCallAudioRouteStateMachine.sendMessageWithSessionInfo(shouldMute + mCallAudioRouteAdapter.sendMessageWithSessionInfo(shouldMute ? CallAudioRouteStateMachine.MUTE_ON : CallAudioRouteStateMachine.MUTE_OFF); } @@ -453,23 +458,23 @@ public class CallAudioManager extends CallsManagerListenerBase { Log.v(this, "setAudioRoute, route: %s", CallAudioState.audioRouteToString(route)); switch (route) { case CallAudioState.ROUTE_BLUETOOTH: - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.USER_SWITCH_BLUETOOTH, 0, bluetoothAddress); return; case CallAudioState.ROUTE_SPEAKER: - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.USER_SWITCH_SPEAKER); return; case CallAudioState.ROUTE_WIRED_HEADSET: - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.USER_SWITCH_HEADSET); return; case CallAudioState.ROUTE_EARPIECE: - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.USER_SWITCH_EARPIECE); return; case CallAudioState.ROUTE_WIRED_OR_EARPIECE: - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE, CallAudioRouteStateMachine.NO_INCLUDE_BLUETOOTH_IN_BASELINE); return; @@ -484,7 +489,7 @@ public class CallAudioManager extends CallsManagerListenerBase { */ void switchBaseline() { Log.i(this, "switchBaseline"); - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE, CallAudioRouteStateMachine.INCLUDE_BLUETOOTH_IN_BASELINE); } @@ -528,7 +533,7 @@ public class CallAudioManager extends CallsManagerListenerBase { synchronized (mCallsManager.getLock()) { Call localForegroundCall = mForegroundCall; boolean result = mRinger.startRinging(localForegroundCall, - mCallAudioRouteStateMachine.isHfpDeviceAvailable()); + mCallAudioRouteAdapter.isHfpDeviceAvailable()); if (result) { localForegroundCall.setStartRingTime(); } @@ -561,7 +566,7 @@ public class CallAudioManager extends CallsManagerListenerBase { @VisibleForTesting public void setCallAudioRouteFocusState(int focusState) { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.SWITCH_FOCUS, focusState); } @@ -571,8 +576,8 @@ public class CallAudioManager extends CallsManagerListenerBase { } @VisibleForTesting - public CallAudioRouteStateMachine getCallAudioRouteStateMachine() { - return mCallAudioRouteStateMachine; + public CallAudioRouteAdapter getCallAudioRouteAdapter() { + return mCallAudioRouteAdapter; } @VisibleForTesting @@ -609,9 +614,9 @@ public class CallAudioManager extends CallsManagerListenerBase { mCallAudioModeStateMachine.dump(pw); pw.decreaseIndent(); - pw.println("CallAudioRouteStateMachine:"); + pw.println("mCallAudioRouteAdapter:"); pw.increaseIndent(); - mCallAudioRouteStateMachine.dump(pw); + mCallAudioRouteAdapter.dump(pw); pw.decreaseIndent(); pw.println("BluetoothDeviceManager:"); @@ -623,7 +628,7 @@ public class CallAudioManager extends CallsManagerListenerBase { } @VisibleForTesting - public void setIsTonePlaying(boolean isTonePlaying) { + public void setIsTonePlaying(Call call, boolean isTonePlaying) { Log.i(this, "setIsTonePlaying; isTonePlaying=%b", isTonePlaying); mIsTonePlaying = isTonePlaying; mCallAudioModeStateMachine.sendMessageWithArgs( @@ -632,7 +637,7 @@ public class CallAudioManager extends CallsManagerListenerBase { makeArgsForModeStateMachine()); if (!isTonePlaying && mIsDisconnectedTonePlaying) { - mCallsManager.onDisconnectedTonePlaying(false); + mCallsManager.onDisconnectedTonePlaying(call, false); mIsDisconnectedTonePlaying = false; } } @@ -761,6 +766,7 @@ public class CallAudioManager extends CallsManagerListenerBase { private void updateForegroundCall() { Call oldForegroundCall = mForegroundCall; + if (mActiveDialingOrConnectingCalls.size() > 0) { // Give preference for connecting calls over active/dialing for foreground-ness. Call possibleConnectingCall = null; @@ -769,8 +775,27 @@ public class CallAudioManager extends CallsManagerListenerBase { possibleConnectingCall = call; } } - mForegroundCall = possibleConnectingCall == null ? - mActiveDialingOrConnectingCalls.iterator().next() : possibleConnectingCall; + if (mFeatureFlags.ensureAudioModeUpdatesOnForegroundCallChange()) { + // Prefer a connecting call + if (possibleConnectingCall != null) { + mForegroundCall = possibleConnectingCall; + } else { + // Next, prefer an active or dialing call which is not in the process of being + // disconnected. + mForegroundCall = mActiveDialingOrConnectingCalls + .stream() + .filter(c -> (c.getState() == CallState.ACTIVE + || c.getState() == CallState.DIALING) + && !c.isLocallyDisconnecting()) + .findFirst() + // If we can't find one, then just fall back to the first one. + .orElse(mActiveDialingOrConnectingCalls.iterator().next()); + } + } else { + // Legacy (buggy) behavior. + mForegroundCall = possibleConnectingCall == null ? + mActiveDialingOrConnectingCalls.iterator().next() : possibleConnectingCall; + } } else if (mRingingCalls.size() > 0) { mForegroundCall = mRingingCalls.iterator().next(); } else if (mHoldingCalls.size() > 0) { @@ -778,12 +803,27 @@ public class CallAudioManager extends CallsManagerListenerBase { } else { mForegroundCall = null; } - + Log.i(this, "updateForegroundCall; oldFg=%s, newFg=%s, aDC=%s, ring=%s, hold=%s", + (oldForegroundCall == null ? "none" : oldForegroundCall.getId()), + (mForegroundCall == null ? "none" : mForegroundCall.getId()), + mActiveDialingOrConnectingCalls.stream().map(c -> c.getId()).collect( + Collectors.joining(",")), + mRingingCalls.stream().map(c -> c.getId()).collect(Collectors.joining(",")), + mHoldingCalls.stream().map(c -> c.getId()).collect(Collectors.joining(",")) + ); if (mForegroundCall != oldForegroundCall) { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioRouteAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); + + if (mForegroundCall != null + && mFeatureFlags.ensureAudioModeUpdatesOnForegroundCallChange()) { + // Ensure the voip audio mode for the new foreground call is taken into account. + mCallAudioModeStateMachine.sendMessageWithArgs( + CallAudioModeStateMachine.FOREGROUND_VOIP_MODE_CHANGE, + makeArgsForModeStateMachine()); + } mDtmfLocalTonePlayer.onForegroundCallChanged(oldForegroundCall, mForegroundCall); - maybePlayHoldTone(); + maybePlayHoldTone(oldForegroundCall); } } @@ -886,9 +926,9 @@ public class CallAudioManager extends CallsManagerListenerBase { Log.d(this, "Found a disconnected call with tone to play %d.", toneToPlay); if (toneToPlay != InCallTonePlayer.TONE_INVALID) { - boolean didToneStart = mPlayerFactory.createPlayer(toneToPlay).startTone(); + boolean didToneStart = mPlayerFactory.createPlayer(call, toneToPlay).startTone(); if (didToneStart) { - mCallsManager.onDisconnectedTonePlaying(true); + mCallsManager.onDisconnectedTonePlaying(call, true); mIsDisconnectedTonePlaying = true; } } @@ -908,10 +948,11 @@ public class CallAudioManager extends CallsManagerListenerBase { /** * Determines if a hold tone should be played and then starts or stops it accordingly. */ - private void maybePlayHoldTone() { + private void maybePlayHoldTone(Call call) { if (shouldPlayHoldTone()) { if (mHoldTonePlayer == null) { - mHoldTonePlayer = mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING); + mHoldTonePlayer = mPlayerFactory.createPlayer(call, + InCallTonePlayer.TONE_CALL_WAITING); mHoldTonePlayer.startTone(); } } else { diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java index 9ad9094ef..71956a1e0 100644 --- a/src/com/android/server/telecom/CallAudioModeStateMachine.java +++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java @@ -16,6 +16,8 @@ package com.android.server.telecom; +import android.media.AudioAttributes; +import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.Looper; import android.os.Message; @@ -29,6 +31,7 @@ import com.android.internal.util.IState; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.server.telecom.flags.FeatureFlags; public class CallAudioModeStateMachine extends StateMachine { /** @@ -38,11 +41,29 @@ public class CallAudioModeStateMachine extends StateMachine { private LocalLog mLocalLog = new LocalLog(20); public static class Factory { public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper, - AudioManager am) { - return new CallAudioModeStateMachine(systemStateHelper, am); + AudioManager am, FeatureFlags featureFlags, + CallAudioCommunicationDeviceTracker callAudioCommunicationDeviceTracker) { + return new CallAudioModeStateMachine(systemStateHelper, am, + featureFlags, callAudioCommunicationDeviceTracker); } } + private static final AudioAttributes RING_AUDIO_ATTRIBUTES = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .setLegacyStreamType(AudioManager.STREAM_RING) + .build(); + public static final AudioFocusRequest RING_AUDIO_FOCUS_REQUEST = new AudioFocusRequest + .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) + .setAudioAttributes(RING_AUDIO_ATTRIBUTES).build(); + + private static final AudioAttributes CALL_AUDIO_ATTRIBUTES = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) + .setLegacyStreamType(AudioManager.STREAM_VOICE_CALL) + .build(); + public static final AudioFocusRequest CALL_AUDIO_FOCUS_REQUEST = new AudioFocusRequest + .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) + .setAudioAttributes(CALL_AUDIO_ATTRIBUTES).build(); + public static class MessageArgs { public boolean hasActiveOrDialingCalls; public boolean hasRingingCalls; @@ -212,6 +233,8 @@ public class CallAudioModeStateMachine extends StateMachine { public static final String STREAMING_STATE_NAME = StreamingFocusState.class.getSimpleName(); public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName(); + private AudioFocusRequest mCurrentAudioFocusRequest = null; + private class BaseState extends State { @Override public boolean processMessage(Message msg) { @@ -256,8 +279,20 @@ public class CallAudioModeStateMachine extends StateMachine { Log.i(LOG_TAG, "Audio focus entering UNFOCUSED state"); mLocalLog.log("Enter UNFOCUSED"); if (mIsInitialized) { - mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.NO_FOCUS); - mAudioManager.setMode(AudioManager.MODE_NORMAL); + // Clear any communication device that was requested previously. + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice(mCommunicationDeviceTracker + .getCurrentLocallyRequestedCommunicationDevice()); + } + if (mFeatureFlags.setAudioModeBeforeAbandonFocus()) { + mAudioManager.setMode(AudioManager.MODE_NORMAL); + mCallAudioManager.setCallAudioRouteFocusState( + CallAudioRouteStateMachine.NO_FOCUS); + } else { + mCallAudioManager.setCallAudioRouteFocusState( + CallAudioRouteStateMachine.NO_FOCUS); + mAudioManager.setMode(AudioManager.MODE_NORMAL); + } mLocalLog.log("Mode MODE_NORMAL"); mMostRecentMode = AudioManager.MODE_NORMAL; // Don't release focus here -- wait until we get a signal that any other audio @@ -310,7 +345,14 @@ public class CallAudioModeStateMachine extends StateMachine { return HANDLED; case AUDIO_OPERATIONS_COMPLETE: Log.i(LOG_TAG, "Abandoning audio focus: now UNFOCUSED"); - mAudioManager.abandonAudioFocusForCall(); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + if (mCurrentAudioFocusRequest != null) { + mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest); + mCurrentAudioFocusRequest = null; + } + } else { + mAudioManager.abandonAudioFocusForCall(); + } return HANDLED; default: // The forced focus switch commands are handled by BaseState. @@ -381,7 +423,14 @@ public class CallAudioModeStateMachine extends StateMachine { return HANDLED; case AUDIO_OPERATIONS_COMPLETE: Log.i(LOG_TAG, "Abandoning audio focus: now AUDIO_PROCESSING"); - mAudioManager.abandonAudioFocusForCall(); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + if (mCurrentAudioFocusRequest != null) { + mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest); + mCurrentAudioFocusRequest = null; + } + } else { + mAudioManager.abandonAudioFocusForCall(); + } return HANDLED; default: // The forced focus switch commands are handled by BaseState. @@ -406,8 +455,13 @@ public class CallAudioModeStateMachine extends StateMachine { } if (mCallAudioManager.startRinging()) { - mAudioManager.requestAudioFocusForCall( - AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + mCurrentAudioFocusRequest = RING_AUDIO_FOCUS_REQUEST; + mAudioManager.requestAudioFocus(RING_AUDIO_FOCUS_REQUEST); + } else { + mAudioManager.requestAudioFocusForCall( + AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + } // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode -- // this trips up the audio system. if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) { @@ -504,8 +558,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering SIM CALL state"); mLocalLog.log("Enter SIM_CALL"); - mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; + mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); + } else { + mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + } mAudioManager.setMode(AudioManager.MODE_IN_CALL); mLocalLog.log("Mode MODE_IN_CALL"); mMostRecentMode = AudioManager.MODE_IN_CALL; @@ -587,8 +646,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering VOIP CALL state"); mLocalLog.log("Enter VOIP_CALL"); - mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; + mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); + } else { + mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + } mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); mLocalLog.log("Mode MODE_IN_COMMUNICATION"); mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION; @@ -670,12 +734,12 @@ public class CallAudioModeStateMachine extends StateMachine { mAudioManager.setMode(AudioManager.MODE_COMMUNICATION_REDIRECT); mMostRecentMode = AudioManager.MODE_NORMAL; mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS); - mCallAudioManager.getCallAudioRouteStateMachine().sendMessageWithSessionInfo( + mCallAudioManager.getCallAudioRouteAdapter().sendMessageWithSessionInfo( CallAudioRouteStateMachine.STREAMING_FORCE_ENABLED); } private void preExit() { - mCallAudioManager.getCallAudioRouteStateMachine().sendMessageWithSessionInfo( + mCallAudioManager.getCallAudioRouteAdapter().sendMessageWithSessionInfo( CallAudioRouteStateMachine.STREAMING_FORCE_DISABLED); } @@ -742,8 +806,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state"); mLocalLog.log("Enter TONE/HOLDING"); - mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; + mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); + } else { + mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + } mAudioManager.setMode(mMostRecentMode); mLocalLog.log("Mode " + mMostRecentMode); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS); @@ -815,16 +884,21 @@ public class CallAudioModeStateMachine extends StateMachine { private final AudioManager mAudioManager; private final SystemStateHelper mSystemStateHelper; private CallAudioManager mCallAudioManager; + private FeatureFlags mFeatureFlags; + private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; private int mMostRecentMode; private boolean mIsInitialized = false; public CallAudioModeStateMachine(SystemStateHelper systemStateHelper, - AudioManager audioManager) { + AudioManager audioManager, FeatureFlags featureFlags, + CallAudioCommunicationDeviceTracker callAudioCommunicationDeviceTracker) { super(CallAudioModeStateMachine.class.getSimpleName()); mAudioManager = audioManager; mSystemStateHelper = systemStateHelper; mMostRecentMode = AudioManager.MODE_NORMAL; + mFeatureFlags = featureFlags; + mCommunicationDeviceTracker = callAudioCommunicationDeviceTracker; createStates(); } @@ -833,11 +907,14 @@ public class CallAudioModeStateMachine extends StateMachine { * Used for testing */ public CallAudioModeStateMachine(SystemStateHelper systemStateHelper, - AudioManager audioManager, Looper looper) { + AudioManager audioManager, Looper looper, FeatureFlags featureFlags, + CallAudioCommunicationDeviceTracker communicationDeviceTracker) { super(CallAudioModeStateMachine.class.getSimpleName(), looper); mAudioManager = audioManager; mSystemStateHelper = systemStateHelper; mMostRecentMode = AudioManager.MODE_NORMAL; + mFeatureFlags = featureFlags; + mCommunicationDeviceTracker = communicationDeviceTracker; createStates(); } diff --git a/src/com/android/server/telecom/CallAudioRouteAdapter.java b/src/com/android/server/telecom/CallAudioRouteAdapter.java new file mode 100644 index 000000000..7f7b43c70 --- /dev/null +++ b/src/com/android/server/telecom/CallAudioRouteAdapter.java @@ -0,0 +1,19 @@ +package com.android.server.telecom; + +import android.os.Handler; +import android.telecom.CallAudioState; + +import com.android.internal.util.IndentingPrintWriter; + +public interface CallAudioRouteAdapter { + void initialize(); + void sendMessageWithSessionInfo(int message); + void sendMessageWithSessionInfo(int message, int arg); + void sendMessageWithSessionInfo(int message, int arg, String data); + void sendMessage(int message, Runnable r); + void setCallAudioManager(CallAudioManager callAudioManager); + CallAudioState getCurrentCallAudioState(); + boolean isHfpDeviceAvailable(); + Handler getAdapterHandler(); + void dump(IndentingPrintWriter pw); +} diff --git a/src/com/android/server/telecom/CallAudioRouteController.java b/src/com/android/server/telecom/CallAudioRouteController.java new file mode 100644 index 000000000..f8c49bb82 --- /dev/null +++ b/src/com/android/server/telecom/CallAudioRouteController.java @@ -0,0 +1,64 @@ +package com.android.server.telecom; + +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.telecom.CallAudioState; + +import com.android.internal.util.IndentingPrintWriter; + +public class CallAudioRouteController implements CallAudioRouteAdapter { + private Handler mHandler; + + public CallAudioRouteController() { + HandlerThread handlerThread = new HandlerThread(this.getClass().getSimpleName()); + handlerThread.start(); + mHandler = new Handler(handlerThread.getLooper()); + } + @Override + public void initialize() { + } + + @Override + public void sendMessageWithSessionInfo(int message) { + } + + @Override + public void sendMessageWithSessionInfo(int message, int arg) { + + } + + @Override + public void sendMessageWithSessionInfo(int message, int arg, String data) { + + } + + @Override + public void sendMessage(int message, Runnable r) { + + } + + @Override + public void setCallAudioManager(CallAudioManager callAudioManager) { + } + + @Override + public CallAudioState getCurrentCallAudioState() { + return null; + } + + @Override + public boolean isHfpDeviceAvailable() { + return false; + } + + @Override + public Handler getAdapterHandler() { + return mHandler; + } + + @Override + public void dump(IndentingPrintWriter pw) { + + } +} diff --git a/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java b/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java index af0757c15..8a87c2236 100644 --- a/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java +++ b/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java @@ -25,17 +25,17 @@ import com.android.server.telecom.bluetooth.BluetoothRouteManager; public class CallAudioRoutePeripheralAdapter implements WiredHeadsetManager.Listener, DockManager.Listener, BluetoothRouteManager.BluetoothStateListener { - private final CallAudioRouteStateMachine mCallAudioRouteStateMachine; + private final CallAudioRouteAdapter mCallAudioAdapter; private final BluetoothRouteManager mBluetoothRouteManager; private final AsyncRingtonePlayer mRingtonePlayer; public CallAudioRoutePeripheralAdapter( - CallAudioRouteStateMachine callAudioRouteStateMachine, + CallAudioRouteAdapter callAudioRouteAdapter, BluetoothRouteManager bluetoothManager, WiredHeadsetManager wiredHeadsetManager, DockManager dockManager, AsyncRingtonePlayer ringtonePlayer) { - mCallAudioRouteStateMachine = callAudioRouteStateMachine; + mCallAudioAdapter = callAudioRouteAdapter; mBluetoothRouteManager = bluetoothManager; mRingtonePlayer = ringtonePlayer; @@ -60,26 +60,26 @@ public class CallAudioRoutePeripheralAdapter implements WiredHeadsetManager.List @Override public void onBluetoothDeviceListChanged() { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED); } @Override public void onBluetoothActiveDevicePresent() { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT); } @Override public void onBluetoothActiveDeviceGone() { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE); } @Override public void onBluetoothAudioConnected() { mRingtonePlayer.updateBtActiveState(true); - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); } @@ -87,20 +87,20 @@ public class CallAudioRoutePeripheralAdapter implements WiredHeadsetManager.List public void onBluetoothAudioConnecting() { mRingtonePlayer.updateBtActiveState(false); // Pretend like audio is connected when communicating w/ CARSM. - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); } @Override public void onBluetoothAudioDisconnected() { mRingtonePlayer.updateBtActiveState(false); - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_AUDIO_DISCONNECTED); } @Override public void onUnexpectedBluetoothStateChange() { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); } @@ -111,17 +111,17 @@ public class CallAudioRoutePeripheralAdapter implements WiredHeadsetManager.List @Override public void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn) { if (!oldIsPluggedIn && newIsPluggedIn) { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET); } else if (oldIsPluggedIn && !newIsPluggedIn){ - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET); } } @Override public void onDockChanged(boolean isDocked) { - mCallAudioRouteStateMachine.sendMessageWithSessionInfo( + mCallAudioAdapter.sendMessageWithSessionInfo( isDocked ? CallAudioRouteStateMachine.CONNECT_DOCK : CallAudioRouteStateMachine.DISCONNECT_DOCK ); diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java index dbc6d6ae5..c0bb50e2f 100644 --- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java +++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java @@ -28,6 +28,7 @@ import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.IAudioService; import android.os.Binder; +import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; @@ -44,6 +45,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.telecom.bluetooth.BluetoothRouteManager; +import com.android.server.telecom.flags.FeatureFlags; import java.util.Collection; import java.util.HashMap; @@ -72,7 +74,7 @@ import java.util.concurrent.Executor; * from a wired headset * mIsMuted: a boolean indicating whether the audio is muted */ -public class CallAudioRouteStateMachine extends StateMachine { +public class CallAudioRouteStateMachine extends StateMachine implements CallAudioRouteAdapter { public static class Factory { public CallAudioRouteStateMachine create( @@ -83,7 +85,9 @@ public class CallAudioRouteStateMachine extends StateMachine { StatusBarNotifier statusBarNotifier, CallAudioManager.AudioServiceFactory audioServiceFactory, int earpieceControl, - Executor asyncTaskExecutor) { + Executor asyncTaskExecutor, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { return new CallAudioRouteStateMachine(context, callsManager, bluetoothManager, @@ -91,7 +95,9 @@ public class CallAudioRouteStateMachine extends StateMachine { statusBarNotifier, audioServiceFactory, earpieceControl, - asyncTaskExecutor); + asyncTaskExecutor, + communicationDeviceTracker, + featureFlags); } } /** Values for CallAudioRouteStateMachine constructor's earPieceRouting arg. */ @@ -371,6 +377,10 @@ public class CallAudioRouteStateMachine extends StateMachine { public void enter() { super.enter(); setSpeakerphoneOn(false); + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, null); + } CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_EARPIECE, mAvailableRoutes, null, mBluetoothRouteManager.getConnectedDevices()); @@ -401,6 +411,10 @@ public class CallAudioRouteStateMachine extends StateMachine { case SWITCH_BLUETOOTH: case USER_SWITCH_BLUETOOTH: if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) { + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_BUILTIN_EARPIECE); + } if (mAudioFocusType == ACTIVE_FOCUS || mBluetoothRouteManager.isInbandRingingEnabled()) { String address = (msg.obj instanceof SomeArgs) ? @@ -417,6 +431,10 @@ public class CallAudioRouteStateMachine extends StateMachine { case SWITCH_HEADSET: case USER_SWITCH_HEADSET: if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) { + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_BUILTIN_EARPIECE); + } transitionTo(mActiveHeadsetRoute); } else { Log.w(this, "Ignoring switch to headset command. Not available."); @@ -426,6 +444,10 @@ public class CallAudioRouteStateMachine extends StateMachine { // fall through; we want to switch to speaker mode when docked and in a call. case SWITCH_SPEAKER: case USER_SWITCH_SPEAKER: + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_BUILTIN_EARPIECE); + } setSpeakerphoneOn(true); // fall through case SPEAKER_ON: @@ -579,6 +601,10 @@ public class CallAudioRouteStateMachine extends StateMachine { public void enter() { super.enter(); setSpeakerphoneOn(false); + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_WIRED_HEADSET, null); + } CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_WIRED_HEADSET, mAvailableRoutes, null, mBluetoothRouteManager.getConnectedDevices()); setSystemAudioState(newState, true); @@ -600,6 +626,10 @@ public class CallAudioRouteStateMachine extends StateMachine { case SWITCH_EARPIECE: case USER_SWITCH_EARPIECE: if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) { + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_WIRED_HEADSET); + } transitionTo(mActiveEarpieceRoute); } else { Log.w(this, "Ignoring switch to earpiece command. Not available."); @@ -615,6 +645,10 @@ public class CallAudioRouteStateMachine extends StateMachine { || mBluetoothRouteManager.isInbandRingingEnabled()) { String address = (msg.obj instanceof SomeArgs) ? (String) ((SomeArgs) msg.obj).arg2 : null; + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_WIRED_HEADSET); + } // Omit transition to ActiveBluetoothRoute until actual connection. setBluetoothOn(address); } else { @@ -631,6 +665,10 @@ public class CallAudioRouteStateMachine extends StateMachine { return HANDLED; case SWITCH_SPEAKER: case USER_SWITCH_SPEAKER: + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_WIRED_HEADSET); + } setSpeakerphoneOn(true); // fall through case SPEAKER_ON: @@ -793,6 +831,17 @@ public class CallAudioRouteStateMachine extends StateMachine { public void enter() { super.enter(); setSpeakerphoneOn(false); + // Try arbitrarily connecting to BT audio if we haven't already. This handles + // the edge case of when the audio route is in a quiescent route while in-call and + // the BT connection fails to be set. Previously, the logic was to setBluetoothOn in + // ACTIVE_FOCUS but the route would still remain in a quiescent route, so instead we + // should be transitioning directly into the active route. + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + setBluetoothOn(null); + } + if (mFeatureFlags.updateRouteMaskWhenBtConnected()) { + mAvailableRoutes |= ROUTE_BLUETOOTH; + } CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_BLUETOOTH, mAvailableRoutes, mBluetoothRouteManager.getBluetoothAudioConnectedDevice(), mBluetoothRouteManager.getConnectedDevices()); @@ -893,8 +942,13 @@ public class CallAudioRouteStateMachine extends StateMachine { case SWITCH_FOCUS: if (msg.arg1 == NO_FOCUS) { // Only disconnect audio here instead of routing away from BT entirely. - mBluetoothRouteManager.disconnectAudio(); - reinitialize(); + if (mFeatureFlags.transitRouteBeforeAudioDisconnectBt()) { + transitionTo(mQuiescentBluetoothRoute); + mBluetoothRouteManager.disconnectAudio(); + } else { + mBluetoothRouteManager.disconnectAudio(); + reinitialize(); + } mCallAudioManager.notifyAudioOperationsComplete(); } else if (msg.arg1 == RINGING_FOCUS && !mBluetoothRouteManager.isInbandRingingEnabled()) { @@ -1019,6 +1073,9 @@ public class CallAudioRouteStateMachine extends StateMachine { public void enter() { super.enter(); mHasUserExplicitlyLeftBluetooth = false; + if (mFeatureFlags.resetMuteWhenEnteringQuiescentBtRoute()) { + setMuteOn(false); + } updateInternalCallAudioState(); } @@ -1065,7 +1122,13 @@ public class CallAudioRouteStateMachine extends StateMachine { return HANDLED; case SWITCH_FOCUS: if (msg.arg1 == ACTIVE_FOCUS) { - setBluetoothOn(null); + // It is possible that the connection to BT will fail while in-call, in + // which case, we want to transition into the active route. + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + transitionTo(mActiveBluetoothRoute); + } else { + setBluetoothOn(null); + } } else if (msg.arg1 == RINGING_FOCUS) { if (mBluetoothRouteManager.isInbandRingingEnabled()) { setBluetoothOn(null); @@ -1520,6 +1583,8 @@ public class CallAudioRouteStateMachine extends StateMachine { private CallAudioState mLastKnownCallAudioState; private CallAudioManager mCallAudioManager; + private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; + private FeatureFlags mFeatureFlags; public CallAudioRouteStateMachine( Context context, @@ -1529,7 +1594,9 @@ public class CallAudioRouteStateMachine extends StateMachine { StatusBarNotifier statusBarNotifier, CallAudioManager.AudioServiceFactory audioServiceFactory, int earpieceControl, - Executor asyncTaskExecutor) { + Executor asyncTaskExecutor, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { super(NAME); mContext = context; mCallsManager = callsManager; @@ -1540,6 +1607,8 @@ public class CallAudioRouteStateMachine extends StateMachine { mAudioServiceFactory = audioServiceFactory; mLock = callsManager.getLock(); mAsyncTaskExecutor = asyncTaskExecutor; + mCommunicationDeviceTracker = communicationDeviceTracker; + mFeatureFlags = featureFlags; createStates(earpieceControl); } @@ -1551,7 +1620,9 @@ public class CallAudioRouteStateMachine extends StateMachine { WiredHeadsetManager wiredHeadsetManager, StatusBarNotifier statusBarNotifier, CallAudioManager.AudioServiceFactory audioServiceFactory, - int earpieceControl, Looper looper, Executor asyncTaskExecutor) { + int earpieceControl, Looper looper, Executor asyncTaskExecutor, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { super(NAME, looper); mContext = context; mCallsManager = callsManager; @@ -1562,7 +1633,8 @@ public class CallAudioRouteStateMachine extends StateMachine { mAudioServiceFactory = audioServiceFactory; mLock = callsManager.getLock(); mAsyncTaskExecutor = asyncTaskExecutor; - + mCommunicationDeviceTracker = communicationDeviceTracker; + mFeatureFlags = featureFlags; createStates(earpieceControl); } @@ -1679,6 +1751,11 @@ public class CallAudioRouteStateMachine extends StateMachine { sendMessage(message, arg, 0, args); } + @Override + public void sendMessage(int message, Runnable r) { + super.sendMessage(message, r); + } + /** * This is for state-independent changes in audio route (i.e. muting or runnables) * @param msg that couldn't be handled. @@ -1708,9 +1785,19 @@ public class CallAudioRouteStateMachine extends StateMachine { } return; case UPDATE_SYSTEM_AUDIO_ROUTE: - updateInternalCallAudioState(); - updateRouteForForegroundCall(); - resendSystemAudioState(); + if (mFeatureFlags.availableRoutesNeverUpdatedAfterSetSystemAudioState()) { + // Ensure available routes is updated. + updateRouteForForegroundCall(); + // Ensure current audio state gets updated to take this into account. + updateInternalCallAudioState(); + // Either resend the current audio state as it stands, or update to reflect any + // changes put into place based on mAvailableRoutes + setSystemAudioState(mCurrentCallAudioState, true); + } else { + updateInternalCallAudioState(); + updateRouteForForegroundCall(); + resendSystemAudioState(); + } return; case RUN_RUNNABLE: java.lang.Runnable r = (java.lang.Runnable) msg.obj; @@ -1735,7 +1822,7 @@ public class CallAudioRouteStateMachine extends StateMachine { } public void dumpPendingMessages(IndentingPrintWriter pw) { - getHandler().getLooper().dump(pw::println, ""); + getAdapterHandler().getLooper().dump(pw::println, ""); } public boolean isHfpDeviceAvailable() { @@ -1747,31 +1834,19 @@ public class CallAudioRouteStateMachine extends StateMachine { final boolean hasAnyCalls = mCallsManager.hasAnyCalls(); // These APIs are all via two-way binder calls so can potentially block Telecom. Since none // of this has to happen in the Telecom lock we'll offload it to the async executor. - - AudioDeviceInfo speakerDevice = null; - for (AudioDeviceInfo info : mAudioManager.getAvailableCommunicationDevices()) { - if (info.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { - speakerDevice = info; - break; - } - } boolean speakerOn = false; - if (speakerDevice != null && on) { - boolean result = mAudioManager.setCommunicationDevice(speakerDevice); - if (result) { - speakerOn = true; + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + if (on) { + speakerOn = mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null); + } else { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); } } else { - AudioDeviceInfo curDevice = mAudioManager.getCommunicationDevice(); - if (curDevice != null - && curDevice.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { - mAudioManager.clearCommunicationDevice(); - } + speakerOn = processLegacySpeakerCommunicationDevice(on); } - final boolean isSpeakerOn = speakerOn; - mAsyncTaskExecutor.execute(() -> { - mStatusBarNotifier.notifySpeakerphone(hasAnyCalls && isSpeakerOn); - }); + mStatusBarNotifier.notifySpeakerphone(hasAnyCalls && speakerOn); } private void setBluetoothOn(String address) { @@ -1869,6 +1944,11 @@ public class CallAudioRouteStateMachine extends StateMachine { setSystemAudioState(mLastKnownCallAudioState, true); } + @VisibleForTesting + public CallAudioState getLastKnownCallAudioState() { + return mLastKnownCallAudioState; + } + private void setSystemAudioState(CallAudioState newCallAudioState, boolean force) { synchronized (mLock) { Log.i(this, "setSystemAudioState: changing from %s to %s", mLastKnownCallAudioState, @@ -1986,6 +2066,58 @@ public class CallAudioRouteStateMachine extends StateMachine { return false; } + private boolean isWatchActiveOrOnlyWatchesAvailable() { + if (!mFeatureFlags.ignoreAutoRouteToWatchDevice()) { + Log.i(this, "isWatchActiveOrOnlyWatchesAvailable: Flag is disabled."); + return false; + } + + boolean containsWatchDevice = false; + boolean containsNonWatchDevice = false; + Collection<BluetoothDevice> connectedBtDevices = + mBluetoothRouteManager.getConnectedDevices(); + + for (BluetoothDevice connectedDevice: connectedBtDevices) { + if (mBluetoothRouteManager.isWatch(connectedDevice)) { + containsWatchDevice = true; + } else { + containsNonWatchDevice = true; + } + } + + // Don't ignore switch if watch is already the active device. + boolean isActiveDeviceWatch = mBluetoothRouteManager.isWatch( + mBluetoothRouteManager.getBluetoothAudioConnectedDevice()); + Log.i(this, "isWatchActiveOrOnlyWatchesAvailable: contains watch: %s, contains " + + "non-wearable device: %s, is active device a watch: %s.", + containsWatchDevice, containsNonWatchDevice, isActiveDeviceWatch); + return containsWatchDevice && !containsNonWatchDevice && !isActiveDeviceWatch; + } + + private boolean processLegacySpeakerCommunicationDevice(boolean on) { + AudioDeviceInfo speakerDevice = null; + for (AudioDeviceInfo info : mAudioManager.getAvailableCommunicationDevices()) { + if (info.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { + speakerDevice = info; + break; + } + } + boolean speakerOn = false; + if (speakerDevice != null && on) { + boolean result = mAudioManager.setCommunicationDevice(speakerDevice); + if (result) { + speakerOn = true; + } + } else { + AudioDeviceInfo curDevice = mAudioManager.getCommunicationDevice(); + if (curDevice != null + && curDevice.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { + mAudioManager.clearCommunicationDevice(); + } + } + return speakerOn; + } + private int calculateBaselineRouteMessage(boolean isExplicitUserRequest, boolean includeBluetooth) { boolean isSkipEarpiece = false; @@ -1998,7 +2130,7 @@ public class CallAudioRouteStateMachine extends StateMachine { } if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0 && !mHasUserExplicitlyLeftBluetooth - && includeBluetooth) { + && includeBluetooth && !isWatchActiveOrOnlyWatchesAvailable()) { return isExplicitUserRequest ? USER_SWITCH_BLUETOOTH : SWITCH_BLUETOOTH; } else if ((mAvailableRoutes & ROUTE_EARPIECE) != 0 && !isSkipEarpiece) { return isExplicitUserRequest ? USER_SWITCH_EARPIECE : SWITCH_EARPIECE; @@ -2054,4 +2186,8 @@ public class CallAudioRouteStateMachine extends StateMachine { return base; } + + public Handler getAdapterHandler() { + return getHandler(); + } } diff --git a/src/com/android/server/telecom/CallDiagnosticServiceController.java b/src/com/android/server/telecom/CallDiagnosticServiceController.java index 6c7ee38af..1077f0d32 100644 --- a/src/com/android/server/telecom/CallDiagnosticServiceController.java +++ b/src/com/android/server/telecom/CallDiagnosticServiceController.java @@ -522,7 +522,7 @@ public class CallDiagnosticServiceController extends CallsManagerListenerBase { callId, messageId, message); if (mPlayerFactory != null) { // Play that tone! - mPlayerFactory.createPlayer(InCallTonePlayer.TONE_IN_CALL_QUALITY_NOTIFICATION) + mPlayerFactory.createPlayer(call, InCallTonePlayer.TONE_IN_CALL_QUALITY_NOTIFICATION) .startTone(); } call.displayDiagnosticMessage(messageId, message); diff --git a/src/com/android/server/telecom/CallEndpointController.java b/src/com/android/server/telecom/CallEndpointController.java index 7e11b47f4..4738cd49f 100644 --- a/src/com/android/server/telecom/CallEndpointController.java +++ b/src/com/android/server/telecom/CallEndpointController.java @@ -87,7 +87,7 @@ public class CallEndpointController extends CallsManagerListenerBase { } public void requestCallEndpointChange(CallEndpoint endpoint, ResultReceiver callback) { - Log.d(this, "requestCallEndpointChange %s", endpoint); + Log.i(this, "requestCallEndpointChange %s", endpoint); int route = mTypeToRouteMap.get(endpoint.getEndpointType()); String bluetoothAddress = getBluetoothAddress(endpoint); @@ -99,7 +99,6 @@ public class CallEndpointController extends CallsManagerListenerBase { } if (isCurrentEndpointRequestedEndpoint(route, bluetoothAddress)) { - Log.d(this, "requestCallEndpointChange: requested endpoint is already active"); callback.send(CallEndpoint.ENDPOINT_OPERATION_SUCCESS, new Bundle()); return; } @@ -130,21 +129,27 @@ public class CallEndpointController extends CallsManagerListenerBase { return false; } CallAudioState currentAudioState = mCallsManager.getCallAudioManager().getCallAudioState(); - // requested non-bt endpoint is already active - if (requestedRoute != CallAudioState.ROUTE_BLUETOOTH && - requestedRoute == currentAudioState.getRoute()) { - return true; - } - // requested bt endpoint is already active - if (requestedRoute == CallAudioState.ROUTE_BLUETOOTH && - currentAudioState.getActiveBluetoothDevice() != null && - requestedAddress.equals( - currentAudioState.getActiveBluetoothDevice().getAddress())) { - return true; + if (requestedRoute == currentAudioState.getRoute()) { + if (requestedRoute != CallAudioState.ROUTE_BLUETOOTH) { + // The audio route (earpiece, speaker, etc.) is already active + // and Telecom can ignore the spam request! + Log.i(this, "iCERE: user requested a non-BT route that is already active"); + return true; + } else if (hasSameBluetoothAddress(currentAudioState, requestedAddress)) { + // if the requested (BT route, device) is active, ignore the request... + Log.i(this, "iCERE: user requested a BT endpoint that is already active"); + return true; + } } return false; } + public boolean hasSameBluetoothAddress(CallAudioState audioState, String requestedAddress) { + boolean hasActiveBtDevice = audioState.getActiveBluetoothDevice() != null; + return hasActiveBtDevice && requestedAddress.equals( + audioState.getActiveBluetoothDevice().getAddress()); + } + private Bundle getErrorResult(int result) { String message; int resultCode; diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java index 7953324df..062c872dc 100644 --- a/src/com/android/server/telecom/CallIntentProcessor.java +++ b/src/com/android/server/telecom/CallIntentProcessor.java @@ -1,6 +1,7 @@ package com.android.server.telecom; import com.android.server.telecom.components.ErrorDialogActivity; +import com.android.server.telecom.flags.FeatureFlags; import android.content.Context; import android.content.Intent; @@ -32,7 +33,7 @@ import java.util.concurrent.CompletableFuture; public class CallIntentProcessor { public interface Adapter { void processOutgoingCallIntent(Context context, CallsManager callsManager, - Intent intent, String callingPackage); + Intent intent, String callingPackage, FeatureFlags featureFlags); void processIncomingCallIntent(CallsManager callsManager, Intent intent); void processUnknownCallIntent(CallsManager callsManager, Intent intent); } @@ -45,9 +46,9 @@ public class CallIntentProcessor { @Override public void processOutgoingCallIntent(Context context, CallsManager callsManager, - Intent intent, String callingPackage) { + Intent intent, String callingPackage, FeatureFlags featureFlags) { CallIntentProcessor.processOutgoingCallIntent(context, callsManager, intent, - callingPackage, mDefaultDialerCache); + callingPackage, mDefaultDialerCache, featureFlags); } @Override @@ -73,12 +74,14 @@ public class CallIntentProcessor { private final Context mContext; private final CallsManager mCallsManager; private final DefaultDialerCache mDefaultDialerCache; + private final FeatureFlags mFeatureFlags; public CallIntentProcessor(Context context, CallsManager callsManager, - DefaultDialerCache defaultDialerCache) { + DefaultDialerCache defaultDialerCache, FeatureFlags featureFlags) { this.mContext = context; this.mCallsManager = callsManager; this.mDefaultDialerCache = defaultDialerCache; + this.mFeatureFlags = featureFlags; } public void processIntent(Intent intent, String callingPackage) { @@ -90,7 +93,7 @@ public class CallIntentProcessor { processUnknownCallIntent(mCallsManager, intent); } else { processOutgoingCallIntent(mContext, mCallsManager, intent, callingPackage, - mDefaultDialerCache); + mDefaultDialerCache, mFeatureFlags); } Trace.endSection(); } @@ -107,7 +110,8 @@ public class CallIntentProcessor { CallsManager callsManager, Intent intent, String callingPackage, - DefaultDialerCache defaultDialerCache) { + DefaultDialerCache defaultDialerCache, + FeatureFlags featureFlags) { Uri handle = intent.getData(); String scheme = handle.getScheme(); @@ -182,10 +186,9 @@ public class CallIntentProcessor { boolean isPrivilegedDialer = defaultDialerCache.isDefaultOrSystemDialer(callingPackage, initiatingUser.getIdentifier()); - NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster( context, callsManager, intent, callsManager.getPhoneNumberUtilsAdapter(), - isPrivilegedDialer, defaultDialerCache, new MmiUtils()); + isPrivilegedDialer, defaultDialerCache, new MmiUtils(), featureFlags); // If the broadcaster comes back with an immediate error, disconnect and show a dialog. NewOutgoingCallIntentBroadcaster.CallDisposition disposition = broadcaster.evaluateCall(); diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java index 72aecacd0..fc4e05d69 100644 --- a/src/com/android/server/telecom/CallLogManager.java +++ b/src/com/android/server/telecom/CallLogManager.java @@ -24,6 +24,7 @@ import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.database.Cursor; import android.location.Country; import android.location.CountryDetector; @@ -50,6 +51,7 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.server.telecom.callfiltering.CallFilteringResult; +import com.android.server.telecom.flags.FeatureFlags; import java.util.Arrays; import java.util.Locale; @@ -75,18 +77,18 @@ public final class CallLogManager extends CallsManagerListenerBase { private static class AddCallArgs { public AddCallArgs(Context context, CallLog.AddCallParams params, @Nullable LogCallCompletedListener logCallCompletedListener, - @NonNull String callId) { + @NonNull Call call) { this.context = context; this.params = params; this.logCallCompletedListener = logCallCompletedListener; - this.callId = callId; + this.call = call; } // Since the members are accessed directly, we don't use the // mXxxx notation. public final Context context; public final CallLog.AddCallParams params; - public final String callId; + public final Call call; @Nullable public final LogCallCompletedListener logCallCompletedListener; } @@ -98,9 +100,9 @@ public final class CallLogManager extends CallsManagerListenerBase { // a conference was merged successfully private static final String REASON_IMS_MERGED_SUCCESSFULLY = "IMS_MERGED_SUCCESSFULLY"; private static final UUID LOG_CALL_FAILED_ANOMALY_ID = - UUID.fromString("1c4c15f3-ab4f-459c-b9ef-43d2988bae82"); + UUID.fromString("d9b38771-ff36-417b-8723-2363a870c702"); private static final String LOG_CALL_FAILED_ANOMALY_DESC = - "Failed to record a call to the call log."; + "Based on the current user, Telecom detected failure to record a call to the call log."; private final Context mContext; private final CarrierConfigManager mCarrierConfigManager; @@ -117,8 +119,11 @@ public final class CallLogManager extends CallsManagerListenerBase { private Object mLock; private String mCurrentCountryIso; + private final FeatureFlags mFeatureFlags; + public CallLogManager(Context context, PhoneAccountRegistrar phoneAccountRegistrar, - MissedCallNotifier missedCallNotifier, AnomalyReporterAdapter anomalyReporterAdapter) { + MissedCallNotifier missedCallNotifier, AnomalyReporterAdapter anomalyReporterAdapter, + FeatureFlags featureFlags) { mContext = context; mCarrierConfigManager = (CarrierConfigManager) mContext .getSystemService(Context.CARRIER_CONFIG_SERVICE); @@ -126,6 +131,7 @@ public final class CallLogManager extends CallsManagerListenerBase { mMissedCallNotifier = missedCallNotifier; mAnomalyReporterAdapter = anomalyReporterAdapter; mLock = new Object(); + mFeatureFlags = featureFlags; } @Override @@ -164,9 +170,10 @@ public final class CallLogManager extends CallsManagerListenerBase { * Call was NOT in the "choose account" phase when disconnected * Call is NOT a conference call which had children (unless it was remotely hosted). * Call is NOT a child call from a conference which was remotely hosted. + * Call has NOT indicated it should be skipped for logging in its extras * Call is NOT simulating a single party conference. * Call was NOT explicitly canceled, except for disconnecting from a conference. - * Call is NOT an external call + * Call is NOT an external call or an external call on watch. * Call is NOT disconnected because of merging into a conference. * Call is NOT a self-managed call OR call is a self-managed call which has indicated it * should be logged in its PhoneAccount @@ -195,6 +202,11 @@ public final class CallLogManager extends CallsManagerListenerBase { return false; } + if (mFeatureFlags.telecomSkipLogBasedOnExtra() && call.getExtras() != null + && call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)) { + return false; + } + // A child call of a conference which was remotely hosted; these didn't originate on this // device and should not be logged. if (call.getParentCall() != null && call.hasProperty(Connection.PROPERTY_REMOTELY_HOSTED)) { @@ -215,8 +227,10 @@ public final class CallLogManager extends CallsManagerListenerBase { & Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE) == Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE; } - // An external call - if (call.isExternalCall()) { + // An external and non-watch call + if (call.isExternalCall() && (!mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WATCH) + || !mFeatureFlags.telecomLogExternalWearableCalls())) { return false; } @@ -255,8 +269,13 @@ public final class CallLogManager extends CallsManagerListenerBase { logCall(call, type, new LogCallCompletedListener() { @Override public void onLogCompleted(@Nullable Uri uri) { - mMissedCallNotifier.showMissedCallNotification( - new MissedCallNotifier.CallInfo(call)); + if (mFeatureFlags.addCallUriForMissedCalls()){ + mMissedCallNotifier.showMissedCallNotification( + new MissedCallNotifier.CallInfo(call), uri); + } else { + mMissedCallNotifier.showMissedCallNotification( + new MissedCallNotifier.CallInfo(call), /* uri= */ null); + } } }, result); } else { @@ -400,7 +419,7 @@ public final class CallLogManager extends CallsManagerListenerBase { okayToLogCall(accountHandle, logNumber, call.isEmergencyCall()); if (okayToLog) { AddCallArgs args = new AddCallArgs(mContext, paramBuilder.build(), - logCallCompletedListener, call.getId()); + logCallCompletedListener, call); Log.addEvent(call, LogUtils.Events.LOG_CALL, "number=" + Log.piiHandle(logNumber) + ",postDial=" + Log.piiHandle(call.getPostDialDigits()) + ",pres=" + call.getHandlePresentation()); @@ -531,18 +550,16 @@ public final class CallLogManager extends CallsManagerListenerBase { AddCallArgs c = callList[i]; mListeners[i] = c.logCallCompletedListener; try { - // May block. - ContentResolver resolver = c.context.getContentResolver(); - Pair<Integer, Integer> startStats = getCallLogStats(resolver); + Pair<Integer, Integer> startStats = getCallLogStats(c.call); Log.i(TAG, "LogCall; about to log callId=%s, " + "startCount=%d, startMaxId=%d", - c.callId, startStats.first, startStats.second); + c.call.getId(), startStats.first, startStats.second); result[i] = Calls.addCall(c.context, c.params); - Pair<Integer, Integer> endStats = getCallLogStats(resolver); + Pair<Integer, Integer> endStats = getCallLogStats(c.call); Log.i(TAG, "LogCall; logged callId=%s, uri=%s, " + "endCount=%d, endMaxId=%s", - c.callId, result, endStats.first, endStats.second); + c.call.getId(), result, endStats.first, endStats.second); if ((endStats.second - startStats.second) <= 0) { // No call was added or even worse we lost a call in the log. Trigger an // anomaly report. Note: it technically possible that an app modified the @@ -560,7 +577,7 @@ public final class CallLogManager extends CallsManagerListenerBase { // // We don't want to crash the whole process just because of that, so just log // it instead. - Log.e(TAG, e, "LogCall: Exception raised adding callId=%s", c.callId); + Log.e(TAG, e, "LogCall: Exception raised adding callId=%s", c.call.getId()); result[i] = null; mAnomalyReporterAdapter.reportAnomaly(LOG_CALL_FAILED_ANOMALY_ID, LOG_CALL_FAILED_ANOMALY_DESC); @@ -645,14 +662,17 @@ public final class CallLogManager extends CallsManagerListenerBase { * ID. There is a limit of 500 entries in the call log for a phone account, so once we hit 500 * we can reasonably expect that number to not change before and after logging a call. * We determine the maximum ID in the call log since this is a way we can objectively check if - * the provider did record a call log entry or not. Ideally there should me more call log + * the provider did record a call log entry or not. Ideally there should be more call log * entries after logging than before, and certainly not less. - * @param resolver content resolver * @return pair with number of rows in the call log and max id. */ - private Pair<Integer, Integer> getCallLogStats(@NonNull ContentResolver resolver) { + private Pair<Integer, Integer> getCallLogStats(@NonNull Call call) { try { - final UserManager userManager = mContext.getSystemService(UserManager.class); + // Ensure we query the call log based on the current user. + final Context currentUserContext = mContext.createContextAsUser( + call.getAssociatedUser(), /* flags= */ 0); + final ContentResolver currentUserResolver = currentUserContext.getContentResolver(); + final UserManager userManager = currentUserContext.getSystemService(UserManager.class); final int currentUserId = userManager.getProcessUserId(); // Use shadow provider based on current user unlock state. @@ -664,19 +684,16 @@ public final class CallLogManager extends CallsManagerListenerBase { } int maxCallId = -1; int numFound; - Cursor countCursor = resolver.query(providerUri, + try (Cursor countCursor = currentUserResolver.query(providerUri, new String[]{Calls._ID}, null, null, - Calls._ID + " DESC"); - try { + Calls._ID + " DESC")) { numFound = countCursor.getCount(); if (numFound > 0) { countCursor.moveToFirst(); maxCallId = countCursor.getInt(0); } - } finally { - countCursor.close(); } return new Pair<>(numFound, maxCallId); } catch (Exception e) { diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java index 98e67bba5..b04e9fa6b 100644..100755 --- a/src/com/android/server/telecom/CallsManager.java +++ b/src/com/android/server/telecom/CallsManager.java @@ -129,10 +129,11 @@ import com.android.server.telecom.callfiltering.CallScreeningServiceFilter; import com.android.server.telecom.callfiltering.DirectToVoicemailFilter; import com.android.server.telecom.callfiltering.DndCallFilter; import com.android.server.telecom.callfiltering.IncomingCallFilterGraph; +import com.android.server.telecom.callfiltering.IncomingCallFilterGraphProvider; import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.components.ErrorDialogActivity; import com.android.server.telecom.components.TelecomBroadcastReceiver; -import com.android.server.telecom.components.UserCallIntentProcessor; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.ui.AudioProcessingNotification; import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity; @@ -141,8 +142,8 @@ import com.android.server.telecom.ui.ConfirmCallDialogActivity; import com.android.server.telecom.ui.DisconnectedCallNotifier; import com.android.server.telecom.ui.IncomingCallNotifier; import com.android.server.telecom.ui.ToastFactory; -import com.android.server.telecom.voip.TransactionManager; import com.android.server.telecom.voip.VoipCallMonitor; +import com.android.server.telecom.voip.TransactionManager; import java.util.ArrayList; import java.util.Arrays; @@ -211,7 +212,7 @@ public class CallsManager extends Call.ListenerBase void onHoldToneRequested(Call call); void onExternalCallChanged(Call call, boolean isExternalCall); void onCallStreamingStateChanged(Call call, boolean isStreaming); - void onDisconnectedTonePlaying(boolean isTonePlaying); + void onDisconnectedTonePlaying(Call call, boolean isTonePlaying); void onConnectionTimeChanged(Call call); void onConferenceStateChanged(Call call, boolean isConference); void onCdmaConferenceSwap(Call call); @@ -287,15 +288,14 @@ public class CallsManager extends Call.ListenerBase public static final String EXCEPTION_RETRIEVING_PHONE_ACCOUNTS_EMERGENCY_ERROR_MSG = "Exception thrown while retrieving list of potential phone accounts when placing an " + "emergency call."; - public static final UUID EMERGENCY_CALL_DISCONNECTED_BEFORE_BEING_ADDED_ERROR_UUID = - UUID.fromString("f9a916c8-8d61-4550-9ad3-11c2e84f6364"); - public static final String EMERGENCY_CALL_DISCONNECTED_BEFORE_BEING_ADDED_ERROR_MSG = - "An emergency call was disconnected after the connection was created but before the " - + "call was successfully added to CallsManager."; public static final UUID EMERGENCY_CALL_ABORTED_NO_PHONE_ACCOUNTS_ERROR_UUID = UUID.fromString("2e994acb-1997-4345-8bf3-bad04303de26"); public static final String EMERGENCY_CALL_ABORTED_NO_PHONE_ACCOUNTS_ERROR_MSG = "An emergency call was aborted since there were no available phone accounts."; + public static final UUID TELEPHONY_HAS_DEFAULT_BUT_TELECOM_DOES_NOT_UUID = + UUID.fromString("0a86157c-50ca-11ee-be56-0242ac120002"); + public static final String TELEPHONY_HAS_DEFAULT_BUT_TELECOM_DOES_NOT_MSG = + "Telephony has a default MO acct but Telecom prompted user for MO"; private static final int[] OUTGOING_CALL_STATES = {CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING, @@ -464,6 +464,9 @@ public class CallsManager extends Call.ListenerBase private final TransactionManager mTransactionManager; private final UserManager mUserManager; private final CallStreamingNotification mCallStreamingNotification; + private final FeatureFlags mFeatureFlags; + + private final IncomingCallFilterGraphProvider mIncomingCallFilterGraphProvider; private final ConnectionServiceFocusManager.CallsManagerRequester mRequester = new ConnectionServiceFocusManager.CallsManagerRequester() { @@ -577,7 +580,10 @@ public class CallsManager extends Call.ListenerBase BlockedNumbersAdapter blockedNumbersAdapter, TransactionManager transactionManager, EmergencyCallDiagnosticLogger emergencyCallDiagnosticLogger, - CallStreamingNotification callStreamingNotification) { + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + CallStreamingNotification callStreamingNotification, + FeatureFlags featureFlags, + IncomingCallFilterGraphProvider incomingCallFilterGraphProvider) { mContext = context; mLock = lock; @@ -596,25 +602,32 @@ public class CallsManager extends Call.ListenerBase mEmergencyCallHelper = emergencyCallHelper; mCallerInfoLookupHelper = callerInfoLookupHelper; mEmergencyCallDiagnosticLogger = emergencyCallDiagnosticLogger; + mIncomingCallFilterGraphProvider = incomingCallFilterGraphProvider; mDtmfLocalTonePlayer = new DtmfLocalTonePlayer(new DtmfLocalTonePlayer.ToneGeneratorProxy()); - CallAudioRouteStateMachine callAudioRouteStateMachine = - callAudioRouteStateMachineFactory.create( - context, - this, - bluetoothManager, - wiredHeadsetManager, - statusBarNotifier, - audioServiceFactory, - CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT, - asyncCallAudioTaskExecutor - ); - callAudioRouteStateMachine.initialize(); + CallAudioRouteAdapter callAudioRouteAdapter; + if (!featureFlags.useRefactoredAudioRouteSwitching()) { + callAudioRouteAdapter = callAudioRouteStateMachineFactory.create( + context, + this, + bluetoothManager, + wiredHeadsetManager, + statusBarNotifier, + audioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT, + asyncCallAudioTaskExecutor, + communicationDeviceTracker, + featureFlags + ); + } else { + callAudioRouteAdapter = new CallAudioRouteController(); + } + callAudioRouteAdapter.initialize(); CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter = new CallAudioRoutePeripheralAdapter( - callAudioRouteStateMachine, + callAudioRouteAdapter, bluetoothManager, wiredHeadsetManager, mDockManager, @@ -642,14 +655,15 @@ public class CallsManager extends Call.ListenerBase ringtoneFactory, systemVibrator, new Ringer.VibrationEffectProxy(), mInCallController, mContext.getSystemService(NotificationManager.class), - accessibilityManagerAdapter); + accessibilityManagerAdapter, featureFlags); mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, audioManager, mTimeoutsAdapter, mLock); - mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine, + mCallAudioManager = new CallAudioManager(callAudioRouteAdapter, this, callAudioModeStateMachineFactory.create(systemStateHelper, - (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)), + (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), + featureFlags, communicationDeviceTracker), playerFactory, mRinger, new RingbackPlayer(playerFactory), - bluetoothStateReceiver, mDtmfLocalTonePlayer); + bluetoothStateReceiver, mDtmfLocalTonePlayer, featureFlags); mConnectionSvrFocusMgr = connectionServiceFocusManagerFactory.create(mRequester); mHeadsetMediaButton = headsetMediaButtonFactory.create(context, this, mLock); @@ -657,23 +671,29 @@ public class CallsManager extends Call.ListenerBase mProximitySensorManager = proximitySensorManagerFactory.create(context, this); mPhoneStateBroadcaster = new PhoneStateBroadcaster(this); mCallLogManager = new CallLogManager(context, phoneAccountRegistrar, mMissedCallNotifier, - mAnomalyReporter); + mAnomalyReporter, featureFlags); mConnectionServiceRepository = new ConnectionServiceRepository(mPhoneAccountRegistrar, mContext, mLock, this); mInCallWakeLockController = inCallWakeLockControllerFactory.create(context, this); mClockProxy = clockProxy; mToastFactory = toastFactory; mRoleManagerAdapter = roleManagerAdapter; + mVoipCallMonitor = new VoipCallMonitor(mContext, mLock); mTransactionManager = transactionManager; mBlockedNumbersAdapter = blockedNumbersAdapter; mCallStreamingController = new CallStreamingController(mContext, mLock); - mVoipCallMonitor = new VoipCallMonitor(mContext, mLock); mCallStreamingNotification = callStreamingNotification; + mFeatureFlags = featureFlags; + if (mFeatureFlags.useImprovedListenerOrder()) { + mListeners.add(mInCallController); + } mListeners.add(mInCallWakeLockController); mListeners.add(statusBarNotifier); mListeners.add(mCallLogManager); - mListeners.add(mInCallController); + if (!mFeatureFlags.useImprovedListenerOrder()) { + mListeners.add(mInCallController); + } mListeners.add(mCallEndpointController); mListeners.add(mCallDiagnosticServiceController); mListeners.add(mCallAudioManager); @@ -748,11 +768,14 @@ public class CallsManager extends Call.ListenerBase @Override @VisibleForTesting public void onSuccessfulOutgoingCall(Call call, int callState) { - Log.v(this, "onSuccessfulOutgoingCall, %s", call); + Log.v(this, "onSuccessfulOutgoingCall, call=[%s], state=[%d]", call, callState); call.setPostCallPackageName(getRoleManagerAdapter().getDefaultCallScreeningApp( call.getAssociatedUser())); - setCallState(call, callState, "successful outgoing call"); + if (!mFeatureFlags.fixAudioFlickerForOutgoingCalls()) { + setCallState(call, callState, "successful outgoing call"); + } + if (!mCalls.contains(call)) { // Call was not added previously in startOutgoingCall due to it being a potential MMI // code, so add it now. @@ -764,7 +787,18 @@ public class CallsManager extends Call.ListenerBase listener.onConnectionServiceChanged(call, null, call.getConnectionService()); } - markCallAsDialing(call); + if (mFeatureFlags.fixAudioFlickerForOutgoingCalls()) { + // Allow the ConnectionService to start the call in the active state. This case is + // helpful for conference calls or meetings that can skip the dialing stage. + if (callState == CallState.ACTIVE) { + setCallState(call, callState, "skipping the dialing state and setting active"); + } else { + markCallAsDialing(call); + } + } + else{ + markCallAsDialing(call); + } } @Override @@ -783,11 +817,12 @@ public class CallsManager extends Call.ListenerBase ? new Bundle() : phoneAccount.getExtras(); TelephonyManager telephonyManager = getTelephonyManager(); + boolean performDndFilter = mFeatureFlags.skipFilterPhoneAccountPerformDndFilter(); if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE) || incomingCall.hasProperty(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) || telephonyManager.isInEmergencySmsMode() || incomingCall.isSelfManaged() || - extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) { + (!performDndFilter && extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING))) { Log.i(this, "Skipping call filtering for %s (ecm=%b, " + "networkIdentifiedEmergencyCall = %b, emergencySmsMode = %b, " + "selfMgd=%b, skipExtra=%b)", @@ -805,12 +840,27 @@ public class CallsManager extends Call.ListenerBase .build(), false); incomingCall.setIsUsingCallFiltering(false); return; + } else if (performDndFilter && extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) { + IncomingCallFilterGraph graph = setupDndFilterOnlyGraph(incomingCall); + graph.performFiltering(); + return; } IncomingCallFilterGraph graph = setUpCallFilterGraph(incomingCall); graph.performFiltering(); } + private IncomingCallFilterGraph setupDndFilterOnlyGraph(Call incomingHfpCall) { + incomingHfpCall.setIsUsingCallFiltering(true); + DndCallFilter dndCallFilter = new DndCallFilter(incomingHfpCall, mRinger); + IncomingCallFilterGraph graph = mIncomingCallFilterGraphProvider.createGraph( + incomingHfpCall, + this::onCallFilteringComplete, mContext, mTimeoutsAdapter, mLock); + graph.addFilter(dndCallFilter); + mGraphHandlerThreads.add(graph.getHandlerThread()); + return graph; + } + private IncomingCallFilterGraph setUpCallFilterGraph(Call incomingCall) { incomingCall.setIsUsingCallFiltering(true); String carrierPackageName = getCarrierPackageName(); @@ -823,7 +873,7 @@ public class CallsManager extends Call.ListenerBase mContext.getPackageManager(), packageName); ParcelableCallUtils.Converter converter = new ParcelableCallUtils.Converter(); - IncomingCallFilterGraph graph = new IncomingCallFilterGraph(incomingCall, + IncomingCallFilterGraph graph = mIncomingCallFilterGraphProvider.createGraph(incomingCall, this::onCallFilteringComplete, mContext, mTimeoutsAdapter, mLock); DirectToVoicemailFilter voicemailFilter = new DirectToVoicemailFilter(incomingCall, mCallerInfoLookupHelper); @@ -990,7 +1040,7 @@ public class CallsManager extends Call.ListenerBase if (result.shouldShowNotification) { Log.i(this, "onCallScreeningCompleted: blocked call, showing notification."); mMissedCallNotifier.showMissedCallNotification( - new MissedCallNotifier.CallInfo(incomingCall)); + new MissedCallNotifier.CallInfo(incomingCall), /* uri= */ null); } } } @@ -1303,7 +1353,7 @@ public class CallsManager extends Call.ListenerBase return mCallAudioManager; } - InCallController getInCallController() { + public InCallController getInCallController() { return mInCallController; } @@ -1432,7 +1482,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, isConference, /* isConference */ mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); // Ensure new calls related to self-managed calls/connections are set as such. This will // be overridden when the actual connection is returned in startCreateConnection, however // doing this now ensures the logs and any other logic will treat this call as self-managed @@ -1459,7 +1510,10 @@ public class CallsManager extends Call.ListenerBase } } // Incoming address was set via EXTRA_INCOMING_CALL_ADDRESS above. - call.setAssociatedUser(phoneAccountHandle.getUserHandle()); + UserHandle associatedUser = UserUtil.getAssociatedUserForCall( + mFeatureFlags.associatedUserRefactorForWorkProfile(), + getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccountHandle); + call.setAssociatedUser(associatedUser); } if (phoneAccount != null) { @@ -1579,15 +1633,19 @@ public class CallsManager extends Call.ListenerBase // Check if the target phone account is possibly in ECBM. call.setIsInECBM(getEmergencyCallHelper() .isLastOutgoingEmergencyCallPAH(call.getTargetPhoneAccount())); - // If the phone account user profile is paused or the call isn't visible to the secondary/ - // guest user, reject the non-emergency incoming call. When the current user is the admin, - // we need to allow the calls to go through if the work profile isn't paused. We should - // always allow emergency calls and also allow non-emergency calls when ECBM is active for - // the phone account. - if ((mUserManager.isQuietModeEnabled(call.getAssociatedUser()) - || (!mUserManager.isUserAdmin(mCurrentUserHandle.getIdentifier()) - && !isCallVisibleForUser(call, mCurrentUserHandle))) - && !call.isEmergencyCall() && !call.isInECBM()) { + + // Check if call is visible to the current user. + boolean isCallHiddenFromProfile = !isCallVisibleForUser(call, mCurrentUserHandle); + // For admins, we should check if the work profile is paused in order to reject + // the call. + if (mUserManager.isUserAdmin(mCurrentUserHandle.getIdentifier())) { + isCallHiddenFromProfile &= mUserManager.isQuietModeEnabled( + call.getAssociatedUser()); + } + + // We should always allow emergency calls and also allow non-emergency calls when ECBM + // is active for the phone account. + if (isCallHiddenFromProfile && !call.isEmergencyCall() && !call.isInECBM()) { Log.d(TAG, "Rejecting non-emergency call because the owner %s is not running.", phoneAccountHandle.getUserHandle()); call.setMissedReason(USER_MISSED_NOT_RUNNING); @@ -1660,11 +1718,15 @@ public class CallsManager extends Call.ListenerBase true /* forceAttachToExistingConnection */, false, /* isConference */ mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); call.initAnalytics(); // For unknown calls, base the associated user off of the target phone account handle. - call.setAssociatedUser(phoneAccountHandle.getUserHandle()); + UserHandle associatedUser = UserUtil.getAssociatedUserForCall( + mFeatureFlags.associatedUserRefactorForWorkProfile(), + getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccountHandle); + call.setAssociatedUser(associatedUser); setIntentExtrasAndStartTime(call, extras); call.addListener(this); notifyStartCreateConnection(call); @@ -1778,7 +1840,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, isConference, /* isConference */ mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); if (extras.containsKey(TelecomManager.TRANSACTION_CALL_ID_KEY)) { call.setIsTransactionalCall(true); @@ -2054,7 +2117,7 @@ public class CallsManager extends Call.ListenerBase + " available accounts."); showErrorMessage(R.string.cant_call_due_to_no_supported_service); mListeners.forEach(l -> l.onCreateConnectionFailed(callToPlace)); - if (callToPlace.isEmergencyCall()){ + if (callToPlace.isEmergencyCall()) { mAnomalyReporter.reportAnomaly( EMERGENCY_CALL_ABORTED_NO_PHONE_ACCOUNTS_ERROR_UUID, EMERGENCY_CALL_ABORTED_NO_PHONE_ACCOUNTS_ERROR_MSG); @@ -2067,6 +2130,21 @@ public class CallsManager extends Call.ListenerBase return CompletableFuture.completedFuture(Pair.create(callToPlace, accountSuggestions.get(0).getPhoneAccountHandle())); } + + // At this point Telecom is requesting the user to select a phone + // account. However, Telephony is reporting that the user has a default + // outgoing account (which is denoted by a non-negative subId number). + // At some point, Telecom and Telephony are out of sync with the default + // outgoing calling account. + if(mFeatureFlags.telephonyHasDefaultButTelecomDoesNot()) { + if (SubscriptionManager.getDefaultVoiceSubscriptionId() != + SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mAnomalyReporter.reportAnomaly( + TELEPHONY_HAS_DEFAULT_BUT_TELECOM_DOES_NOT_UUID, + TELEPHONY_HAS_DEFAULT_BUT_TELECOM_DOES_NOT_MSG); + } + } + // This is the state where the user is expected to select an account callToPlace.setState(CallState.SELECT_PHONE_ACCOUNT, "needs account selection"); @@ -2895,9 +2973,15 @@ public class CallsManager extends Call.ListenerBase // from the client via a transaction before answering. call.answer(videoState); } else { + if (!mFeatureFlags.genAnomReportOnFocusTimeout()) { + Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall(); + Log.d(this, "answerCall: Incoming call = %s Ongoing call %s", call, activeCall); + } // Hold or disconnect the active call and request call focus for the incoming call. - Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall(); - Log.d(this, "answerCall: Incoming call = %s Ongoing call %s", call, activeCall); + Bundle bundle = new Bundle(); + bundle.putLong(TelecomManager.EXTRA_CALL_ANSWERED_TIME_MILLIS, + mClockProxy.currentTimeMillis()); + call.putConnectionServiceExtras(bundle); holdActiveCallForNewCall(call); mConnectionSvrFocusMgr.requestFocus( call, @@ -3528,14 +3612,15 @@ public class CallsManager extends Call.ListenerBase * Called when disconnect tone is started or stopped, including any InCallTone * after disconnected call. * + * @param call * @param isTonePlaying true if the disconnected tone is started, otherwise the disconnected - * tone is stopped. + * tone is stopped. */ @VisibleForTesting - public void onDisconnectedTonePlaying(boolean isTonePlaying) { + public void onDisconnectedTonePlaying(Call call, boolean isTonePlaying) { Log.v(this, "onDisconnectedTonePlaying, %s", isTonePlaying ? "started" : "stopped"); for (CallsManagerListener listener : mListeners) { - listener.onDisconnectedTonePlaying(isTonePlaying); + listener.onDisconnectedTonePlaying(call, isTonePlaying); } } @@ -3730,11 +3815,6 @@ public class CallsManager extends Call.ListenerBase // Notify listeners that the call was disconnected before being added to CallsManager. // Listeners will not receive onAdded or onRemoved callbacks. if (!mCalls.contains(call)) { - if (call.isEmergencyCall()) { - mAnomalyReporter.reportAnomaly( - EMERGENCY_CALL_DISCONNECTED_BEFORE_BEING_ADDED_ERROR_UUID, - EMERGENCY_CALL_DISCONNECTED_BEFORE_BEING_ADDED_ERROR_MSG); - } mListeners.forEach(l -> l.onCreateConnectionFailed(call)); } @@ -4169,7 +4249,8 @@ public class CallsManager extends Call.ListenerBase connectTime, connectElapsedTime, mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); // Unlike connections, conferences are not created first and then notified as create // connection complete from the CS. They originate from the CS and are reported directly to @@ -4187,7 +4268,10 @@ public class CallsManager extends Call.ListenerBase call.setStatusHints(parcelableConference.getStatusHints()); call.putConnectionServiceExtras(parcelableConference.getExtras()); // For conference calls, set the associated user from the target phone account user handle. - call.setAssociatedUser(phoneAccount.getUserHandle()); + UserHandle associatedUser = UserUtil.getAssociatedUserForCall( + mFeatureFlags.associatedUserRefactorForWorkProfile(), getPhoneAccountRegistrar(), + getCurrentUserHandle(), phoneAccount); + call.setAssociatedUser(associatedUser); // In case this Conference was added via a ConnectionManager, keep track of the original // Connection ID as created by the originating ConnectionService. Bundle extras = parcelableConference.getExtras(); @@ -5225,7 +5309,8 @@ public class CallsManager extends Call.ListenerBase connection.getConnectTimeMillis() /* connectTimeMillis */, connection.getConnectElapsedTimeMillis(), /* connectElapsedTimeMillis */ mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); call.initAnalytics(); call.getAnalytics().setCreatedFromExistingConnection(true); @@ -5240,7 +5325,10 @@ public class CallsManager extends Call.ListenerBase connection.getCallerDisplayNamePresentation()); // For existing connections, use the phone account user handle to determine the user // association with the call. - call.setAssociatedUser(connection.getPhoneAccount().getUserHandle()); + UserHandle associatedUser = UserUtil.getAssociatedUserForCall( + mFeatureFlags.associatedUserRefactorForWorkProfile(), getPhoneAccountRegistrar(), + getCurrentUserHandle(), connection.getPhoneAccount()); + call.setAssociatedUser(associatedUser); call.addListener(this); call.putConnectionServiceExtras(connection.getExtras()); @@ -5465,7 +5553,7 @@ public class CallsManager extends Call.ListenerBase mCallAudioManager.getCallAudioModeStateMachine().getHandler().post(() -> { mainHandlerLatch.countDown(); }); - mCallAudioManager.getCallAudioRouteStateMachine().getHandler().post(() -> { + mCallAudioManager.getCallAudioRouteAdapter().getAdapterHandler().post(() -> { mainHandlerLatch.countDown(); }); @@ -5491,9 +5579,10 @@ public class CallsManager extends Call.ListenerBase // We are going to place the new outgoing call, so disconnect any ongoing self-managed // calls which are ongoing at this time. disconnectSelfManagedCalls("outgoing call " + callId); - - mPendingCallConfirm.complete(mPendingCall); - mPendingCallConfirm = null; + if (mPendingCallConfirm != null) { + mPendingCallConfirm.complete(mPendingCall); + mPendingCallConfirm = null; + } mPendingCall = null; } } @@ -5512,8 +5601,10 @@ public class CallsManager extends Call.ListenerBase markCallAsDisconnected(mPendingCall, new DisconnectCause(DisconnectCause.CANCELED)); markCallAsRemoved(mPendingCall); mPendingCall = null; - mPendingCallConfirm.complete(null); - mPendingCallConfirm = null; + if (mPendingCallConfirm != null) { + mPendingCallConfirm.complete(null); + mPendingCallConfirm = null; + } } } @@ -5753,7 +5844,8 @@ public class CallsManager extends Call.ListenerBase return; } ConnectionServiceWrapper service = mConnectionServiceRepository.getService( - phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle()); + phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle(), + mFeatureFlags); if (service == null) { Log.i(this, "Found no connection service."); return; @@ -5778,7 +5870,8 @@ public class CallsManager extends Call.ListenerBase return; } ConnectionServiceWrapper service = mConnectionServiceRepository.getService( - phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle()); + phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle(), + mFeatureFlags); if (service == null) { Log.i(this, "Found no connection service."); return; @@ -5882,7 +5975,7 @@ public class CallsManager extends Call.ListenerBase handoverFromCall.getHandle(), null, null, null, Call.CALL_DIRECTION_OUTGOING, false, - false, mClockProxy, mToastFactory); + false, mClockProxy, mToastFactory, mFeatureFlags); call.initAnalytics(); // Set self-managed and voipAudioMode if destination is self-managed CS @@ -6089,7 +6182,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, false, /* isConference */ mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); if (fromCall == null || isHandoverInProgress() || !isHandoverFromPhoneAccountSupported(fromCall.getTargetPhoneAccount()) || diff --git a/src/com/android/server/telecom/CallsManagerListenerBase.java b/src/com/android/server/telecom/CallsManagerListenerBase.java index 43f3b906c..0c54be308 100644 --- a/src/com/android/server/telecom/CallsManagerListenerBase.java +++ b/src/com/android/server/telecom/CallsManagerListenerBase.java @@ -16,10 +16,10 @@ package com.android.server.telecom; -import android.telecom.AudioState; import android.telecom.CallAudioState; import android.telecom.CallEndpoint; import android.telecom.VideoProfile; + import java.util.Set; /** @@ -112,7 +112,7 @@ public abstract class CallsManagerListenerBase implements CallsManager.CallsMana } @Override - public void onDisconnectedTonePlaying(boolean isTonePlaying) { + public void onDisconnectedTonePlaying(Call call, boolean isTonePlaying) { } @Override diff --git a/src/com/android/server/telecom/ConnectionServiceFocusManager.java b/src/com/android/server/telecom/ConnectionServiceFocusManager.java index 3694727a2..35be0f898 100644 --- a/src/com/android/server/telecom/ConnectionServiceFocusManager.java +++ b/src/com/android/server/telecom/ConnectionServiceFocusManager.java @@ -26,8 +26,11 @@ import android.telecom.Log; import android.telecom.Logging.Session; import android.text.TextUtils; import android.util.LocalLog; +import android.util.LogPrinter; +import android.util.Printer; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.telecom.flags.Flags; import com.android.internal.util.IndentingPrintWriter; import java.util.ArrayList; @@ -35,6 +38,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -44,6 +48,11 @@ public class ConnectionServiceFocusManager { private static final String TAG = "ConnectionSvrFocusMgr"; private static final int GET_CURRENT_FOCUS_TIMEOUT_MILLIS = 1000; private final LocalLog mLocalLog = new LocalLog(20); + private final AnomalyReporterAdapter mAnomalyReporter = new AnomalyReporterAdapterImpl(); + public static final UUID WATCHDOG_GET_CALL_FOCUS_TIMEOUT_UUID = + UUID.fromString("edd7334a-ef87-432b-a1d0-a2f23959c73e"); + public static final String WATCHDOG_GET_CALL_FOCUS_TIMEOUT_MSG = + "Telecom CallAnomalyWatchdog detected a timeout while getting the call focus."; /** Factory interface used to create the {@link ConnectionServiceFocusManager} instance. */ public interface ConnectionServiceFocusManagerFactory { @@ -332,8 +341,23 @@ public class ConnectionServiceFocusManager { if (syncCallFocus != null) { return syncCallFocus.orElse(null); } else { - Log.w(TAG, "Timed out waiting for synchronous current focus. Returning possibly" - + " inaccurate result"); + if (Flags.genAnomReportOnFocusTimeout()) { + Log.w(TAG, "Timed out waiting for synchronous current focus. Returning possibly" + + " inaccurate result. returning currentFocusCall=[%s]", + mCurrentFocusCall); + + // dump the state of the handler to better understand the timeout + mEventHandler.dump( + new LogPrinter(android.util.Log.INFO, TAG), "CsFocusMgr_timeout"); + + // report the timeout + mAnomalyReporter.reportAnomaly( + WATCHDOG_GET_CALL_FOCUS_TIMEOUT_UUID, + WATCHDOG_GET_CALL_FOCUS_TIMEOUT_MSG); + } else { + Log.w(TAG, "Timed out waiting for synchronous current focus. Returning possibly" + + " inaccurate result"); + } return mCurrentFocusCall; } } catch (InterruptedException e) { diff --git a/src/com/android/server/telecom/ConnectionServiceRepository.java b/src/com/android/server/telecom/ConnectionServiceRepository.java index 3991ed51f..d6a78d0a8 100644 --- a/src/com/android/server/telecom/ConnectionServiceRepository.java +++ b/src/com/android/server/telecom/ConnectionServiceRepository.java @@ -23,6 +23,7 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.telecom.flags.FeatureFlags; import java.util.HashMap; @@ -61,7 +62,10 @@ public class ConnectionServiceRepository { } @VisibleForTesting - public ConnectionServiceWrapper getService(ComponentName componentName, UserHandle userHandle) { + public ConnectionServiceWrapper getService( + ComponentName componentName, + UserHandle userHandle, + FeatureFlags featureFlags) { Pair<ComponentName, UserHandle> cacheKey = Pair.create(componentName, userHandle); ConnectionServiceWrapper service = mServiceCache.get(cacheKey); if (service == null) { @@ -72,7 +76,8 @@ public class ConnectionServiceRepository { mCallsManager, mContext, mLock, - userHandle); + userHandle, + featureFlags); service.addListener(mUnbindListener); mServiceCache.put(cacheKey, service); } diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java index 728e121f5..593673061 100644 --- a/src/com/android/server/telecom/ConnectionServiceWrapper.java +++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java @@ -23,17 +23,16 @@ import android.app.AppOpsManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; +import android.graphics.drawable.Icon; import android.location.Location; import android.location.LocationManager; import android.location.LocationRequest; -import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.CancellationSignal; import android.os.IBinder; import android.os.ParcelFileDescriptor; -import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; @@ -65,19 +64,23 @@ import com.android.internal.telecom.IConnectionServiceAdapter; import com.android.internal.telecom.IVideoProvider; import com.android.internal.telecom.RemoteServiceCallback; import com.android.internal.util.Preconditions; +import com.android.server.telecom.flags.FeatureFlags; +import com.android.server.telecom.flags.Flags; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.Objects; /** * Wrapper for {@link IConnectionService}s, handles binding to {@link IConnectionService} and keeps @@ -90,9 +93,12 @@ public class ConnectionServiceWrapper extends ServiceBinder implements ConnectionServiceFocusManager.ConnectionServiceFocus { private static final String TELECOM_ABBREVIATION = "cast"; + private static final long SERVICE_BINDING_TIMEOUT = 15000L; private CompletableFuture<Pair<Integer, Location>> mQueryLocationFuture = null; private @Nullable CancellationSignal mOngoingQueryLocationRequest = null; private final ExecutorService mQueryLocationExecutor = Executors.newSingleThreadExecutor(); + private ScheduledExecutorService mScheduledExecutor = + Executors.newSingleThreadScheduledExecutor(); private final class Adapter extends IConnectionServiceAdapter.Stub { @@ -516,8 +522,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements // Check status hints image for cross user access if (parcelableConference.getStatusHints() != null) { Icon icon = parcelableConference.getStatusHints().getIcon(); - parcelableConference.getStatusHints().setIcon(StatusHints. - validateAccountIconUserBoundary(icon, callingUserHandle)); + parcelableConference.getStatusHints().setIcon(StatusHints + .validateAccountIconUserBoundary(icon, callingUserHandle)); } if (parcelableConference.getConnectElapsedTimeMillis() != 0 @@ -992,6 +998,12 @@ public class ConnectionServiceWrapper extends ServiceBinder implements connectIdToCheck = callId; } + // Check status hints image for cross user access + if (connection.getStatusHints() != null) { + Icon icon = connection.getStatusHints().getIcon(); + connection.getStatusHints().setIcon(StatusHints. + validateAccountIconUserBoundary(icon, userHandle)); + } // Handle the case where an existing connection was added by Telephony via // a connection manager. The remote connection service API does not include // the ability to specify a parent connection when adding an existing @@ -1030,14 +1042,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements connection.getCallDirection(), connection.getCallerNumberVerificationStatus()); } - - // Check status hints image for cross user access - if (connection.getStatusHints() != null) { - Icon icon = connection.getStatusHints().getIcon(); - connection.getStatusHints().setIcon(StatusHints. - validateAccountIconUserBoundary(icon, userHandle)); - } - // Check to see if this Connection has already been added. Call alreadyAddedConnection = mCallsManager .getAlreadyAddedConnection(connectIdToCheck); @@ -1350,6 +1354,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements private final CallsManager mCallsManager; private final AppOpsManager mAppOpsManager; private final Context mContext; + private final FeatureFlags mFlags; private ConnectionServiceFocusManager.ConnectionServiceFocusListener mConnSvrFocusListener; @@ -1371,8 +1376,10 @@ public class ConnectionServiceWrapper extends ServiceBinder implements CallsManager callsManager, Context context, TelecomSystem.SyncRoot lock, - UserHandle userHandle) { - super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle); + UserHandle userHandle, + FeatureFlags featureFlags) { + super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle, + featureFlags); mConnectionServiceRepository = connectionServiceRepository; phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() { // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections @@ -1382,6 +1389,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements mCallsManager = callsManager; mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mContext = context; + mFlags = featureFlags; } /** See {@link IConnectionService#addConnectionServiceAdapter}. */ @@ -1595,7 +1603,22 @@ public class ConnectionServiceWrapper extends ServiceBinder implements .setParticipants(call.getParticipants()) .setIsAdhocConferenceCall(call.isAdhocConferenceCall()) .build(); - + if (Flags.unbindTimeoutConnections()) { + android.telecom.Logging.Runnable r = + new android.telecom.Logging.Runnable("CSW.cC", mLock) { + @Override + public void loggedRun() { + if (!call.isCreateConnectionComplete()) { + Log.e(this, new Exception(), "Conference %s creation timeout", + getComponentName()); + response.handleCreateConferenceFailure( + new DisconnectCause(DisconnectCause.ERROR)); + } + } + }; + mScheduledExecutor.schedule(r.getRunnableToCancel(), SERVICE_BINDING_TIMEOUT, + TimeUnit.MILLISECONDS); + } try { mServiceInterface.createConference( call.getConnectionManagerPhoneAccount(), @@ -1604,7 +1627,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements call.shouldAttachToExistingConnection(), call.isUnknown(), Log.getExternalSession(TELECOM_ABBREVIATION)); - } catch (RemoteException e) { Log.e(this, e, "Failure to createConference -- %s", getComponentName()); mPendingResponses.remove(callId).handleCreateConferenceFailure( @@ -1637,6 +1659,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements Log.i(ConnectionServiceWrapper.this, "Call not present" + " in call id mapper, maybe it was aborted before the bind" + " completed successfully?"); + response.handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.CANCELED)); return; @@ -1698,6 +1721,23 @@ public class ConnectionServiceWrapper extends ServiceBinder implements .setRttPipeToInCall(call.getCsToInCallRttPipeForCs()) .build(); + if (Flags.unbindTimeoutConnections()) { + android.telecom.Logging.Runnable r = + new android.telecom.Logging.Runnable("CSW.cC", mLock) { + @Override + public void loggedRun() { + if (!call.isCreateConnectionComplete()) { + Log.e(this, new Exception(), + "Connection %s creation timeout", + getComponentName()); + response.handleCreateConnectionFailure( + new DisconnectCause(DisconnectCause.ERROR)); + } + } + }; + mScheduledExecutor.schedule(r.getRunnableToCancel(), SERVICE_BINDING_TIMEOUT, + TimeUnit.MILLISECONDS); + } try { mServiceInterface.createConnection( call.getConnectionManagerPhoneAccount(), @@ -1706,7 +1746,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements call.shouldAttachToExistingConnection(), call.isUnknown(), Log.getExternalSession(TELECOM_ABBREVIATION)); - } catch (RemoteException e) { Log.e(this, e, "Failure to createConnection -- %s", getComponentName()); mPendingResponses.remove(callId).handleCreateConnectionFailure( @@ -2155,7 +2194,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements } } - void addCall(Call call) { + @VisibleForTesting + public void addCall(Call call) { if (mCallIdMapper.getCallId(call) == null) { mCallIdMapper.addCall(call); } @@ -2490,12 +2530,11 @@ public class ConnectionServiceWrapper extends ServiceBinder implements */ private void handleConnectionServiceDeath() { if (!mPendingResponses.isEmpty()) { - CreateConnectionResponse[] responses = mPendingResponses.values().toArray( - new CreateConnectionResponse[mPendingResponses.values().size()]); + Collection<CreateConnectionResponse> responses = mPendingResponses.values(); mPendingResponses.clear(); - for (int i = 0; i < responses.length; i++) { - responses[i].handleCreateConnectionFailure( - new DisconnectCause(DisconnectCause.ERROR, "CS_DEATH")); + for (CreateConnectionResponse response : responses) { + response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR, + "CS_DEATH")); } } mCallIdMapper.clear(); @@ -2539,7 +2578,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements isCallerConnectionManager = true; } ConnectionServiceWrapper service = mConnectionServiceRepository.getService( - handle.getComponentName(), handle.getUserHandle()); + handle.getComponentName(), handle.getUserHandle(), mFlags); if (service != null && service != this) { simServices.add(service); } else { @@ -2624,4 +2663,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements sb.append("]"); return sb.toString(); } + + @VisibleForTesting + public void setScheduledExecutorService(ScheduledExecutorService service) { + mScheduledExecutor = service; + } } diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java index 19691c1a2..f5b257daf 100644 --- a/src/com/android/server/telecom/CreateConnectionProcessor.java +++ b/src/com/android/server/telecom/CreateConnectionProcessor.java @@ -32,6 +32,8 @@ import android.telephony.TelephonyManager; // TODO: Needed for move to system service: import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.telecom.flags.Flags; +import com.android.server.telecom.flags.FeatureFlags; import java.util.ArrayList; import java.util.Collection; @@ -125,6 +127,7 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { private DisconnectCause mLastErrorDisconnectCause; private final PhoneAccountRegistrar mPhoneAccountRegistrar; private final Context mContext; + private final FeatureFlags mFlags; private CreateConnectionTimeout mTimeout; private ConnectionServiceWrapper mService; private int mConnectionAttempt; @@ -132,7 +135,8 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { @VisibleForTesting public CreateConnectionProcessor( Call call, ConnectionServiceRepository repository, CreateConnectionResponse response, - PhoneAccountRegistrar phoneAccountRegistrar, Context context) { + PhoneAccountRegistrar phoneAccountRegistrar, Context context, + FeatureFlags featureFlags) { Log.v(this, "CreateConnectionProcessor created for Call = %s", call); mCall = call; mRepository = repository; @@ -140,6 +144,7 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { mPhoneAccountRegistrar = phoneAccountRegistrar; mContext = context; mConnectionAttempt = 0; + mFlags = featureFlags; } boolean isProcessingComplete() { @@ -239,7 +244,7 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { Log.i(this, "Trying attempt %s", attempt); PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount; mService = mRepository.getService(phoneAccount.getComponentName(), - phoneAccount.getUserHandle()); + phoneAccount.getUserHandle(), mFlags); if (mService == null) { Log.i(this, "Found no connection service for attempt %s", attempt); attemptNextPhoneAccount(); @@ -247,7 +252,25 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { mConnectionAttempt++; mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount); mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); - mCall.setConnectionService(mService); + if (mFlags.updatedRcsCallCountTracking()) { + if (Objects.equals(attempt.connectionManagerPhoneAccount, + attempt.targetPhoneAccount)) { + mCall.setConnectionService(mService); + } else { + PhoneAccountHandle remotePhoneAccount = attempt.targetPhoneAccount; + ConnectionServiceWrapper mRemoteService = + mRepository.getService(remotePhoneAccount.getComponentName(), + remotePhoneAccount.getUserHandle(), mFlags); + if (mRemoteService == null) { + mCall.setConnectionService(mService); + } else { + Log.v(this, "attemptNextPhoneAccount Setting RCS = %s", mRemoteService); + mCall.setConnectionService(mService, mRemoteService); + } + } + } else { + mCall.setConnectionService(mService); + } setTimeoutIfNeeded(mService, attempt); if (mCall.isIncoming()) { if (mCall.isAdhocConferenceCall()) { diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java index 598664e0f..ad3d26a66 100644 --- a/src/com/android/server/telecom/InCallController.java +++ b/src/com/android/server/telecom/InCallController.java @@ -22,7 +22,9 @@ import static android.os.Process.myUid; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityManager; import android.app.AppOpsManager; +import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationManager; import android.content.AttributionSource; @@ -47,7 +49,6 @@ import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; -import android.permission.PermissionManager; import android.telecom.CallAudioState; import android.telecom.CallEndpoint; import android.telecom.ConnectionService; @@ -66,6 +67,7 @@ import com.android.internal.telecom.IInCallService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.SystemStateHelper.SystemStateListener; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.ui.NotificationChannelManager; import java.util.ArrayList; @@ -80,6 +82,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it @@ -1237,11 +1240,12 @@ public class InCallController extends CallsManagerListenerBase implements private ArraySet<String> mAllCarrierPrivilegedApps = new ArraySet<>(); private ArraySet<String> mActiveCarrierPrivilegedApps = new ArraySet<>(); + private FeatureFlags mFeatureFlags; public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager, SystemStateHelper systemStateHelper, DefaultDialerCache defaultDialerCache, Timeouts.Adapter timeoutsAdapter, EmergencyCallHelper emergencyCallHelper, - CarModeTracker carModeTracker, ClockProxy clockProxy) { + CarModeTracker carModeTracker, ClockProxy clockProxy, FeatureFlags featureFlags) { mContext = context; mAppOpsManager = context.getSystemService(AppOpsManager.class); mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); @@ -1258,6 +1262,7 @@ public class InCallController extends CallsManagerListenerBase implements IntentFilter userAddedFilter = new IntentFilter(Intent.ACTION_USER_ADDED); userAddedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mUserAddedReceiver, userAddedFilter); + mFeatureFlags = featureFlags; } private void restrictPhoneCallOps() { @@ -1402,17 +1407,31 @@ public class InCallController extends CallsManagerListenerBase implements @Override public void onCallRemoved(Call call) { Log.i(this, "onCallRemoved: %s", call); - if (mCallsManager.getCalls().isEmpty()) { + // Instead of checking if there are no active calls, we should check if there any calls with + // the same associated user returned from getUserFromCall. For instance, it's possible to + // have calls coexist on the personal profile and work profile, in which case, we would only + // remove the ICS connection for the user associated with the call to be disconnected. + UserHandle userFromCall = getUserFromCall(call); + Stream<Call> callsAssociatedWithUserFromCall = mCallsManager.getCalls().stream() + .filter((c) -> getUserFromCall(c).equals(userFromCall)); + boolean isCallCountZero = mFeatureFlags.associatedUserRefactorForWorkProfile() + ? callsAssociatedWithUserFromCall.count() == 0 + : mCallsManager.getCalls().isEmpty(); + if (isCallCountZero) { /** Let's add a 2 second delay before we send unbind to the services to hopefully * give them enough time to process all the pending messages. */ mHandler.postDelayed(new Runnable("ICC.oCR", mLock) { @Override public void loggedRun() { - // Check again to make sure there are no active calls. - if (mCallsManager.getCalls().isEmpty()) { - unbindFromServices(getUserFromCall(call)); - + // Check again to make sure there are no active calls for the associated user. + Stream<Call> callsAssociatedWithUserFromCall = mCallsManager.getCalls().stream() + .filter((c) -> getUserFromCall(c).equals(userFromCall)); + boolean isCallCountZero = mFeatureFlags.associatedUserRefactorForWorkProfile() + ? callsAssociatedWithUserFromCall.count() == 0 + : mCallsManager.getCalls().isEmpty(); + if (isCallCountZero) { + unbindFromServices(userFromCall); mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission(); } } @@ -1690,6 +1709,29 @@ public class InCallController extends CallsManagerListenerBase implements @VisibleForTesting public void bringToForeground(boolean showDialpad, UserHandle callingUser) { + KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class); + boolean isLockscreenRestricted = keyguardManager != null + && keyguardManager.isKeyguardLocked(); + UserHandle currentUser = mCallsManager.getCurrentUserHandle(); + // Handle cases when calls are placed from the keyguard UI screen, which operates under + // the admin user. This needs to account for emergency calls placed from secondary/guest + // users as well as the work profile. Once the screen is locked, the user should be able to + // return to the call (from the keyguard UI). + if (mFeatureFlags.eccKeyguard() && mCallsManager.isInEmergencyCall() + && isLockscreenRestricted && !mInCallServices.containsKey(callingUser)) { + // If screen is locked and the current user is the system, query calls for the work + // profile user, if available. Otherwise, the user is in the secondary/guest profile, + // so we can default to the system user. + if (currentUser.isSystem()) { + UserManager um = mContext.getSystemService(UserManager.class); + UserHandle workProfileUser = findChildManagedProfileUser(currentUser, um); + boolean hasWorkCalls = mCallsManager.getCalls().stream() + .filter((c) -> getUserFromCall(c).equals(workProfileUser)).count() > 0; + callingUser = hasWorkCalls ? workProfileUser : currentUser; + } else { + callingUser = currentUser; + } + } if (mInCallServices.containsKey(callingUser)) { for (IInCallService inCallService : mInCallServices.get(callingUser).values()) { try { @@ -1805,6 +1847,7 @@ public class InCallController extends CallsManagerListenerBase implements * Unbinds an existing bound connection to the in-call app. */ public void unbindFromServices(UserHandle userHandle) { + Log.i(this, "Unbinding from services for user %s", userHandle); try { mContext.unregisterReceiver(mPackageChangedReceiver); } catch (IllegalArgumentException e) { @@ -2293,7 +2336,9 @@ public class InCallController extends CallsManagerListenerBase implements } // Upon successful connection, send the state of the world to the service. - List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls()); + List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls().stream().filter( + call -> getUserFromCall(call).equals(userHandle)) + .collect(Collectors.toUnmodifiableList())); Log.i(this, "Adding %s calls to InCallService after onConnected: %s, including external " + "calls", calls.size(), info.getComponentName()); int numCallsSent = 0; @@ -2430,10 +2475,15 @@ public class InCallController extends CallsManagerListenerBase implements try { inCallService.updateCall( sanitizeParcelableCallForService(info, parcelableCall)); - } catch (RemoteException ignored) { + } catch (RemoteException exception) { + Log.w(this, "Call status update did not send to: " + + componentName +" successfully with error " + exception); } } Log.i(this, "Components updated: %s", componentsUpdated); + } else { + Log.i(this, + "Unable to update call. InCallService not found for user: %s", userFromCall); } } @@ -2872,8 +2922,11 @@ public class InCallController extends CallsManagerListenerBase implements } else { UserHandle userFromCall = call.getAssociatedUser(); UserManager userManager = mContext.getSystemService(UserManager.class); - // Emergency call should never be blocked, so if the user associated with call is in - // quite mode, use the primary user for the emergency call. + // Emergency call should never be blocked, so if the user associated with the target + // phone account handle user is in quiet mode, use the current user for the ecall. + // Note, that this only applies to incoming calls that are received on assigned + // sims (i.e. work sim), where the associated user would be the target phone account + // handle user. if ((call.isEmergencyCall() || call.isInECBM()) && (userManager.isQuietModeEnabled(userFromCall) // We should also account for secondary/guest users where the profile may not @@ -2885,4 +2938,25 @@ public class InCallController extends CallsManagerListenerBase implements return userFromCall; } } + + /** + * Useful for debugging purposes and called on the command line via + * an "adb shell telecom command". + * + * @return true if a particular non-ui InCallService package is bound in a call. + */ + public boolean isNonUiInCallServiceBound(String packageName) { + for (NonUIInCallServiceConnectionCollection ics : mNonUIInCallServiceConnections.values()) { + for (InCallServiceBindingConnection connection : ics.getSubConnections()) { + InCallServiceInfo serviceInfo = connection.mInCallServiceInfo; + Log.i(this, "isNonUiInCallServiceBound: found serviceInfo=[%s]", serviceInfo); + if (serviceInfo != null && + serviceInfo.mComponentName.getPackageName().contains(packageName)) { + Log.i(this, "isNonUiInCallServiceBound: found target package"); + return true; + } + } + } + return false; + } } diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java index 3cc4aacc6..a5942f02e 100644 --- a/src/com/android/server/telecom/InCallTonePlayer.java +++ b/src/com/android/server/telecom/InCallTonePlayer.java @@ -69,8 +69,8 @@ public class InCallTonePlayer extends Thread { mCallAudioManager = callAudioManager; } - public InCallTonePlayer createPlayer(int tone) { - return new InCallTonePlayer(tone, mCallAudioManager, + public InCallTonePlayer createPlayer(Call call, int tone) { + return new InCallTonePlayer(call, tone, mCallAudioManager, mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory, mMediaPlayerFactory, mAudioManagerAdapter); } @@ -212,6 +212,7 @@ public class InCallTonePlayer extends Thread { private Session mSession; private final Object mSessionLock = new Object(); + private final Call mCall; private final ToneGeneratorFactory mToneGenerator; private final MediaPlayerFactory mMediaPlayerFactory; private final AudioManagerAdapter mAudioManagerAdapter; @@ -228,6 +229,7 @@ public class InCallTonePlayer extends Thread { * @param toneId ID of the tone to play, see TONE_* constants. */ private InCallTonePlayer( + Call call, int toneId, CallAudioManager callAudioManager, CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, @@ -235,6 +237,7 @@ public class InCallTonePlayer extends Thread { ToneGeneratorFactory toneGeneratorFactory, MediaPlayerFactory mediaPlayerFactor, AudioManagerAdapter audioManagerAdapter) { + mCall = call; mState = STATE_OFF; mToneId = toneId; mCallAudioManager = callAudioManager; @@ -476,7 +479,7 @@ public class InCallTonePlayer extends Thread { } if (sTonesPlaying.incrementAndGet() == 1) { - mCallAudioManager.setIsTonePlaying(true); + mCallAudioManager.setIsTonePlaying(mCall, true); } synchronized (mSessionLock) { @@ -524,7 +527,7 @@ public class InCallTonePlayer extends Thread { Log.i(InCallTonePlayer.this, "cleanUpTonePlayer(): tonesPlaying=%d, tone completed", newToneCount); if (mCallAudioManager != null) { - mCallAudioManager.setIsTonePlaying(false); + mCallAudioManager.setIsTonePlaying(mCall, false); } else { Log.w(InCallTonePlayer.this, "cleanUpTonePlayer(): mCallAudioManager is null!"); diff --git a/src/com/android/server/telecom/MissedCallNotifier.java b/src/com/android/server/telecom/MissedCallNotifier.java index 0e5a2874d..b0a7c8ecb 100644 --- a/src/com/android/server/telecom/MissedCallNotifier.java +++ b/src/com/android/server/telecom/MissedCallNotifier.java @@ -16,6 +16,7 @@ package com.android.server.telecom; +import android.annotation.Nullable; import android.net.Uri; import android.os.UserHandle; import android.telecom.PhoneAccountHandle; @@ -85,7 +86,7 @@ public interface MissedCallNotifier extends CallsManager.CallsManagerListener { void clearMissedCalls(UserHandle userHandle); - void showMissedCallNotification(CallInfo call); + void showMissedCallNotification(CallInfo call, @Nullable Uri uri); void reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper, CallInfoFactory callInfoFactory); diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java index 3b402b1aa..6070baa5f 100644 --- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java +++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java @@ -16,6 +16,7 @@ package com.android.server.telecom; +import android.Manifest; import android.app.Activity; import android.app.AppOpsManager; import android.app.BroadcastOptions; @@ -37,6 +38,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.callredirection.CallRedirectionProcessor; // TODO: Needed for move to system service: import com.android.internal.R; @@ -77,6 +79,7 @@ public class NewOutgoingCallIntentBroadcaster { private final TelecomSystem.SyncRoot mLock; private final DefaultDialerCache mDefaultDialerCache; private final MmiUtils mMmiUtils; + private final FeatureFlags mFeatureFlags; /* * Whether or not the outgoing call intent originated from the default phone application. If @@ -100,7 +103,8 @@ public class NewOutgoingCallIntentBroadcaster { @VisibleForTesting public NewOutgoingCallIntentBroadcaster(Context context, CallsManager callsManager, Intent intent, PhoneNumberUtilsAdapter phoneNumberUtilsAdapter, - boolean isDefaultPhoneApp, DefaultDialerCache defaultDialerCache, MmiUtils mmiUtils) { + boolean isDefaultPhoneApp, DefaultDialerCache defaultDialerCache, MmiUtils mmiUtils, + FeatureFlags featureFlags) { mContext = context; mCallsManager = callsManager; mIntent = intent; @@ -109,6 +113,7 @@ public class NewOutgoingCallIntentBroadcaster { mLock = mCallsManager.getLock(); mDefaultDialerCache = defaultDialerCache; mMmiUtils = mmiUtils; + mFeatureFlags = featureFlags; } /** @@ -128,7 +133,8 @@ public class NewOutgoingCallIntentBroadcaster { // Once the NEW_OUTGOING_CALL broadcast is finished, the resultData is // used as the actual number to call. (If null, no call will be placed.) String resultNumber = getResultData(); - Log.i(this, "Received new-outgoing-call-broadcast for %s with data %s", mCall, + Log.i(NewOutgoingCallIntentBroadcaster.this, + "Received new-outgoing-call-broadcast for %s with data %s", mCall, Log.pii(resultNumber)); boolean endEarly = false; @@ -320,6 +326,7 @@ public class NewOutgoingCallIntentBroadcaster { String scheme = mPhoneNumberUtilsAdapter.isUriNumber(number) ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL; result.callingAddress = Uri.fromParts(scheme, number, null); + return result; } @@ -351,14 +358,57 @@ public class NewOutgoingCallIntentBroadcaster { public void processCall(Call call, CallDisposition disposition) { mCall = call; + + // If the new outgoing call broadast doesn't block, trigger the legacy process call + // behavior and exit out here. + if (!mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) { + legacyProcessCall(disposition); + return; + } + boolean callRedirectionWithService = false; + // Only try to do redirection if it was requested and we're not calling immediately. + // We can expect callImmediately to be true for emergency calls and voip calls. + if (disposition.requestRedirection && !disposition.callImmediately) { + CallRedirectionProcessor callRedirectionProcessor = new CallRedirectionProcessor( + mContext, mCallsManager, mCall, disposition.callingAddress, + mCallsManager.getPhoneAccountRegistrar(), + getGateWayInfoFromIntent(mIntent, mIntent.getData()), + mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, + false), + mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, + VideoProfile.STATE_AUDIO_ONLY)); + /** + * If there is an available {@link android.telecom.CallRedirectionService}, use the + * {@link CallRedirectionProcessor} to perform call redirection instead of using + * broadcasting. + */ + callRedirectionWithService = callRedirectionProcessor + .canMakeCallRedirectionWithServiceAsUser(mCall.getAssociatedUser()); + if (callRedirectionWithService) { + callRedirectionProcessor.performCallRedirection(mCall.getAssociatedUser()); + } + } + + // If no redirection was kicked off, place the call now. + if (!callRedirectionWithService) { + callImmediately(disposition); + } + + // Finally, send the non-blocking broadcast if we're supposed to (ie for any non-voip call). + if (disposition.sendBroadcast) { + UserHandle targetUser = mCall.getAssociatedUser(); + broadcastIntent(mIntent, disposition.number, false /* receiverRequired */, targetUser); + } + } + + /** + * The legacy non-flagged version of processing a call. Although there is some code duplication + * if makes the new flow cleaner to read. + * @param disposition + */ + private void legacyProcessCall(CallDisposition disposition) { if (disposition.callImmediately) { - boolean speakerphoneOn = mIntent.getBooleanExtra( - TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false); - int videoState = mIntent.getIntExtra( - TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, - VideoProfile.STATE_AUDIO_ONLY); - placeOutgoingCallImmediately(mCall, disposition.callingAddress, null, - speakerphoneOn, videoState); + callImmediately(disposition); // Don't return but instead continue and send the ACTION_NEW_OUTGOING_CALL broadcast // so that third parties can still inspect (but not intercept) the outgoing call. When @@ -390,13 +440,26 @@ public class NewOutgoingCallIntentBroadcaster { if (disposition.sendBroadcast) { UserHandle targetUser = mCall.getAssociatedUser(); - Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser); broadcastIntent(mIntent, disposition.number, !disposition.callImmediately && !callRedirectionWithService, targetUser); } } /** + * Place a call immediately. + * @param disposition The disposition; used for retrieving the address of the call. + */ + private void callImmediately(CallDisposition disposition) { + boolean speakerphoneOn = mIntent.getBooleanExtra( + TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false); + int videoState = mIntent.getIntExtra( + TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, + VideoProfile.STATE_AUDIO_ONLY); + placeOutgoingCallImmediately(mCall, disposition.callingAddress, null, + speakerphoneOn, videoState); + } + + /** * Sends a new outgoing call ordered broadcast so that third party apps can cancel the * placement of the call or redirect it to a different number. * @@ -415,28 +478,51 @@ public class NewOutgoingCallIntentBroadcaster { if (number != null) { broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); } - - // Force receivers of this broadcast intent to run at foreground priority because we - // want to finish processing the broadcast intent as soon as possible. - broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Log.v(this, "Broadcasting intent: %s.", broadcastIntent); checkAndCopyProviderExtras(originalCallIntent, broadcastIntent); - final BroadcastOptions options = BroadcastOptions.makeBasic(); - options.setBackgroundActivityStartsAllowed(true); - mContext.sendOrderedBroadcastAsUser( - broadcastIntent, - targetUser, - android.Manifest.permission.PROCESS_OUTGOING_CALLS, - AppOpsManager.OP_PROCESS_OUTGOING_CALLS, - options.toBundle(), - receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null, - null, // scheduler - Activity.RESULT_OK, // initialCode - number, // initialData: initial value for the result data (number to be modified) - null); // initialExtras + if (mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) { + // Where the new outgoing call broadcast is unblocking, do not give receiver FG priority + // and do not allow background activity starts. + broadcastIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + Log.i(this, "broadcastIntent: Sending non-blocking for %s to %s", mCall.getId(), + targetUser); + if (mFeatureFlags.telecomResolveHiddenDependencies()) { + mContext.sendBroadcastAsUser( + broadcastIntent, + targetUser, + Manifest.permission.PROCESS_OUTGOING_CALLS); + } else { + mContext.sendBroadcastAsUser( + broadcastIntent, + targetUser, + android.Manifest.permission.PROCESS_OUTGOING_CALLS, + AppOpsManager.OP_PROCESS_OUTGOING_CALLS); // initialExtras + } + } else { + Log.i(this, "broadcastIntent: Sending ordered for %s to %s, waitForResult=%b", + mCall.getId(), targetUser, receiverRequired); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setBackgroundActivityStartsAllowed(true); + // Force receivers of this broadcast intent to run at foreground priority because we + // want to finish processing the broadcast intent as soon as possible. + broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + + mContext.sendOrderedBroadcastAsUser( + broadcastIntent, + targetUser, + android.Manifest.permission.PROCESS_OUTGOING_CALLS, + AppOpsManager.OP_PROCESS_OUTGOING_CALLS, + options.toBundle(), + receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null, + null, // scheduler + Activity.RESULT_OK, // initialCode + number, // initialData: initial value for the result data (number to be + // modified) + null); // initialExtras + } } /** diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java index 673b99a9b..c77e6050d 100644 --- a/src/com/android/server/telecom/ParcelableCallUtils.java +++ b/src/com/android/server/telecom/ParcelableCallUtils.java @@ -158,6 +158,10 @@ public class ParcelableCallUtils { properties |= android.telecom.Call.Details.PROPERTY_VOIP_AUDIO_MODE; } + if (call.isTransactionalCall()) { + properties |= android.telecom.Call.Details.PROPERTY_IS_TRANSACTIONAL; + } + // If this is a single-SIM device, the "default SIM" will always be the only SIM. boolean isDefaultSmsAccount = phoneAccountRegistrar != null && phoneAccountRegistrar.isUserSelectedSmsPhoneAccount(call.getTargetPhoneAccount()); diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java index acf07e35a..5f23e4d70 100644 --- a/src/com/android/server/telecom/PhoneAccountRegistrar.java +++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java @@ -61,6 +61,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.XmlUtils; import com.android.modules.utils.ModifiedUtf8; +import com.android.server.telecom.flags.Flags; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -389,26 +390,62 @@ public class PhoneAccountRegistrar { account.getGroupId())); } - // Potentially update the default voice subid in SubscriptionManager. + // Potentially update the default voice subid in SubscriptionManager so that Telephony and + // Telecom are in sync. int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : getSubscriptionIdForPhoneAccount(accountHandle); - if (isSimAccount || accountHandle == null) { - int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId(); - if (newSubId != currentVoiceSubId) { - Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; " - + "account=%s, subId=%d", accountHandle, newSubId); - mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId); + if (Flags.onlyUpdateTelephonyOnValidSubIds()) { + if (shouldUpdateTelephonyDefaultVoiceSubId(accountHandle, isSimAccount, newSubId)) { + updateDefaultVoiceSubId(newSubId, accountHandle); } else { - Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub"); + Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle); } } else { - Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle); + if (isSimAccount || accountHandle == null) { + updateDefaultVoiceSubId(newSubId, accountHandle); + } else { + Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle); + } } - write(); fireDefaultOutgoingChanged(); } + private void updateDefaultVoiceSubId(int newSubId, PhoneAccountHandle accountHandle){ + int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId(); + if (newSubId != currentVoiceSubId) { + Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; " + + "account=%s, subId=%d", accountHandle, newSubId); + mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId); + } else { + Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub"); + } + } + + // This helper is important for CTS testing. [PhoneAccount]s created by Telecom in CTS are + // assigned a subId value of INVALID_SUBSCRIPTION_ID (-1) by Telephony. However, when + // Telephony has a default outgoing calling voice account of -1, that translates to no default + // account (user should be prompted to select an acct when making MOs). In order to avoid + // Telephony clearing out the newly changed default [PhoneAccount] in Telecom, Telephony should + // not be updated. This situation will never occur in production since [PhoneAccount]s in + // production are assigned non-negative subId values. + private boolean shouldUpdateTelephonyDefaultVoiceSubId(PhoneAccountHandle phoneAccountHandle, + boolean isSimAccount, int newSubId) { + // user requests no call preference + if (phoneAccountHandle == null) { + return true; + } + // do not update Telephony if the newSubId is invalid + if (newSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + Log.w(this, "shouldUpdateTelephonyDefaultVoiceSubId: " + + "invalid subId scenario, not updating Telephony. " + + "phoneAccountHandle=[%s], isSimAccount=[%b], newSubId=[%s]", + phoneAccountHandle, isSimAccount, newSubId); + return false; + } + return isSimAccount; + } + boolean isUserSelectedSmsPhoneAccount(PhoneAccountHandle accountHandle) { return getSubscriptionIdForPhoneAccount(accountHandle) == SubscriptionManager.getDefaultSmsSubscriptionId(); @@ -897,13 +934,15 @@ public class PhoneAccountRegistrar { * @throws IllegalArgumentException if MAX_PHONE_ACCOUNT_REGISTRATIONS are reached */ private void enforceMaxPhoneAccountLimit(@NonNull PhoneAccount account) { - final PhoneAccountHandle accountHandle = account.getAccountHandle(); - final UserHandle user = accountHandle.getUserHandle(); - final ComponentName componentName = accountHandle.getComponentName(); - - if (getPhoneAccountHandles(0, null, componentName.getPackageName(), - true /* includeDisabled */, user, false /* crossUserAccess */).size() - >= MAX_PHONE_ACCOUNT_REGISTRATIONS) { + List<PhoneAccount> unverifiedAccounts = getAccountsForPackage_BypassResolveComp( + account.getAccountHandle().getComponentName().getPackageName(), + account.getAccountHandle().getUserHandle()); + // verify each phone account is backed by a valid ConnectionService. If the + // ConnectionService has been disabled or cannot be resolved, unregister the accounts. + List<PhoneAccount> verifiedAccounts = + cleanupUnresolvableConnectionServiceAccounts(unverifiedAccounts); + // enforce the max phone account limit for the application registering accounts + if (verifiedAccounts.size() >= MAX_PHONE_ACCOUNT_REGISTRATIONS) { EventLog.writeEvent(0x534e4554, "259064622", Binder.getCallingUid(), "enforceMaxPhoneAccountLimit"); throw new IllegalArgumentException( @@ -1550,6 +1589,51 @@ public class PhoneAccountRegistrar { } /** + * This getter should be used when you want to bypass the {@link + * PhoneAccountRegistrar#resolveComponent(PhoneAccountHandle)} check when fetching accounts + */ + @VisibleForTesting + public List<PhoneAccount> getAccountsForPackage_BypassResolveComp(String packageName, + UserHandle userHandle) { + List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size()); + for (PhoneAccount m : mState.accounts) { + PhoneAccountHandle handle = m.getAccountHandle(); + + if (packageName != null && !packageName.equals( + handle.getComponentName().getPackageName())) { + // Not the right package name; skip this one. + continue; + } + + if (!isVisibleForUser(m, userHandle, false)) { + // Account is not visible for the current user; skip this one. + continue; + } + accounts.add(m); + } + return accounts; + } + + @VisibleForTesting + public List<PhoneAccount> cleanupUnresolvableConnectionServiceAccounts( + List<PhoneAccount> accounts) { + ArrayList<PhoneAccount> verifiedAccounts = new ArrayList<>(); + for (PhoneAccount account : accounts) { + PhoneAccountHandle handle = account.getAccountHandle(); + // if the ConnectionService has been disabled or can longer be found, remove the handle + if (resolveComponent(handle).isEmpty()) { + Log.i(this, + "Cannot resolve the ConnectionService for handle=[%s]; unregistering" + + " account", handle); + unregisterPhoneAccount(handle); + } else { + verifiedAccounts.add(account); + } + } + return verifiedAccounts; + } + + /** * Clean up the orphan {@code PhoneAccount}. An orphan {@code PhoneAccount} is a phone * account that does not have a {@code UserHandle} or belongs to a deleted package. * @@ -1662,6 +1746,7 @@ public class PhoneAccountRegistrar { } else { pw.println(defaultOutgoing); } + pw.println("defaultVoiceSubId: " + SubscriptionManager.getDefaultVoiceSubscriptionId()); pw.println("simCallManager: " + getSimCallManager(mCurrentUserHandle)); pw.println("phoneAccounts:"); pw.increaseIndent(); diff --git a/src/com/android/server/telecom/RingbackPlayer.java b/src/com/android/server/telecom/RingbackPlayer.java index a8af3acbd..5ace9ba6e 100644 --- a/src/com/android/server/telecom/RingbackPlayer.java +++ b/src/com/android/server/telecom/RingbackPlayer.java @@ -19,6 +19,7 @@ package com.android.server.telecom; import static com.android.server.telecom.LogUtils.Events.START_RINBACK; import static com.android.server.telecom.LogUtils.Events.STOP_RINGBACK; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import android.telecom.Log; @@ -42,8 +43,12 @@ public class RingbackPlayer { */ private InCallTonePlayer mTonePlayer; - RingbackPlayer(InCallTonePlayer.Factory playerFactory) { + private final Object mLock; + + @VisibleForTesting + public RingbackPlayer(InCallTonePlayer.Factory playerFactory) { mPlayerFactory = playerFactory; + mLock = new Object(); } /** @@ -52,25 +57,27 @@ public class RingbackPlayer { * @param call The call for which to ringback. */ public void startRingbackForCall(Call call) { - Preconditions.checkState(call.getState() == CallState.DIALING); + synchronized (mLock) { + Preconditions.checkState(call.getState() == CallState.DIALING); - if (mCall == call) { - Log.w(this, "Ignoring duplicate requests to ring for %s.", call); - return; - } + if (mCall == call) { + Log.w(this, "Ignoring duplicate requests to ring for %s.", call); + return; + } - if (mCall != null) { - // We only get here for the foreground call so, there's no reason why there should - // exist a current dialing call. - Log.wtf(this, "Ringback player thinks there are two foreground-dialing calls."); - } + if (mCall != null) { + // We only get here for the foreground call so, there's no reason why there should + // exist a current dialing call. + Log.wtf(this, "Ringback player thinks there are two foreground-dialing calls."); + } - mCall = call; - if (mTonePlayer == null) { - Log.i(this, "Playing the ringback tone for %s.", call); - Log.addEvent(call, START_RINBACK); - mTonePlayer = mPlayerFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK); - mTonePlayer.startTone(); + mCall = call; + if (mTonePlayer == null) { + Log.i(this, "Playing the ringback tone for %s.", call); + Log.addEvent(call, START_RINBACK); + mTonePlayer = mPlayerFactory.createPlayer(call, InCallTonePlayer.TONE_RING_BACK); + mTonePlayer.startTone(); + } } } @@ -80,19 +87,27 @@ public class RingbackPlayer { * @param call The call for which to stop ringback. */ public void stopRingbackForCall(Call call) { - if (mCall == call) { - // The foreground call is no longer dialing or is no longer the foreground call. In - // either case, stop the ringback tone. - mCall = null; + synchronized (mLock) { + if (mCall == call) { + // The foreground call is no longer dialing or is no longer the foreground call. In + // either case, stop the ringback tone. + mCall = null; - if (mTonePlayer == null) { - Log.w(this, "No player found to stop."); - } else { - Log.i(this, "Stopping the ringback tone for %s.", call); - Log.addEvent(call, STOP_RINGBACK); - mTonePlayer.stopTone(); - mTonePlayer = null; + if (mTonePlayer == null) { + Log.w(this, "No player found to stop."); + } else { + Log.i(this, "Stopping the ringback tone for %s.", call); + Log.addEvent(call, STOP_RINGBACK); + mTonePlayer.stopTone(); + mTonePlayer = null; + } } } } + + public boolean isRingbackPlaying() { + synchronized (mLock) { + return mTonePlayer != null; + } + } }
\ No newline at end of file diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java index 16dc5c462..3ec4ebe4c 100644 --- a/src/com/android/server/telecom/Ringer.java +++ b/src/com/android/server/telecom/Ringer.java @@ -22,10 +22,12 @@ import static android.provider.CallLog.Calls.USER_MISSED_NO_VIBRATE; import static android.provider.Settings.Global.ZEN_MODE_OFF; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationManager; import android.app.Person; import android.content.Context; +import android.content.res.Resources; import android.media.AudioManager; import android.media.Ringtone; import android.media.VolumeShaper; @@ -38,13 +40,20 @@ import android.os.UserManager; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.vibrator.persistence.ParsedVibration; +import android.os.vibrator.persistence.VibrationXmlParser; import android.telecom.Log; import android.telecom.TelecomManager; import android.view.accessibility.AccessibilityManager; import com.android.internal.annotations.VisibleForTesting; import com.android.server.telecom.LogUtils.EventTimer; +import com.android.server.telecom.flags.FeatureFlags; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -59,6 +68,8 @@ import java.util.function.Supplier; */ @VisibleForTesting public class Ringer { + private static final String TAG = "TelecomRinger"; + public interface AccessibilityManagerAdapter { boolean startFlashNotificationSequence(@NonNull Context context, @AccessibilityManager.FlashNotificationReason int reason); @@ -84,6 +95,16 @@ public class Ringer { // Used for test to notify the completion of RingerAttributes private CountDownLatch mAttributesLatch; + /** + * Delay to be used between consecutive vibrations when a non-repeating vibration effect is + * provided by the device. + * + * <p>If looking to customize the loop delay for a device's ring vibration, the desired repeat + * behavior should be encoded directly in the effect specification in the device configuration + * rather than changing the here (i.e. in `R.raw.default_ringtone_vibration_effect` resource). + */ + private static int DEFAULT_RING_VIBRATION_LOOP_DELAY_MS = 1000; + private static final long[] PULSE_PRIMING_PATTERN = {0,12,250,12,500}; // priming + interval private static final int[] PULSE_PRIMING_AMPLITUDE = {0,255,0,255,0}; // priming + interval @@ -96,9 +117,11 @@ public class Ringer { private static final int[] PULSE_RAMPING_AMPLITUDE = { 77,77,78,79,81,84,87,93,101,114,133,162,205,255,255,0}; - private static final long[] PULSE_PATTERN; + @VisibleForTesting + public static final long[] PULSE_PATTERN; - private static final int[] PULSE_AMPLITUDE; + @VisibleForTesting + public static final int[] PULSE_AMPLITUDE; private static final int RAMPING_RINGER_VIBRATION_DURATION = 5000; private static final int RAMPING_RINGER_DURATION = 10000; @@ -162,6 +185,7 @@ public class Ringer { private final InCallController mInCallController; private final VibrationEffectProxy mVibrationEffectProxy; private final boolean mIsHapticPlaybackSupportedByDevice; + private final FeatureFlags mFlags; /** * For unit testing purposes only; when set, {@link #startRinging(Call, boolean)} will complete * the future provided by the test using {@link #setBlockOnRingingFuture(CompletableFuture)}. @@ -207,7 +231,8 @@ public class Ringer { VibrationEffectProxy vibrationEffectProxy, InCallController inCallController, NotificationManager notificationManager, - AccessibilityManagerAdapter accessibilityManagerAdapter) { + AccessibilityManagerAdapter accessibilityManagerAdapter, + FeatureFlags featureFlags) { mLock = new Object(); mSystemSettingsUtil = systemSettingsUtil; @@ -223,18 +248,15 @@ public class Ringer { mNotificationManager = notificationManager; mAccessibilityManagerAdapter = accessibilityManagerAdapter; - if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) { - mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN, - SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT); - } else { - mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(PULSE_PATTERN, - PULSE_AMPLITUDE, REPEAT_VIBRATION_AT); - } + mDefaultVibrationEffect = + loadDefaultRingVibrationEffect( + mContext, mVibrator, mVibrationEffectProxy, featureFlags); mIsHapticPlaybackSupportedByDevice = mSystemSettingsUtil.isHapticPlaybackSupported(mContext); mAudioManager = mContext.getSystemService(AudioManager.class); + mFlags = featureFlags; } @VisibleForTesting @@ -570,7 +592,7 @@ public class Ringer { Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE, reason); mCallWaitingCall = call; mCallWaitingPlayer = - mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING); + mPlayerFactory.createPlayer(call, InCallTonePlayer.TONE_CALL_WAITING); mCallWaitingPlayer.startTone(); } } @@ -629,14 +651,21 @@ public class Ringer { Log.i(this, "shouldRingForContact: returning computation from DndCallFilter."); return !call.isCallSuppressedByDoNotDisturb(); } - final Uri contactUri = call.getHandle(); - final Bundle peopleExtras = new Bundle(); - if (contactUri != null) { - ArrayList<Person> personList = new ArrayList<>(); - personList.add(new Person.Builder().setUri(contactUri.toString()).build()); - peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList); + Uri contactUri = call.getHandle(); + if (mFlags.telecomResolveHiddenDependencies()) { + if (contactUri == null) { + contactUri = Uri.EMPTY; + } + return mNotificationManager.matchesCallFilter(contactUri); + } else { + final Bundle peopleExtras = new Bundle(); + if (contactUri != null) { + ArrayList<Person> personList = new ArrayList<>(); + personList.add(new Person.Builder().setUri(contactUri.toString()).build()); + peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList); + } + return mNotificationManager.matchesCallFilter(peopleExtras); } - return mNotificationManager.matchesCallFilter(peopleExtras); } private boolean hasExternalRinger(Call foregroundCall) { @@ -757,4 +786,65 @@ public class Ringer { return false; } } + + @Nullable + private static VibrationEffect loadSerializedDefaultRingVibration( + Resources resources, Vibrator vibrator) { + try { + InputStream vibrationInputStream = + resources.openRawResource( + com.android.internal.R.raw.default_ringtone_vibration_effect); + ParsedVibration parsedVibration = VibrationXmlParser + .parseDocument( + new InputStreamReader(vibrationInputStream, StandardCharsets.UTF_8)); + if (parsedVibration == null) { + Log.w(TAG, "Got null parsed default ring vibration effect."); + return null; + } + return parsedVibration.resolve(vibrator); + } catch (IOException | Resources.NotFoundException e) { + Log.e(TAG, e, "Error parsing default ring vibration effect."); + return null; + } + } + + private static VibrationEffect loadDefaultRingVibrationEffect( + Context context, + Vibrator vibrator, + VibrationEffectProxy vibrationEffectProxy, + FeatureFlags featureFlags) { + Resources resources = context.getResources(); + + if (resources.getBoolean(R.bool.use_simple_vibration_pattern)) { + Log.i(TAG, "Using simple default ring vibration."); + return createSimpleRingVibration(vibrationEffectProxy); + } + + if (featureFlags.useDeviceProvidedSerializedRingerVibration()) { + VibrationEffect parsedEffect = loadSerializedDefaultRingVibration(resources, vibrator); + if (parsedEffect != null) { + Log.i(TAG, "Using parsed default ring vibration."); + // Make the parsed effect repeating to make it vibrate continuously during ring. + // If the effect is already repeating, this API call is a no-op. + // Otherwise, it uses `DEFAULT_RING_VIBRATION_LOOP_DELAY_MS` when changing a + // non-repeating vibration to a repeating vibration. + // This is so that we ensure consecutive loops of the vibration play with some gap + // in between. + return parsedEffect.applyRepeatingIndefinitely( + /* wantRepeating= */ true, DEFAULT_RING_VIBRATION_LOOP_DELAY_MS); + } + // Fallback to the simple vibration if the serialized effect cannot be loaded. + return createSimpleRingVibration(vibrationEffectProxy); + } + + Log.i(TAG, "Using pulse default ring vibration."); + return vibrationEffectProxy.createWaveform( + PULSE_PATTERN, PULSE_AMPLITUDE, REPEAT_VIBRATION_AT); + } + + private static VibrationEffect createSimpleRingVibration( + VibrationEffectProxy vibrationEffectProxy) { + return vibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN, + SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT); + } } diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java index 7274993e7..77f7b2e65 100644 --- a/src/com/android/server/telecom/ServiceBinder.java +++ b/src/com/android/server/telecom/ServiceBinder.java @@ -29,6 +29,7 @@ import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.server.telecom.flags.FeatureFlags; import java.util.Collections; import java.util.Set; @@ -240,6 +241,8 @@ public abstract class ServiceBinder { * Abbreviated form of the package name from {@link #mComponentName}; used for session logging. */ protected final String mPackageAbbreviation; + private final FeatureFlags mFlags; + /** The set of callbacks waiting for notification of the binding's success or failure. */ private final Set<BindCallback> mCallbacks = new ArraySet<>(); @@ -282,7 +285,7 @@ public abstract class ServiceBinder { * @param userHandle The {@link UserHandle} to use for binding. */ protected ServiceBinder(String serviceAction, ComponentName componentName, Context context, - TelecomSystem.SyncRoot lock, UserHandle userHandle) { + TelecomSystem.SyncRoot lock, UserHandle userHandle, FeatureFlags featureFlags) { Preconditions.checkState(!TextUtils.isEmpty(serviceAction)); Preconditions.checkNotNull(componentName); @@ -292,6 +295,7 @@ public abstract class ServiceBinder { mComponentName = componentName; mPackageAbbreviation = Log.getPackageAbbreviation(componentName); mUserHandle = userHandle; + mFlags = featureFlags; } final UserHandle getUserHandle() { @@ -305,10 +309,16 @@ public abstract class ServiceBinder { } final void decrementAssociatedCallCount() { - decrementAssociatedCallCount(false /*isSuppressingUnbind*/); + if (mFlags.updatedRcsCallCountTracking()) { + decrementAssociatedCallCountUpdated(); + } else { + decrementAssociatedCallCount(false /*isSuppressingUnbind*/); + } } final void decrementAssociatedCallCount(boolean isSuppressingUnbind) { + // This is the legacy method - will be removed after the Flags.updatedRcsCallCountTracking + // mendel study completes. if (mAssociatedCallCount > 0) { mAssociatedCallCount--; Log.v(this, "Call count decrement %d, %s", mAssociatedCallCount, @@ -323,6 +333,21 @@ public abstract class ServiceBinder { } } + final void decrementAssociatedCallCountUpdated() { + if (mAssociatedCallCount > 0) { + mAssociatedCallCount--; + Log.i(this, "Call count decrement %d, %s", mAssociatedCallCount, + mComponentName.flattenToShortString()); + + if (mAssociatedCallCount == 0) { + unbind(); + } + } else { + Log.wtf(this, "%s: ignoring a request to decrement mAssociatedCallCount below zero", + mComponentName.getClassName()); + } + } + final int getAssociatedCallCount() { return mAssociatedCallCount; } diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java index 7d3eeb683..1dd68c91e 100644 --- a/src/com/android/server/telecom/TelecomServiceImpl.java +++ b/src/com/android/server/telecom/TelecomServiceImpl.java @@ -79,6 +79,7 @@ import com.android.internal.telecom.ICallEventCallback; import com.android.internal.telecom.ITelecomService; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.components.UserCallIntentProcessorFactory; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.settings.BlockedNumbersActivity; import com.android.server.telecom.voip.IncomingCallTransaction; import com.android.server.telecom.voip.OutgoingCallTransaction; @@ -88,6 +89,7 @@ import com.android.server.telecom.voip.VoipCallTransactionResult; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.reflect.Method; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -1551,6 +1553,23 @@ public class TelecomServiceImpl { } mCallIntentProcessorAdapter.processIncomingCallIntent( mCallsManager, intent); + if (mFeatureFlags.earlyBindingToIncallService()) { + PhoneAccount account = + mPhoneAccountRegistrar.getPhoneAccountUnchecked( + phoneAccountHandle); + Bundle accountExtra = + account == null ? new Bundle() : account.getExtras(); + PackageManager packageManager = mContext.getPackageManager(); + // Start binding to InCallServices for wearable calls that do not + // require call filtering. This is to wake up default dialer earlier + // to mitigate InCallService binding latency. + if (packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH) + && accountExtra != null && accountExtra.getBoolean( + PhoneAccount.EXTRA_SKIP_CALL_FILTERING, + false)) { + mCallsManager.getInCallController().bindToServices(null); + } + } } finally { Binder.restoreCallingIdentity(token); } @@ -1967,6 +1986,11 @@ public class TelecomServiceImpl { pw.increaseIndent(); Analytics.dump(pw); pw.decreaseIndent(); + + pw.println("Flag Configurations: "); + pw.increaseIndent(); + reflectAndPrintFlagConfigs(pw); + pw.decreaseIndent(); } if (isTimeLineView) { Log.dumpEventsTimeline(pw); @@ -1976,6 +2000,28 @@ public class TelecomServiceImpl { } /** + * Print all feature flag configurations that Telecom is using for debugging purposes. + */ + private void reflectAndPrintFlagConfigs(IndentingPrintWriter pw) { + + try { + // Look away, a forbidden technique (reflection) is being used to allow us to get + // all flag configs without having to add them manually to this method. + Method[] methods = FeatureFlags.class.getMethods(); + if (methods.length == 0) { + pw.println("NONE"); + return; + } + for (Method m : methods) { + pw.println(m.getName() + "-> " + m.invoke(mFeatureFlags)); + } + } catch (Exception e) { + pw.println("[ERROR]"); + } + + } + + /** * @see android.telecom.TelecomManager#createManageBlockedNumbersIntent */ @Override @@ -2138,7 +2184,7 @@ public class TelecomServiceImpl { try { Log.i(this, "handleCallIntent: handling call intent"); mCallIntentProcessorAdapter.processOutgoingCallIntent(mContext, - mCallsManager, intent, callingPackage); + mCallsManager, intent, callingPackage, mFeatureFlags); } finally { Binder.restoreCallingIdentity(token); } @@ -2212,6 +2258,39 @@ public class TelecomServiceImpl { } /** + * A method intended for use in testing to query whether a particular non-ui inCallService + * is bound in a call. + * @param packageName of the service to query. + * @return whether it is bound or not. + */ + @Override + public boolean isNonUiInCallServiceBound(String packageName) { + Log.startSession("TCI.iNUICSB"); + try { + synchronized (mLock) { + enforceShellOnly(Binder.getCallingUid(), "isNonUiInCallServiceBound"); + if (!(mContext.checkCallingOrSelfPermission(READ_PHONE_STATE) + == PackageManager.PERMISSION_GRANTED) || + !(mContext.checkCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE) + == PackageManager.PERMISSION_GRANTED)) { + throw new SecurityException("isNonUiInCallServiceBound requires the" + + " READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE permission"); + } + long token = Binder.clearCallingIdentity(); + try { + return mCallsManager + .getInCallController() + .isNonUiInCallServiceBound(packageName); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } finally { + Log.endSession(); + } + } + + /** * A method intended for use in testing to reset car mode at all priorities. * * Runs during setup to avoid cascading failures from failing car mode CTS. @@ -2478,6 +2557,7 @@ public class TelecomServiceImpl { private final TelecomSystem.SyncRoot mLock; private TransactionManager mTransactionManager; private final TransactionalServiceRepository mTransactionalServiceRepository; + private final FeatureFlags mFeatureFlags; public TelecomServiceImpl( Context context, @@ -2488,6 +2568,7 @@ public class TelecomServiceImpl { DefaultDialerCache defaultDialerCache, SubscriptionManagerAdapter subscriptionManagerAdapter, SettingsSecureAdapter settingsSecureAdapter, + FeatureFlags featureFlags, TelecomSystem.SyncRoot lock) { mContext = context; mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); @@ -2495,6 +2576,7 @@ public class TelecomServiceImpl { mPackageManager = mContext.getPackageManager(); mCallsManager = callsManager; + mFeatureFlags = featureFlags; mLock = lock; mPhoneAccountRegistrar = phoneAccountRegistrar; mUserCallIntentProcessorFactory = userCallIntentProcessorFactory; diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java index da325f71b..101cd2d09 100644 --- a/src/com/android/server/telecom/TelecomSystem.java +++ b/src/com/android/server/telecom/TelecomSystem.java @@ -45,8 +45,12 @@ import com.android.server.telecom.bluetooth.BluetoothDeviceManager; import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; import com.android.server.telecom.callfiltering.BlockedNumbersAdapter; +import com.android.server.telecom.callfiltering.CallFilterResultCallback; +import com.android.server.telecom.callfiltering.IncomingCallFilterGraph; +import com.android.server.telecom.callfiltering.IncomingCallFilterGraphProvider; import com.android.server.telecom.components.UserCallIntentProcessor; import com.android.server.telecom.components.UserCallIntentProcessorFactory; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.ui.AudioProcessingNotification; import com.android.server.telecom.ui.CallStreamingNotification; import com.android.server.telecom.ui.DisconnectedCallNotifier; @@ -224,7 +228,8 @@ public class TelecomSystem { Ringer.AccessibilityManagerAdapter accessibilityManagerAdapter, Executor asyncTaskExecutor, Executor asyncCallAudioTaskExecutor, - BlockedNumbersAdapter blockedNumbersAdapter) { + BlockedNumbersAdapter blockedNumbersAdapter, + FeatureFlags featureFlags) { mContext = context.getApplicationContext(); LogUtils.initLogging(mContext); android.telecom.Log.setLock(mLock); @@ -250,13 +255,19 @@ public class TelecomSystem { return context.getContentResolver().openInputStream(uri); } }); + CallAudioCommunicationDeviceTracker communicationDeviceTracker = new + CallAudioCommunicationDeviceTracker(mContext); BluetoothDeviceManager bluetoothDeviceManager = new BluetoothDeviceManager(mContext, - mContext.getSystemService(BluetoothManager.class).getAdapter()); + mContext.getSystemService(BluetoothManager.class).getAdapter(), + communicationDeviceTracker, featureFlags); BluetoothRouteManager bluetoothRouteManager = new BluetoothRouteManager(mContext, mLock, - bluetoothDeviceManager, new Timeouts.Adapter()); + bluetoothDeviceManager, new Timeouts.Adapter(), + communicationDeviceTracker, featureFlags); BluetoothStateReceiver bluetoothStateReceiver = new BluetoothStateReceiver( - bluetoothDeviceManager, bluetoothRouteManager); + bluetoothDeviceManager, bluetoothRouteManager, + communicationDeviceTracker, featureFlags); mContext.registerReceiver(bluetoothStateReceiver, BluetoothStateReceiver.INTENT_FILTER); + communicationDeviceTracker.setBluetoothRouteManager(bluetoothRouteManager); WiredHeadsetManager wiredHeadsetManager = new WiredHeadsetManager(mContext); SystemStateHelper systemStateHelper = new SystemStateHelper(mContext, mLock); @@ -264,7 +275,8 @@ public class TelecomSystem { mMissedCallNotifier = missedCallNotifierImplFactory .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, defaultDialerCache, - deviceIdleControllerAdapter); + deviceIdleControllerAdapter, + featureFlags); DisconnectedCallNotifier.Factory disconnectedCallNotifierFactory = new DisconnectedCallNotifier.Default(); @@ -283,7 +295,7 @@ public class TelecomSystem { EmergencyCallHelper emergencyCallHelper) { return new InCallController(context, lock, callsManager, systemStateProvider, defaultDialerCache, timeoutsAdapter, emergencyCallHelper, - new CarModeTracker(), clockProxy); + new CarModeTracker(), clockProxy, featureFlags); } }; @@ -401,7 +413,10 @@ public class TelecomSystem { blockedNumbersAdapter, transactionManager, emergencyCallDiagnosticLogger, - callStreamingNotification); + communicationDeviceTracker, + callStreamingNotification, + featureFlags, + IncomingCallFilterGraph::new); mIncomingCallNotifier = incomingCallNotifier; incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() { @@ -445,7 +460,7 @@ public class TelecomSystem { } mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager, - defaultDialerCache); + defaultDialerCache, featureFlags); mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor( mContext, mCallsManager); @@ -469,6 +484,7 @@ public class TelecomSystem { defaultDialerCache, new TelecomServiceImpl.SubscriptionManagerAdapterImpl(), new TelecomServiceImpl.SettingsSecureAdapterImpl(), + featureFlags, mLock); } finally { Log.endSession(); diff --git a/src/com/android/server/telecom/TransactionalServiceWrapper.java b/src/com/android/server/telecom/TransactionalServiceWrapper.java index 25aaad789..02ccef7a9 100644 --- a/src/com/android/server/telecom/TransactionalServiceWrapper.java +++ b/src/com/android/server/telecom/TransactionalServiceWrapper.java @@ -451,7 +451,8 @@ public class TransactionalServiceWrapper implements @Override public void onError(CallException exception) { - Log.i(TAG, "onSetInactive: onError: with e=[%e]", exception); + Log.w(TAG, "onSetInactive: onError: e.code=[%d], e.msg=[%s]", + exception.getCode(), exception.getMessage()); } }); } finally { @@ -498,8 +499,9 @@ public class TransactionalServiceWrapper implements @Override public void onError(CallException exception) { - Log.i(TAG, "onCallStreamingStarted: onError: with e=[%e]", - exception); + Log.w(TAG, "onCallStreamingStarted: onError: " + + "e.code=[%d], e.msg=[%s]", + exception.getCode(), exception.getMessage()); stopCallStreaming(call); } } diff --git a/src/com/android/server/telecom/UserUtil.java b/src/com/android/server/telecom/UserUtil.java index d0a561ad9..670ad3438 100644 --- a/src/com/android/server/telecom/UserUtil.java +++ b/src/com/android/server/telecom/UserUtil.java @@ -24,8 +24,11 @@ import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.telecom.Log; +import android.telecom.PhoneAccount; +import android.telecom.PhoneAccountHandle; import com.android.server.telecom.components.ErrorDialogActivity; +import com.android.server.telecom.flags.FeatureFlags; public final class UserUtil { @@ -99,4 +102,37 @@ public final class UserUtil { } return false; } + + /** + * Gets the associated user for the given call. Note: this is applicable to all calls except + * outgoing calls as the associated user is already based off of the user placing the + * call. + * + * @param phoneAccountRegistrar + * @param currentUser Current user profile (this can either be the admin or a secondary/guest + * user). Note that work profile users fall under the admin user. + * @param targetPhoneAccount The phone account to retrieve the {@link UserHandle} from. + * @return current user if it isn't the admin or if the work profile is paused for the target + * phone account handle user, otherwise return the target phone account handle user. If the + * flag is disabled, return the legacy {@link UserHandle}. + */ + public static UserHandle getAssociatedUserForCall(boolean isAssociatedUserFlagEnabled, + PhoneAccountRegistrar phoneAccountRegistrar, UserHandle currentUser, + PhoneAccountHandle targetPhoneAccount) { + if (!isAssociatedUserFlagEnabled) { + return targetPhoneAccount.getUserHandle(); + } + // For multi-user phone accounts, associate the call with the profile receiving/placing + // the call. For SIM accounts (that are assigned to specific users), the user association + // will be placed on the target phone account handle user. + PhoneAccount account = phoneAccountRegistrar.getPhoneAccountUnchecked(targetPhoneAccount); + if (account != null) { + return account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER) + ? currentUser + : targetPhoneAccount.getUserHandle(); + } + // If target phone account handle is null or account cannot be found, + // return the current user. + return currentUser; + } } diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java index b5e74572c..27e5a7dcb 100644 --- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java +++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java @@ -35,6 +35,8 @@ import android.util.LocalLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; +import com.android.server.telecom.flags.FeatureFlags; import java.util.ArrayList; import java.util.Collection; @@ -210,8 +212,12 @@ public class BluetoothDeviceManager { private BluetoothAdapter mBluetoothAdapter; private AudioManager mAudioManager; private Executor mExecutor; + private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; + private FeatureFlags mFeatureFlags; - public BluetoothDeviceManager(Context context, BluetoothAdapter bluetoothAdapter) { + public BluetoothDeviceManager(Context context, BluetoothAdapter bluetoothAdapter, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { if (bluetoothAdapter != null) { mBluetoothAdapter = bluetoothAdapter; bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener, @@ -222,6 +228,8 @@ public class BluetoothDeviceManager { BluetoothProfile.LE_AUDIO); mAudioManager = context.getSystemService(AudioManager.class); mExecutor = context.getMainExecutor(); + mCommunicationDeviceTracker = communicationDeviceTracker; + mFeatureFlags = featureFlags; } } @@ -446,9 +454,14 @@ public class BluetoothDeviceManager { } public void disconnectAudio() { - disconnectSco(); - clearLeAudioCommunicationDevice(); - clearHearingAidCommunicationDevice(); + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearBtCommunicationDevice(); + disconnectSco(); + } else { + disconnectSco(); + clearLeAudioCommunicationDevice(); + clearHearingAidCommunicationDevice(); + } } public void disconnectSco() { @@ -665,7 +678,10 @@ public class BluetoothDeviceManager { * Only after receiving ACTION_ACTIVE_DEVICE_CHANGED it is known that device that * will be audio switched to is available to be choose as communication device */ if (!switchingBtDevices) { - return setLeAudioCommunicationDevice(); + return mFeatureFlags.callAudioCommunicationDeviceRefactor() ? + mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_BLE_HEADSET, device) + : setLeAudioCommunicationDevice(); } return true; } @@ -676,7 +692,10 @@ public class BluetoothDeviceManager { * Only after receiving ACTION_ACTIVE_DEVICE_CHANGED it is known that device that * will be audio switched to is available to be choose as communication device */ if (!switchingBtDevices) { - return setHearingAidCommunicationDevice(); + return mFeatureFlags.callAudioCommunicationDeviceRefactor() ? + mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_HEARING_AID, null) + : setHearingAidCommunicationDevice(); } return true; } @@ -717,7 +736,9 @@ public class BluetoothDeviceManager { } public boolean isInbandRingingEnabled() { - BluetoothDevice activeDevice = mBluetoothRouteManager.getBluetoothAudioConnectedDevice(); + // Get the inband ringing enabled status of expected BT device to route call audio instead + // of using the address of currently connected device. + BluetoothDevice activeDevice = mBluetoothRouteManager.getMostRecentlyReportedActiveDevice(); Log.i(this, "isInbandRingingEnabled: activeDevice: " + activeDevice); if (mBluetoothRouteManager.isCachedLeAudioDevice(activeDevice)) { if (mBluetoothLeAudioService == null) { diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java index bce6e9959..235ba56c4 100644 --- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java +++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java @@ -17,12 +17,14 @@ package com.android.server.telecom.bluetooth; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothLeAudio; import android.content.Context; +import android.media.AudioDeviceInfo; import android.os.Message; import android.telecom.Log; import android.telecom.Logging.Session; @@ -33,8 +35,10 @@ import com.android.internal.os.SomeArgs; import com.android.internal.util.IState; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.Timeouts; +import com.android.server.telecom.flags.FeatureFlags; import java.util.ArrayList; import java.util.Collection; @@ -43,6 +47,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -132,7 +137,8 @@ public class BluetoothRouteManager extends StateMachine { @Override public void enter() { BluetoothDevice erroneouslyConnectedDevice = getBluetoothAudioConnectedDevice(); - if (erroneouslyConnectedDevice != null) { + if (erroneouslyConnectedDevice != null && + !erroneouslyConnectedDevice.equals(mHearingAidActiveDeviceCache)) { Log.w(LOG_TAG, "Entering AudioOff state but device %s appears to be connected. " + "Switching to audio-on state for that device.", erroneouslyConnectedDevice); // change this to just transition to the new audio on state @@ -250,6 +256,27 @@ public class BluetoothRouteManager extends StateMachine { SomeArgs args = (SomeArgs) msg.obj; String address = (String) args.arg2; boolean switchingBtDevices = !Objects.equals(mDeviceAddress, address); + + if (switchingBtDevices == true) { // check if it is an hearing aid pair + BluetoothAdapter bluetoothAdapter = mDeviceManager.getBluetoothAdapter(); + if (bluetoothAdapter != null) { + List<BluetoothDevice> activeHearingAids = + bluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID); + for (BluetoothDevice hearingAid : activeHearingAids) { + if (hearingAid != null) { + String hearingAidAddress = hearingAid.getAddress(); + if (hearingAidAddress != null) { + if (hearingAidAddress.equals(address) || + hearingAidAddress.equals(mDeviceAddress)) { + switchingBtDevices = false; + break; + } + } + } + } + + } + } try { switch (msg.what) { case NEW_DEVICE_CONNECTED: @@ -391,8 +418,13 @@ public class BluetoothRouteManager extends StateMachine { String actualAddress = connectBtAudio(address, true /* switchingBtDevices*/); if (actualAddress != null) { - transitionTo(getConnectingStateForAddress(address, - "AudioConnected/CONNECT_BT")); + if (mFeatureFlags.useActualAddressToEnterConnectingState()) { + transitionTo(getConnectingStateForAddress(actualAddress, + "AudioConnected/CONNECT_BT")); + } else { + transitionTo(getConnectingStateForAddress(address, + "AudioConnected/CONNECT_BT")); + } } else { Log.w(LOG_TAG, "Tried to connect to %s but failed" + " to connect to any BT device.", (String) args.arg2); @@ -469,15 +501,21 @@ public class BluetoothRouteManager extends StateMachine { private BluetoothDevice mHearingAidActiveDeviceCache = null; private BluetoothDevice mLeAudioActiveDeviceCache = null; private BluetoothDevice mMostRecentlyReportedActiveDevice = null; + private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; + private FeatureFlags mFeatureFlags; public BluetoothRouteManager(Context context, TelecomSystem.SyncRoot lock, - BluetoothDeviceManager deviceManager, Timeouts.Adapter timeoutsAdapter) { + BluetoothDeviceManager deviceManager, Timeouts.Adapter timeoutsAdapter, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { super(BluetoothRouteManager.class.getSimpleName()); mContext = context; mLock = lock; mDeviceManager = deviceManager; mDeviceManager.setBluetoothRouteManager(this); mTimeoutsAdapter = timeoutsAdapter; + mCommunicationDeviceTracker = communicationDeviceTracker; + mFeatureFlags = featureFlags; mAudioOffState = new AudioOffState(); addState(mAudioOffState); @@ -621,12 +659,22 @@ public class BluetoothRouteManager extends StateMachine { if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO) { mLeAudioActiveDeviceCache = device; if (device == null) { - mDeviceManager.clearLeAudioCommunicationDevice(); + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_BLE_HEADSET); + } else { + mDeviceManager.clearLeAudioCommunicationDevice(); + } } } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID) { mHearingAidActiveDeviceCache = device; if (device == null) { - mDeviceManager.clearHearingAidCommunicationDevice(); + if (mFeatureFlags.callAudioCommunicationDeviceRefactor()) { + mCommunicationDeviceTracker.clearCommunicationDevice( + AudioDeviceInfo.TYPE_HEARING_AID); + } else { + mDeviceManager.clearHearingAidCommunicationDevice(); + } } } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEADSET) { mHfpActiveDeviceCache = device; @@ -645,6 +693,10 @@ public class BluetoothRouteManager extends StateMachine { } } + public BluetoothDevice getMostRecentlyReportedActiveDevice() { + return mMostRecentlyReportedActiveDevice; + } + public boolean hasBtActiveDevice() { return mLeAudioActiveDeviceCache != null || mHearingAidActiveDeviceCache != null || @@ -663,6 +715,33 @@ public class BluetoothRouteManager extends StateMachine { return mDeviceManager.getUniqueConnectedDevices(); } + public boolean isWatch(BluetoothDevice device) { + if (device == null) { + Log.i(this, "isWatch: device is null. Returning false"); + return false; + } + + BluetoothClass deviceClass = device.getBluetoothClass(); + if (deviceClass != null && deviceClass.getDeviceClass() + == BluetoothClass.Device.WEARABLE_WRIST_WATCH) { + Log.i(this, "isWatch: bluetooth class component is a WEARABLE_WRIST_WATCH."); + return true; + } + + // Check metadata + byte[] deviceType = device.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE); + if (deviceType == null) { + return false; + } + String deviceTypeStr = new String(deviceType); + if (deviceTypeStr.equals(BluetoothDevice.DEVICE_TYPE_WATCH)) { + Log.i(this, "isWatch: bluetooth device type is DEVICE_TYPE_WATCH."); + return true; + } + + return false; + } + private String connectBtAudio(String address, boolean switchingBtDevices) { return connectBtAudio(address, 0, switchingBtDevices); } @@ -692,10 +771,19 @@ public class BluetoothRouteManager extends StateMachine { ? address : getActiveDeviceAddress(); if (actualAddress == null) { Log.i(this, "No device specified and BT stack has no active device." - + " Using arbitrary device"); + + " Using arbitrary device - except watch"); if (deviceList.size() > 0) { - actualAddress = deviceList.iterator().next().getAddress(); - } else { + for (BluetoothDevice device : deviceList) { + if (mFeatureFlags.ignoreAutoRouteToWatchDevice() && isWatch(device)) { + Log.i(this, "Skipping a watch device: " + device); + continue; + } + actualAddress = device.getAddress(); + break; + } + } + + if (actualAddress == null) { Log.i(this, "No devices available at all. Not connecting."); return null; } @@ -797,21 +885,37 @@ public class BluetoothRouteManager extends StateMachine { } } + boolean isHearingAidSetForCommunication = + mFeatureFlags.callAudioCommunicationDeviceRefactor() + ? mCommunicationDeviceTracker.isAudioDeviceSetForType( + AudioDeviceInfo.TYPE_HEARING_AID) + : mDeviceManager.isHearingAidSetAsCommunicationDevice(); if (bluetoothHearingAid != null) { - if (mDeviceManager.isHearingAidSetAsCommunicationDevice()) { - for (BluetoothDevice device : bluetoothAdapter.getActiveDevices( - BluetoothProfile.HEARING_AID)) { - if (device != null) { - hearingAidActiveDevice = device; - activeDevices++; - break; + if (isHearingAidSetForCommunication) { + List<BluetoothDevice> hearingAidsActiveDevices = bluetoothAdapter.getActiveDevices( + BluetoothProfile.HEARING_AID); + if (hearingAidsActiveDevices.contains(mHearingAidActiveDeviceCache)) { + hearingAidActiveDevice = mHearingAidActiveDeviceCache; + activeDevices++; + } else { + for (BluetoothDevice device : hearingAidsActiveDevices) { + if (device != null) { + hearingAidActiveDevice = device; + activeDevices++; + break; + } } } } } + boolean isLeAudioSetForCommunication = + mFeatureFlags.callAudioCommunicationDeviceRefactor() + ? mCommunicationDeviceTracker.isAudioDeviceSetForType( + AudioDeviceInfo.TYPE_BLE_HEADSET) + : mDeviceManager.isLeAudioCommunicationDevice(); if (bluetoothLeAudio != null) { - if (mDeviceManager.isLeAudioCommunicationDevice()) { + if (isLeAudioSetForCommunication) { for (BluetoothDevice device : bluetoothAdapter.getActiveDevices( BluetoothProfile.LE_AUDIO)) { if (device != null) { diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java index 09b8f76a3..d2521ac72 100644 --- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java +++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java @@ -26,11 +26,14 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.media.AudioDeviceInfo; import android.os.Bundle; import android.telecom.Log; import android.telecom.Logging.Session; import com.android.internal.os.SomeArgs; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; +import com.android.server.telecom.flags.FeatureFlags; import static com.android.server.telecom.bluetooth.BluetoothRouteManager.BT_AUDIO_IS_ON; import static com.android.server.telecom.bluetooth.BluetoothRouteManager.BT_AUDIO_LOST; @@ -56,6 +59,8 @@ public class BluetoothStateReceiver extends BroadcastReceiver { private boolean mIsInCall = false; private final BluetoothRouteManager mBluetoothRouteManager; private final BluetoothDeviceManager mBluetoothDeviceManager; + private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; + private FeatureFlags mFeatureFlags; public void onReceive(Context context, Intent intent) { Log.startSession("BSR.oR"); @@ -205,17 +210,27 @@ public class BluetoothStateReceiver extends BroadcastReceiver { /* In Le Audio case, once device got Active, the Telecom needs to make sure it * is set as communication device before we can say that BT_AUDIO_IS_ON */ + boolean isLeAudioSetForCommunication = + mFeatureFlags.callAudioCommunicationDeviceRefactor() + ? mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_BLE_HEADSET, device) + : mBluetoothDeviceManager.setLeAudioCommunicationDevice(); if ((!usePreferredAudioProfile || preferredDuplexProfile == BluetoothProfile.LE_AUDIO) - && !mBluetoothDeviceManager.setLeAudioCommunicationDevice()) { + && !isLeAudioSetForCommunication) { Log.w(LOG_TAG, "Device %s cannot be use as LE audio communication device.", device); return; } } else { + boolean isHearingAidSetForCommunication = + mFeatureFlags.callAudioCommunicationDeviceRefactor() + ? mCommunicationDeviceTracker.setCommunicationDevice( + AudioDeviceInfo.TYPE_HEARING_AID, null) + : mBluetoothDeviceManager.setHearingAidCommunicationDevice(); /* deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID */ - if (!mBluetoothDeviceManager.setHearingAidCommunicationDevice()) { + if (!isHearingAidSetForCommunication) { Log.w(LOG_TAG, "Device %s cannot be use as hearing aid communication device.", device); @@ -232,9 +247,13 @@ public class BluetoothStateReceiver extends BroadcastReceiver { } public BluetoothStateReceiver(BluetoothDeviceManager deviceManager, - BluetoothRouteManager routeManager) { + BluetoothRouteManager routeManager, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { mBluetoothDeviceManager = deviceManager; mBluetoothRouteManager = routeManager; + mCommunicationDeviceTracker = communicationDeviceTracker; + mFeatureFlags = featureFlags; } public void setIsInCall(boolean isInCall) { diff --git a/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraphProvider.java b/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraphProvider.java new file mode 100644 index 000000000..1501280de --- /dev/null +++ b/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraphProvider.java @@ -0,0 +1,44 @@ +/* + * 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.telecom.callfiltering; + +import android.content.Context; + +import com.android.server.telecom.Call; +import com.android.server.telecom.TelecomSystem; +import com.android.server.telecom.Timeouts; + +/** + * Interface to provide a {@link IncomingCallFilterGraph}. This class serve for unit test purpose + * to mock an incoming call filter graph in test code. + */ +public interface IncomingCallFilterGraphProvider { + + + /** + * Provide a {@link IncomingCallFilterGraph} + * @param call The call for the filters. + * @param listener Callback object to trigger when filtering is done. + * @param context An android context. + * @param timeoutsAdapter Adapter to provide timeout value for call filtering. + * @param lock Telecom lock. + * @return + */ + IncomingCallFilterGraph createGraph(Call call, CallFilterResultCallback listener, + Context context, + Timeouts.Adapter timeoutsAdapter, TelecomSystem.SyncRoot lock); +} diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java index 90a683fc8..9287d33fd 100644 --- a/src/com/android/server/telecom/components/TelecomService.java +++ b/src/com/android/server/telecom/components/TelecomService.java @@ -45,6 +45,7 @@ import com.android.server.telecom.ConnectionServiceFocusManager; import com.android.server.telecom.ContactsAsyncHelper; import com.android.server.telecom.DefaultDialerCache; import com.android.server.telecom.DeviceIdleControllerAdapter; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.HeadsetMediaButton; import com.android.server.telecom.HeadsetMediaButtonFactory; import com.android.server.telecom.InCallWakeLockControllerFactory; @@ -61,6 +62,7 @@ import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.TelecomWakeLock; import com.android.server.telecom.Timeouts; import com.android.server.telecom.callfiltering.BlockedNumbersAdapter; +import com.android.server.telecom.flags.FeatureFlagsImpl; import com.android.server.telecom.settings.BlockedNumbersUtil; import com.android.server.telecom.ui.IncomingCallNotifier; import com.android.server.telecom.ui.MissedCallNotifierImpl; @@ -115,10 +117,11 @@ public class TelecomService extends Service implements TelecomSystem.Component { Context context, PhoneAccountRegistrar phoneAccountRegistrar, DefaultDialerCache defaultDialerCache, - DeviceIdleControllerAdapter idleControllerAdapter) { + DeviceIdleControllerAdapter idleControllerAdapter, + FeatureFlags featureFlags) { return new MissedCallNotifierImpl(context, phoneAccountRegistrar, defaultDialerCache, - idleControllerAdapter); + idleControllerAdapter, featureFlags); } }, new CallerInfoAsyncQueryFactory() { @@ -230,7 +233,8 @@ public class TelecomService extends Service implements TelecomSystem.Component { BlockedNumbersUtil.updateEmergencyCallNotification(context, showNotification); } - })); + }, + new FeatureFlagsImpl())); } } diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java index 6b97f970a..25ce0ca5a 100644 --- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java +++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.READ_PHONE_STATE; import static android.app.admin.DevicePolicyResources.Strings.Telecomm.NOTIFICATION_MISSED_WORK_CALL_TITLE; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.BroadcastOptions; import android.app.Notification; import android.app.NotificationManager; @@ -42,6 +43,7 @@ import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.UserHandle; +import android.provider.CallLog; import android.provider.CallLog.Calls; import android.telecom.CallerInfo; import android.telecom.Log; @@ -62,6 +64,7 @@ import com.android.server.telecom.CallsManagerListenerBase; import com.android.server.telecom.Constants; import com.android.server.telecom.DefaultDialerCache; import com.android.server.telecom.DeviceIdleControllerAdapter; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.MissedCallNotifier; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.R; @@ -87,7 +90,8 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements MissedCallNotifier makeMissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar, DefaultDialerCache defaultDialerCache, - DeviceIdleControllerAdapter deviceIdleControllerAdapter); + DeviceIdleControllerAdapter deviceIdleControllerAdapter, + FeatureFlags featureFlags); } public interface NotificationBuilderFactory { @@ -141,19 +145,22 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements private final Map<UserHandle, Integer> mMissedCallCounts; private Set<UserHandle> mUsersToLoadAfterBootComplete = new ArraySet<>(); + private FeatureFlags mFeatureFlags; public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar, DefaultDialerCache defaultDialerCache, - DeviceIdleControllerAdapter deviceIdleControllerAdapter) { + DeviceIdleControllerAdapter deviceIdleControllerAdapter, + FeatureFlags featureFlags) { this(context, phoneAccountRegistrar, defaultDialerCache, - new DefaultNotificationBuilderFactory(), deviceIdleControllerAdapter); + new DefaultNotificationBuilderFactory(), deviceIdleControllerAdapter, featureFlags); } public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar, DefaultDialerCache defaultDialerCache, NotificationBuilderFactory notificationBuilderFactory, - DeviceIdleControllerAdapter deviceIdleControllerAdapter) { + DeviceIdleControllerAdapter deviceIdleControllerAdapter, + FeatureFlags featureFlags) { mContext = context; mPhoneAccountRegistrar = phoneAccountRegistrar; mNotificationManager = @@ -163,6 +170,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements mNotificationBuilderFactory = notificationBuilderFactory; mMissedCallCounts = new ArrayMap<>(); + mFeatureFlags = featureFlags; } /** Clears missed call notification and marks the call log's missed calls as read. */ @@ -261,17 +269,17 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements } private void sendNotificationThroughDefaultDialer(String dialerPackage, CallInfo callInfo, - UserHandle userHandle, int missedCallCount) { + UserHandle userHandle, int missedCallCount, @Nullable Uri uri) { Intent intent = getShowMissedCallIntentForDefaultDialer(dialerPackage) .setFlags(Intent.FLAG_RECEIVER_FOREGROUND) .putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT, createClearMissedCallsPendingIntent(userHandle)) .putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, missedCallCount) + .putExtra(TelecomManager.EXTRA_CALL_LOG_URI, uri) .putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER, callInfo == null ? null : callInfo.getPhoneNumber()) .putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, callInfo == null ? null : callInfo.getPhoneAccountHandle()); - if (missedCallCount == 1 && callInfo != null) { final Uri handleUri = callInfo.getHandle(); String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart(); @@ -295,7 +303,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements * @param callInfo The missed call. */ @Override - public void showMissedCallNotification(@NonNull CallInfo callInfo) { + public void showMissedCallNotification(@NonNull CallInfo callInfo, @Nullable Uri uri) { final PhoneAccountHandle phoneAccountHandle = callInfo.getPhoneAccountHandle(); final PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle); @@ -306,10 +314,11 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements } else { userHandle = phoneAccountHandle.getUserHandle(); } - showMissedCallNotification(callInfo, userHandle); + showMissedCallNotification(callInfo, userHandle, uri); } - private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle) { + private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle, + @Nullable Uri uri) { int missedCallCounts; synchronized (mMissedCallCountsLock) { Integer currentCount = mMissedCallCounts.get(userHandle); @@ -324,7 +333,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements String dialerPackage = getDefaultDialerPackage(userHandle); if (shouldManageNotificationThroughDefaultDialer(dialerPackage, userHandle)) { sendNotificationThroughDefaultDialer(dialerPackage, callInfo, userHandle, - missedCallCounts); + missedCallCounts, uri); return; } @@ -446,7 +455,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements String dialerPackage = getDefaultDialerPackage(userHandle); if (shouldManageNotificationThroughDefaultDialer(dialerPackage, userHandle)) { sendNotificationThroughDefaultDialer(dialerPackage, null, userHandle, - 0 /* missedCallCount */); + /* missedCallCount= */ 0, /* uri= */ null); return; } @@ -631,6 +640,13 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements while (cursor.moveToNext()) { // Get data about the missed call from the cursor final String handleString = cursor.getString(CALL_LOG_COLUMN_NUMBER); + final Uri uri; + if (mFeatureFlags.addCallUriForMissedCalls()){ + uri = Calls.CONTENT_URI.buildUpon().appendPath( + Long.toString(cursor.getInt(CALL_LOG_COLUMN_ID))).build(); + }else{ + uri = null; + } final int presentation = cursor.getInt(CALL_LOG_COLUMN_NUMBER_PRESENTATION); final long date = cursor.getLong(CALL_LOG_COLUMN_DATE); @@ -663,7 +679,8 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements // null, just show the notification. CallInfo callInfo = callInfoFactory.makeCallInfo( info, null, handle, date); - showMissedCallNotification(callInfo, userHandle); + showMissedCallNotification(callInfo, userHandle, + /* uri= */ uri); } } @@ -678,7 +695,8 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements } CallInfo callInfo = callInfoFactory.makeCallInfo( info, null, handle, date); - showMissedCallNotification(callInfo, userHandle); + showMissedCallNotification(callInfo, userHandle, + /* uri= */ uri); } } ); diff --git a/src/com/android/server/telecom/voip/VerifyCallStateChangeTransaction.java b/src/com/android/server/telecom/voip/VerifyCallStateChangeTransaction.java new file mode 100644 index 000000000..b17dedd44 --- /dev/null +++ b/src/com/android/server/telecom/voip/VerifyCallStateChangeTransaction.java @@ -0,0 +1,147 @@ +/* + * 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.telecom.voip; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.telecom.Call; +import com.android.server.telecom.CallsManager; + +import android.telecom.DisconnectCause; +import android.telecom.Log; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; + +/** + * VerifyCallStateChangeTransaction is a transaction that verifies a CallState change and has + * the ability to disconnect if the CallState is not changed within the timeout window. + * <p> + * Note: This transaction has a timeout of 2 seconds. + */ +public class VerifyCallStateChangeTransaction extends VoipCallTransaction { + private static final String TAG = VerifyCallStateChangeTransaction.class.getSimpleName(); + public static final int FAILURE_CODE = 0; + public static final int SUCCESS_CODE = 1; + public static final int TIMEOUT_SECONDS = 2; + private final Call mCall; + private final CallsManager mCallsManager; + private final int mTargetCallState; + private final boolean mShouldDisconnectUponFailure; + private final CompletableFuture<Integer> mCallStateOrTimeoutResult = new CompletableFuture<>(); + private final CompletableFuture<VoipCallTransactionResult> mTransactionResult = + new CompletableFuture<>(); + + @VisibleForTesting + public Call.CallStateListener mCallStateListenerImpl = new Call.CallStateListener() { + @Override + public void onCallStateChanged(int newCallState) { + Log.d(TAG, "newState=[%d], expectedState=[%d]", newCallState, mTargetCallState); + if (newCallState == mTargetCallState) { + mCallStateOrTimeoutResult.complete(SUCCESS_CODE); + } + // NOTE:: keep listening to the call state until the timeout is reached. It's possible + // another call state is reached in between... + } + }; + + public VerifyCallStateChangeTransaction(CallsManager callsManager, Call call, + int targetCallState, boolean shouldDisconnectUponFailure) { + super(callsManager.getLock()); + mCallsManager = callsManager; + mCall = call; + mTargetCallState = targetCallState; + mShouldDisconnectUponFailure = shouldDisconnectUponFailure; + } + + @Override + public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) { + Log.d(TAG, "processTransaction:"); + // It's possible the Call is already in the expected call state + if (isNewCallStateTargetCallState()) { + mTransactionResult.complete( + new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED, + TAG)); + return mTransactionResult; + } + initCallStateListenerOnTimeout(); + // At this point, the mCallStateOrTimeoutResult has been completed. There are 2 scenarios: + // (1) newCallState == targetCallState --> the transaction is successful + // (2) timeout is reached --> evaluate the current call state and complete the t accordingly + // also need to do cleanup for the transaction + evaluateCallStateUponChangeOrTimeout(); + + return mTransactionResult; + } + + private boolean isNewCallStateTargetCallState() { + return mCall.getState() == mTargetCallState; + } + + private void initCallStateListenerOnTimeout() { + mCall.addCallStateListener(mCallStateListenerImpl); + mCallStateOrTimeoutResult.completeOnTimeout(FAILURE_CODE, TIMEOUT_SECONDS, + TimeUnit.SECONDS); + } + + private void evaluateCallStateUponChangeOrTimeout() { + mCallStateOrTimeoutResult.thenAcceptAsync((result) -> { + Log.i(TAG, "processTransaction: thenAcceptAsync: result=[%s]", result); + mCall.removeCallStateListener(mCallStateListenerImpl); + if (isNewCallStateTargetCallState()) { + mTransactionResult.complete( + new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED, + TAG)); + } else { + maybeDisconnectCall(); + mTransactionResult.complete( + new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_FAILED, + TAG)); + } + }).exceptionally(exception -> { + Log.i(TAG, "hit exception=[%s] while completing future", exception); + mTransactionResult.complete( + new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_FAILED, + TAG)); + return null; + }); + } + + private void maybeDisconnectCall() { + if (mShouldDisconnectUponFailure) { + mCallsManager.markCallAsDisconnected(mCall, + new DisconnectCause(DisconnectCause.ERROR, + "did not hold in timeout window")); + mCallsManager.markCallAsRemoved(mCall); + } + } + + @VisibleForTesting + public CompletableFuture<Integer> getCallStateOrTimeoutResult() { + return mCallStateOrTimeoutResult; + } + + @VisibleForTesting + public CompletableFuture<VoipCallTransactionResult> getTransactionResult() { + return mTransactionResult; + } + + @VisibleForTesting + public Call.CallStateListener getCallStateListenerImpl() { + return mCallStateListenerImpl; + } +} diff --git a/src/com/android/server/telecom/voip/VoipCallMonitor.java b/src/com/android/server/telecom/voip/VoipCallMonitor.java index 3779a6d50..8f6ad514f 100644 --- a/src/com/android/server/telecom/voip/VoipCallMonitor.java +++ b/src/com/android/server/telecom/voip/VoipCallMonitor.java @@ -16,6 +16,12 @@ package com.android.server.telecom.voip; +import static android.app.ForegroundServiceDelegationOptions.DELEGATION_SERVICE_PHONE_CALL; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL; + import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ForegroundServiceDelegationOptions; @@ -199,8 +205,11 @@ public class VoipCallMonitor extends CallsManagerListenerBase { ForegroundServiceDelegationOptions options = new ForegroundServiceDelegationOptions(pid, uid, handle.getComponentName().getPackageName(), null /* clientAppThread */, false /* isSticky */, String.valueOf(handle.hashCode()), - 0 /* foregroundServiceType */, - ForegroundServiceDelegationOptions.DELEGATION_SERVICE_PHONE_CALL); + FOREGROUND_SERVICE_TYPE_PHONE_CALL | + FOREGROUND_SERVICE_TYPE_MICROPHONE | + FOREGROUND_SERVICE_TYPE_CAMERA | + FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE /* foregroundServiceTypes */, + DELEGATION_SERVICE_PHONE_CALL /* delegationService */); ServiceConnection fgsConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { diff --git a/src/com/android/server/telecom/voip/VoipCallTransactionResult.java b/src/com/android/server/telecom/voip/VoipCallTransactionResult.java index 2916fc64b..ffc025560 100644 --- a/src/com/android/server/telecom/voip/VoipCallTransactionResult.java +++ b/src/com/android/server/telecom/voip/VoipCallTransactionResult.java @@ -24,13 +24,14 @@ public class VoipCallTransactionResult { public static final int RESULT_SUCCEED = 0; public static final int RESULT_FAILED = 1; - private int mResult; - private String mMessage; - private Call mCall; + private final int mResult; + private final String mMessage; + private final Call mCall; public VoipCallTransactionResult(int result, String message) { mResult = result; mMessage = message; + mCall = null; } public VoipCallTransactionResult(int result, Call call, String message) { @@ -70,7 +71,7 @@ public class VoipCallTransactionResult { append("{ VoipCallTransactionResult: [mResult: "). append(mResult). append("], [mCall: "). - append(mCall.toString()). + append((mCall != null) ? mCall : "null"). append("], [mMessage="). append(mMessage).append("] }").toString(); } diff --git a/testapps/transactionalVoipApp/res/values-af/strings.xml b/testapps/transactionalVoipApp/res/values-af/strings.xml index efcbdc0b8..bf7ad3353 100644 --- a/testapps/transactionalVoipApp/res/values-af/strings.xml +++ b/testapps/transactionalVoipApp/res/values-af/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API-toetsaktiwiteit"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaksionele inoproepaktiwiteit"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registreer foonrekening"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Begin voorgronddiens (simuleer masjienvertaling + app op agtergrond)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Begin uitgaande oproep"</string> + <string name="start_incoming" msgid="6444983300186361271">"Begin inkomende oproep"</string> + <string name="get_call_id" msgid="5513943242738347108">"oproep-id is nie gestel nie"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"antwoord"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ontkoppel"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Oorstuk"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Luidspreker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"begin stroom"</string> + <string name="crash_app" msgid="2548690390730057704">"gooi uitsondering"</string> + <string name="update_notification" msgid="8677916482672588779">"dateer kennisgewing aan voortdurende oproepstyl op"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-am/strings.xml b/testapps/transactionalVoipApp/res/values-am/strings.xml index b155a3afd..d71c28739 100644 --- a/testapps/transactionalVoipApp/res/values-am/strings.xml +++ b/testapps/transactionalVoipApp/res/values-am/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"የግብይት ኤፒአይ ሙከራ እንቅስቃሴ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"በጥሪ እንቅስቃሴ ውስጥ ግብይታዊ"</string> <string name="register_phone_account" msgid="1920315963082350332">"የስልክ መለያ መዝግብ"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS ይጀምሩ (በዳራው ውስጥ MT + መተግበሪያን ያስመስላል)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"ወጪ ጥሪን ይጀምሩ"</string> + <string name="start_incoming" msgid="6444983300186361271">"ገቢ ጥሪን ይጀምሩ"</string> + <string name="get_call_id" msgid="5513943242738347108">"የደዋይ መታወቂያ አልተቀናበረም"</string> + <string name="set_call_active" msgid="3365404393507589899">"ወደ ገቢር ተቀናብሯል"</string> + <string name="answer" msgid="5423590397665409939">"መልስ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"ወደ ገቢር ያልሆነ ተቀናብሯል"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ግንኙነትን ያቋርጡ"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ማዳመጫ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ድምፅ ማውጫ"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ብሉቱዝ"</string> + <string name="start_stream" msgid="3567634786280097431">"ዥረት ይጀምሩ"</string> + <string name="crash_app" msgid="2548690390730057704">"ለየት ያለ ነገርን ይጣሉ"</string> + <string name="update_notification" msgid="8677916482672588779">"በመካሄድ ላይ ላለ ጥሪ ቅጥ ማሳወቂያ ያዘምኑ"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ar/strings.xml b/testapps/transactionalVoipApp/res/values-ar/strings.xml index e6c7e6f0a..d2c146491 100644 --- a/testapps/transactionalVoipApp/res/values-ar/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ar/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"نشاط اختبار واجهة برمجة التطبيقات من خلال المعاملات"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"نشاط المعاملات أثناء المكالمة"</string> <string name="register_phone_account" msgid="1920315963082350332">"تسجيل حساب الهاتف"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"بدء FGS (محاكاة الترجمة الآلية + التطبيق في الخلفية)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"بدء مكالمة صادرة"</string> + <string name="start_incoming" msgid="6444983300186361271">"بدء مكالمة واردة"</string> + <string name="get_call_id" msgid="5513943242738347108">"لم يتم ضبط رقم تعريف المكالمة"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"الإجابة"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"إلغاء الربط"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"سماعة الأذن"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"مكبّر الصوت"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"البلوتوث"</string> + <string name="start_stream" msgid="3567634786280097431">"بدء البث"</string> + <string name="crash_app" msgid="2548690390730057704">"طرح استثناء"</string> + <string name="update_notification" msgid="8677916482672588779">"إشعار التعديل إلى نمط المكالمات الجارية"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-as/strings.xml b/testapps/transactionalVoipApp/res/values-as/strings.xml index 995624a6c..c48ac0e6c 100644 --- a/testapps/transactionalVoipApp/res/values-as/strings.xml +++ b/testapps/transactionalVoipApp/res/values-as/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"লেনদেন সম্বন্ধীয় API পৰীক্ষণৰ কাৰ্যকলাপ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"কলত হোৱা লেনদেন সম্বন্ধীয় কাৰ্যকলাপ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ফ\'নৰ একাউণ্ট পঞ্জীয়ন কৰক"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS আৰম্ভ কৰক (নেপথ্যত MT + এপ্ ছিমুলে’ট কৰক)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"বহিৰ্গামী কল আৰম্ভ কৰক"</string> + <string name="start_incoming" msgid="6444983300186361271">"অন্তৰ্গামী কল আৰম্ভ কৰক"</string> + <string name="get_call_id" msgid="5513943242738347108">"কলৰ আইডিটো ছেট কৰা হোৱা নাই"</string> + <string name="set_call_active" msgid="3365404393507589899">"সক্ৰিয় হিচাপে ছেট কৰক"</string> + <string name="answer" msgid="5423590397665409939">"উত্তৰ দিয়ক"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"নিষ্ক্ৰিয় হিচাপে ছেট কৰক"</string> + <string name="disconnect_call" msgid="1349412380315371385">"সংযোগ বিচ্ছিন্ন কৰক"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ইয়েৰপিচ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"স্পীকাৰ"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ব্লুটুথ"</string> + <string name="start_stream" msgid="3567634786280097431">"ষ্ট্ৰীম কৰিবলৈ আৰম্ভ কৰক"</string> + <string name="crash_app" msgid="2548690390730057704">"থ্ৰ’ এক্সচেপশ্বন"</string> + <string name="update_notification" msgid="8677916482672588779">"চলিত কলৰ শৈলী সম্পৰ্কে আপডে’ট দিয়া জাননী"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-az/strings.xml b/testapps/transactionalVoipApp/res/values-az/strings.xml index db37f1b00..75d82784d 100644 --- a/testapps/transactionalVoipApp/res/values-az/strings.xml +++ b/testapps/transactionalVoipApp/res/values-az/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Tranzaksiya ilə bağlı API test Fəaliyyəti"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Tranzaksiya üzrə Zəngdaxili Fəaliyyət"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefon Hesabını Qeydiyyatdan Keçirin"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS-ni başladın (arxa fonda MT + tətbiqini simulyasiya edin)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Gedən zəng başladın"</string> + <string name="start_incoming" msgid="6444983300186361271">"Gələn zəng başladın"</string> + <string name="get_call_id" msgid="5513943242738347108">"zəng ID-si təyin olunmayıb"</string> + <string name="set_call_active" msgid="3365404393507589899">"Aktiv kimi təyin edin"</string> + <string name="answer" msgid="5423590397665409939">"cavab"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Qeyri-aktiv kimi təyin edin"</string> + <string name="disconnect_call" msgid="1349412380315371385">"əlaqəni kəsin"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Qulaqlıq"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Dinamik"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"yayıma başlayın"</string> + <string name="crash_app" msgid="2548690390730057704">"istisna yaradın"</string> + <string name="update_notification" msgid="8677916482672588779">"bildirişi davam edən zəng üslubuna yeniləyin"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml b/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml index 9b02b9e2d..f82491064 100644 --- a/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml +++ b/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktivnost testiranja transakcionog API-ja"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Aktivnost poziva u vezi sa transakcijama"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registruj nalog telefona"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Pokreni FGS (simulirajte MT + aplikaciju u pozadini)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Započnite odlazni poziv"</string> + <string name="start_incoming" msgid="6444983300186361271">"Započnite dolazni poziv"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID poziva nije podešen"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"odgovori"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"prekini vezu"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Slušalica"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"počnite da strimujete"</string> + <string name="crash_app" msgid="2548690390730057704">"izbaciti izuzetak"</string> + <string name="update_notification" msgid="8677916482672588779">"ažurirajte obaveštenje na stil aktuelnog poziva"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-be/strings.xml b/testapps/transactionalVoipApp/res/values-be/strings.xml index 81b06d2ef..36d558ecf 100644 --- a/testapps/transactionalVoipApp/res/values-be/strings.xml +++ b/testapps/transactionalVoipApp/res/values-be/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Праверачныя дзеянні API трансакцый"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Дзеянні падчас выклікаў"</string> <string name="register_phone_account" msgid="1920315963082350332">"Зарэгістраваць уліковы запіс тэлефона"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Запусціць FGS (сімуляцыя MT + праграма ў фонавым рэжыме)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Пачаць выходны выклік"</string> + <string name="start_incoming" msgid="6444983300186361271">"Пачаць уваходны выклік"</string> + <string name="get_call_id" msgid="5513943242738347108">"ідэнтыфікатар выкліку не зададзены"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"адказаць"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"завяршыць выклік"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Навушнік"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Дынамік"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"пачаць перадачу плынню"</string> + <string name="crash_app" msgid="2548690390730057704">"адправіць паведамленне аб выключэнні"</string> + <string name="update_notification" msgid="8677916482672588779">"стыль паведамлення аб абнаўленні для бягучага званка"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-bg/strings.xml b/testapps/transactionalVoipApp/res/values-bg/strings.xml index 283fc249f..2210400a8 100644 --- a/testapps/transactionalVoipApp/res/values-bg/strings.xml +++ b/testapps/transactionalVoipApp/res/values-bg/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Активност за тестване на API за транзакции"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Транзакционална активност в обаждане"</string> <string name="register_phone_account" msgid="1920315963082350332">"Регистриране на профила на телефона"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Стартиране на FGS (симулиране на MT + приложението на заден план)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Започване на изходящо обаждане"</string> + <string name="start_incoming" msgid="6444983300186361271">"Започване на входящо обаждане"</string> + <string name="get_call_id" msgid="5513943242738347108">"идентификаторът на обаждането не е зададен"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"отговаряне"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"прекратяване на връзката"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Слушалка"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Високоговорител"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"започване на поточно предаване"</string> + <string name="crash_app" msgid="2548690390730057704">"генериране на изключение"</string> + <string name="update_notification" msgid="8677916482672588779">"актуализиране на известието до стила на текущото обаждане"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-bn/strings.xml b/testapps/transactionalVoipApp/res/values-bn/strings.xml index c4266d0eb..45f13be68 100644 --- a/testapps/transactionalVoipApp/res/values-bn/strings.xml +++ b/testapps/transactionalVoipApp/res/values-bn/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API টেস্ট সংক্রান্ত অ্যাক্টিভিটি"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"কল অ্যাক্টিভিটিতে হওয়া ট্রানজ্যাকশন"</string> <string name="register_phone_account" msgid="1920315963082350332">"ফোনের অ্যাকাউন্ট রেজিস্টার করুন"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS শুরু করুন (সিমুলেট MT + ব্যাকগ্রাউন্ডে থাকা অ্যাপ)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"আউটগোয়িং কল শুরু করুন"</string> + <string name="start_incoming" msgid="6444983300186361271">"ইনকামিং কল শুরু করুন"</string> + <string name="get_call_id" msgid="5513943242738347108">"কলার আইডি সেট করা নেই"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"উত্তর দিন"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ডিসকানেক্ট করুন"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ইয়ারপিস"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"স্পিকার"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ব্লুটুথ"</string> + <string name="start_stream" msgid="3567634786280097431">"স্ট্রিমিং শুরু করুন"</string> + <string name="crash_app" msgid="2548690390730057704">"এক্সেপশন যোগ করুন"</string> + <string name="update_notification" msgid="8677916482672588779">"চালু থাকা কলের স্টাইলে আপডেট সংক্রান্ত বিজ্ঞপ্তি"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-bs/strings.xml b/testapps/transactionalVoipApp/res/values-bs/strings.xml index f9939300b..24ffba2d3 100644 --- a/testapps/transactionalVoipApp/res/values-bs/strings.xml +++ b/testapps/transactionalVoipApp/res/values-bs/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktivnost testa transakcijskog API-ja"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transakcijska aktivnost u pozivu"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrirajte račun telefona"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Pokreni FGS (simuliraj MT i aplikaciju u pozadini)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Pokreni odlazni poziv"</string> + <string name="start_incoming" msgid="6444983300186361271">"Pokreni dolazni poziv"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID poziva nije postavljen"</string> + <string name="set_call_active" msgid="3365404393507589899">"postavi na Aktivno"</string> + <string name="answer" msgid="5423590397665409939">"odgovori"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"postavi na Neaktivno"</string> + <string name="disconnect_call" msgid="1349412380315371385">"prekini vezu"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Slušalica"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"pokreni prijenos"</string> + <string name="crash_app" msgid="2548690390730057704">"izbaci izuzetak"</string> + <string name="update_notification" msgid="8677916482672588779">"ažuriraj obavještenje u stil poziva u toku"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ca/strings.xml b/testapps/transactionalVoipApp/res/values-ca/strings.xml index 37561c878..550044425 100644 --- a/testapps/transactionalVoipApp/res/values-ca/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ca/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Activitat de prova de l\'API transaccional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Activitat de transaccions durant la trucada"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registra el compte del telèfon"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Inicia FGS (simula MT + aplicació en segon pla)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Inicia una trucada sortint"</string> + <string name="start_incoming" msgid="6444983300186361271">"Inicia una trucada entrant"</string> + <string name="get_call_id" msgid="5513943242738347108">"identificador de trucada no definit"</string> + <string name="set_call_active" msgid="3365404393507589899">"defineix com a activa"</string> + <string name="answer" msgid="5423590397665409939">"respon"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"defineix com a inactiva"</string> + <string name="disconnect_call" msgid="1349412380315371385">"desconnecta"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auricular"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altaveu"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"inicia la reproducció en línia"</string> + <string name="crash_app" msgid="2548690390730057704">"llança una excepció"</string> + <string name="update_notification" msgid="8677916482672588779">"actualitza la notificació a l\'estil de trucada en curs"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-cs/strings.xml b/testapps/transactionalVoipApp/res/values-cs/strings.xml index 189a8460b..66327650f 100644 --- a/testapps/transactionalVoipApp/res/values-cs/strings.xml +++ b/testapps/transactionalVoipApp/res/values-cs/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktivita testování v transakčním rozhraní API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transakční aktivita během hovoru"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrovat telefonní účet"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Spustit službu v popředí (simulovat MT a aplikaci v pozadí)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Zahájit odchozí hovor"</string> + <string name="start_incoming" msgid="6444983300186361271">"Zahájit příchozí hovor"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID hovoru není nastaveno"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"odpověď"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"odpojit"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Sluchátko"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Reproduktor"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"zahájit streamování"</string> + <string name="crash_app" msgid="2548690390730057704">"vyvolat výjimku"</string> + <string name="update_notification" msgid="8677916482672588779">"styl aktualizace oznámení o probíhajícím hovoru"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-da/strings.xml b/testapps/transactionalVoipApp/res/values-da/strings.xml index c7f9be48e..1a23b5838 100644 --- a/testapps/transactionalVoipApp/res/values-da/strings.xml +++ b/testapps/transactionalVoipApp/res/values-da/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Testaktivitet for transaktions-API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaktionsrelateret aktivitet i opkald"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrer telefonkonto"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Start FGS (simuler maskinoversættelse + app i baggrunden)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Start udgående opkald"</string> + <string name="start_incoming" msgid="6444983300186361271">"Start indgående opkald"</string> + <string name="get_call_id" msgid="5513943242738347108">"opkalds-id ikke konfigureret"</string> + <string name="set_call_active" msgid="3365404393507589899">"Indstil som aktiv"</string> + <string name="answer" msgid="5423590397665409939">"svar"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Indstil som inaktiv"</string> + <string name="disconnect_call" msgid="1349412380315371385">"afslut opkald"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Højttaler"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Højttaler"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"start med at streame"</string> + <string name="crash_app" msgid="2548690390730057704">"udløs en undtagelse"</string> + <string name="update_notification" msgid="8677916482672588779">"opdateringsnotifikation til igangværende opkaldsstil"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-de/strings.xml b/testapps/transactionalVoipApp/res/values-de/strings.xml index f7719b931..4f853fcac 100644 --- a/testapps/transactionalVoipApp/res/values-de/strings.xml +++ b/testapps/transactionalVoipApp/res/values-de/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Testaktivität zur transaktionalen API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaktionsaktivität bei aktiven Anruf"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefonkonto registrieren"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS starten (MT und App im Hintergrund simulieren)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Ausgehenden Anruf starten"</string> + <string name="start_incoming" msgid="6444983300186361271">"Eingehenden Anruf starten"</string> + <string name="get_call_id" msgid="5513943242738347108">"Anrufer-ID nicht festgelegt"</string> + <string name="set_call_active" msgid="3365404393507589899">"aktiv"</string> + <string name="answer" msgid="5423590397665409939">"annehmen"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"inaktiv"</string> + <string name="disconnect_call" msgid="1349412380315371385">"beenden"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Kopfhörer"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Lautsprecher"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Streaming starten"</string> + <string name="crash_app" msgid="2548690390730057704">"Ausnahme auslösen"</string> + <string name="update_notification" msgid="8677916482672588779">"Benachrichtigung zum Stil des laufenden Anrufs aktualisieren"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-el/strings.xml b/testapps/transactionalVoipApp/res/values-el/strings.xml index 7c836008d..555398199 100644 --- a/testapps/transactionalVoipApp/res/values-el/strings.xml +++ b/testapps/transactionalVoipApp/res/values-el/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Δοκιμαστική δραστηριότητα API συναλλαγών"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Δραστηριότητα συναλλαγής στην κλήση"</string> <string name="register_phone_account" msgid="1920315963082350332">"Εγγραφή λογαριασμού τηλεφώνου"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Έναρξη FGS (προσομοίωση MT + εφαρμογή στο παρασκήνιο)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Έναρξη εξερχόμενης κλήσης"</string> + <string name="start_incoming" msgid="6444983300186361271">"Έναρξη εισερχόμενης κλήσης"</string> + <string name="get_call_id" msgid="5513943242738347108">"δεν έχει οριστεί αναγνωριστικό κλήσης"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"απάντηση"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"αποσύνδεση"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Ακουστικό τηλεφώνου"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Ηχείο"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"έναρξη ροής"</string> + <string name="crash_app" msgid="2548690390730057704">"εμφάνιση εξαίρεσης"</string> + <string name="update_notification" msgid="8677916482672588779">"ενημέρωση ειδοποίησης στο στιλ κλήσης σε εξέλιξη"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml b/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml index abf46115f..bf68cf535 100644 --- a/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml +++ b/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API test activity"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transactional in-call activity"</string> <string name="register_phone_account" msgid="1920315963082350332">"Register phone account"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Start FGS (simulate MT + app in background)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Start outgoing call"</string> + <string name="start_incoming" msgid="6444983300186361271">"Start incoming call"</string> + <string name="get_call_id" msgid="5513943242738347108">"call ID not set"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"answer"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"disconnect"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Earpiece"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"start streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"Update notification to ongoing call style"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml b/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml index 101400127..269f0d3ff 100644 --- a/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml +++ b/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml @@ -32,4 +32,6 @@ <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> <string name="start_stream" msgid="3567634786280097431">"start streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"update notification to ongoing call style"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml b/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml index abf46115f..bf68cf535 100644 --- a/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml +++ b/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API test activity"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transactional in-call activity"</string> <string name="register_phone_account" msgid="1920315963082350332">"Register phone account"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Start FGS (simulate MT + app in background)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Start outgoing call"</string> + <string name="start_incoming" msgid="6444983300186361271">"Start incoming call"</string> + <string name="get_call_id" msgid="5513943242738347108">"call ID not set"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"answer"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"disconnect"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Earpiece"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"start streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"Update notification to ongoing call style"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml b/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml index abf46115f..bf68cf535 100644 --- a/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml +++ b/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API test activity"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transactional in-call activity"</string> <string name="register_phone_account" msgid="1920315963082350332">"Register phone account"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Start FGS (simulate MT + app in background)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Start outgoing call"</string> + <string name="start_incoming" msgid="6444983300186361271">"Start incoming call"</string> + <string name="get_call_id" msgid="5513943242738347108">"call ID not set"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"answer"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"disconnect"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Earpiece"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"start streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"Update notification to ongoing call style"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml b/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml index 40b001681..d94683ace 100644 --- a/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml +++ b/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml @@ -32,4 +32,6 @@ <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> <string name="start_stream" msgid="3567634786280097431">"start streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"update notification to ongoing call style"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml b/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml index 588150c40..da554d148 100644 --- a/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml +++ b/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Actividad de prueba de la API transaccional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Actividad transaccional en las llamadas"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrar cuenta telefónica"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Iniciar FGS (simulación de TA y app en segundo plano)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Iniciar llamada saliente"</string> + <string name="start_incoming" msgid="6444983300186361271">"Iniciar llamada entrante"</string> + <string name="get_call_id" msgid="5513943242738347108">"no se estableció el identificador de llamadas"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"responder"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"desconectar"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auricular"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Bocina"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Iniciar transmisión"</string> + <string name="crash_app" msgid="2548690390730057704">"generación de excepción"</string> + <string name="update_notification" msgid="8677916482672588779">"notificación de actualización del estilo de llamada en curso"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-es/strings.xml b/testapps/transactionalVoipApp/res/values-es/strings.xml index 0e290aed8..b3f2919b9 100644 --- a/testapps/transactionalVoipApp/res/values-es/strings.xml +++ b/testapps/transactionalVoipApp/res/values-es/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Actividad de prueba de API transaccional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Actividad transaccional durante la llamada"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrar cuenta de teléfono"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Iniciar FGS (simular MT + aplicación en segundo plano)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Iniciar llamada saliente"</string> + <string name="start_incoming" msgid="6444983300186361271">"Iniciar llamada entrante"</string> + <string name="get_call_id" msgid="5513943242738347108">"identificador de llamada no definido"</string> + <string name="set_call_active" msgid="3365404393507589899">"Activar"</string> + <string name="answer" msgid="5423590397665409939">"responder"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Desactivar"</string> + <string name="disconnect_call" msgid="1349412380315371385">"desconectar"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auricular"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altavoz"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"iniciar emisión"</string> + <string name="crash_app" msgid="2548690390730057704">"excepción de expresión \"throw\""</string> + <string name="update_notification" msgid="8677916482672588779">"actualizar notificación al estilo de llamada en curso"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-et/strings.xml b/testapps/transactionalVoipApp/res/values-et/strings.xml index d9e9f9705..4cc5aabd6 100644 --- a/testapps/transactionalVoipApp/res/values-et/strings.xml +++ b/testapps/transactionalVoipApp/res/values-et/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Tehingupõhise API testimise tegevus"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Kõnesisene toimingutegevus"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefonikonto registreerimine"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Käivita FGS (simuleeri taustal MT-d ja rakendust)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Alusta väljuvat kõnet"</string> + <string name="start_incoming" msgid="6444983300186361271">"Alusta sissetulevat kõnet"</string> + <string name="get_call_id" msgid="5513943242738347108">"helistaja ID pole seadistatud"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"vastus"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"katkesta ühendus"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Kuular"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Kõlar"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"käivita voogesitus"</string> + <string name="crash_app" msgid="2548690390730057704">"erandi viskamine"</string> + <string name="update_notification" msgid="8677916482672588779">"värskendage märguannet käimasoleva kõne stiilis"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-eu/strings.xml b/testapps/transactionalVoipApp/res/values-eu/strings.xml index 379065e63..8b3a1814b 100644 --- a/testapps/transactionalVoipApp/res/values-eu/strings.xml +++ b/testapps/transactionalVoipApp/res/values-eu/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transakzio bidezko APIen proba-jarduerak"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Deiko transakzio-jarduerak"</string> <string name="register_phone_account" msgid="1920315963082350332">"Erregistratu telefonoaren kontua"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Hasi FGS (simulatu itzulpen automatikoa + aplikazioa atzeko planoan)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Hasi irteerako dei bat simulatzen"</string> + <string name="start_incoming" msgid="6444983300186361271">"Hasi sarrerako dei bat simulatzen"</string> + <string name="get_call_id" msgid="5513943242738347108">"ez da ezarri deiaren identifikatzailea"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"erantzun"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"deskonektatu"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Aurikularrak"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Bozgorailua"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetootha"</string> + <string name="start_stream" msgid="3567634786280097431">"hasi zuzenean igortzen"</string> + <string name="crash_app" msgid="2548690390730057704">"eman salbuespena"</string> + <string name="update_notification" msgid="8677916482672588779">"eguneratu jakinarazpena, abian den deiaren estiloarekin bat etor dadin"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-fa/strings.xml b/testapps/transactionalVoipApp/res/values-fa/strings.xml index eb7b88e3c..88143cb5f 100644 --- a/testapps/transactionalVoipApp/res/values-fa/strings.xml +++ b/testapps/transactionalVoipApp/res/values-fa/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"فعالیت آزمایشی Transactional API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"تبادلی در فعالیت تماس"</string> <string name="register_phone_account" msgid="1920315963082350332">"ثبت حساب تلفن"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"شروع FGS (شبیهسازی ترجمه ماشینی + برنامه در پسزمینه)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"شروع تماس خروجی"</string> + <string name="start_incoming" msgid="6444983300186361271">"شروع تماس ورودی"</string> + <string name="get_call_id" msgid="5513943242738347108">"شناسه تماس تنظیم نشده است"</string> + <string name="set_call_active" msgid="3365404393507589899">"تنظیم بهعنوان فعال"</string> + <string name="answer" msgid="5423590397665409939">"پاسخ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"تنظیم بهعنوان غیرفعال"</string> + <string name="disconnect_call" msgid="1349412380315371385">"قطع ارتباط"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"گوشی"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"بلندگو"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"بلوتوث"</string> + <string name="start_stream" msgid="3567634786280097431">"شروع جاریسازی"</string> + <string name="crash_app" msgid="2548690390730057704">"استثنا قائل شدن"</string> + <string name="update_notification" msgid="8677916482672588779">"بهروزرسانی اعلان بهسبک تماس درحال انجام"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-fi/strings.xml b/testapps/transactionalVoipApp/res/values-fi/strings.xml index d64dbe21e..673d56dba 100644 --- a/testapps/transactionalVoipApp/res/values-fi/strings.xml +++ b/testapps/transactionalVoipApp/res/values-fi/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Tapahtuman API-testitoiminta"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Tapahtuman puhelunaikainen toiminta"</string> <string name="register_phone_account" msgid="1920315963082350332">"Rekisteröi puhelintili"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Käynnistä FGS (simuloi MT + sovellus taustalla)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Aloita lähtevä puhelu"</string> + <string name="start_incoming" msgid="6444983300186361271">"Aloita saapuva puhelu"</string> + <string name="get_call_id" msgid="5513943242738347108">"soittajan tunnusta ei asetettu"</string> + <string name="set_call_active" msgid="3365404393507589899">"aseta aktiiviseksi"</string> + <string name="answer" msgid="5423590397665409939">"vastaa"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"aseta ei-aktiiviseksi"</string> + <string name="disconnect_call" msgid="1349412380315371385">"katkaise yhteys"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Kaiutin"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Kaiutin"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"aloita suoratoisto"</string> + <string name="crash_app" msgid="2548690390730057704">"lähetyspoikkeus"</string> + <string name="update_notification" msgid="8677916482672588779">"päivitä ilmoitus käynnissä olevan puhelun tyyliin"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml b/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml index 173fc888b..d58aa1395 100644 --- a/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml +++ b/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Activité de test de l\'API transactionnelle"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Activité transactionnelle durant l\'appel"</string> <string name="register_phone_account" msgid="1920315963082350332">"Inscrire un compte téléphonique"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Démarrer FGS (simuler TA + application en arrière-plan)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Démarrer un appel sortant"</string> + <string name="start_incoming" msgid="6444983300186361271">"Démarrer un appel entrant"</string> + <string name="get_call_id" msgid="5513943242738347108">"identifiant de l\'appel non défini"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"répondre"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"déconnecter"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Écouteur"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Haut-parleur"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"démarrer une diffusion"</string> + <string name="crash_app" msgid="2548690390730057704">"générer une exception"</string> + <string name="update_notification" msgid="8677916482672588779">"modifier la notification en fonction du style de l\'appel en cours"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-fr/strings.xml b/testapps/transactionalVoipApp/res/values-fr/strings.xml index 8fcbe7dc6..780b8e8c5 100644 --- a/testapps/transactionalVoipApp/res/values-fr/strings.xml +++ b/testapps/transactionalVoipApp/res/values-fr/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Activité de test de l\'API transactionnelle"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Activité transactionnelle en cours d\'appel"</string> <string name="register_phone_account" msgid="1920315963082350332">"Enregistrer un compte de téléphonie"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Démarrer les services de premier plan (simuler la MT + l\'application en arrière-plan)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Démarrer un appel sortant"</string> + <string name="start_incoming" msgid="6444983300186361271">"Démarrer un appel entrant"</string> + <string name="get_call_id" msgid="5513943242738347108">"affichage du numéro de l\'appelant non défini"</string> + <string name="set_call_active" msgid="3365404393507589899">"Définir comme actif"</string> + <string name="answer" msgid="5423590397665409939">"réponse"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Définir comme inactif"</string> + <string name="disconnect_call" msgid="1349412380315371385">"raccrocher"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Écouteur"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Haut-parleur"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"démarrer la diffusion"</string> + <string name="crash_app" msgid="2548690390730057704">"générer une exception"</string> + <string name="update_notification" msgid="8677916482672588779">"modifier la notification en fonction du style de l\'appel en cours"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-gl/strings.xml b/testapps/transactionalVoipApp/res/values-gl/strings.xml index 9f98e24bb..f168ab26a 100644 --- a/testapps/transactionalVoipApp/res/values-gl/strings.xml +++ b/testapps/transactionalVoipApp/res/values-gl/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Actividade de proba da API transaccional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Actividade transaccional nas chamadas"</string> <string name="register_phone_account" msgid="1920315963082350332">"Rexistrar conta do teléfono"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Iniciar FGS (simular MT + aplicación en segundo plano)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Iniciar chamada saínte"</string> + <string name="start_incoming" msgid="6444983300186361271">"Iniciar chamada entrante"</string> + <string name="get_call_id" msgid="5513943242738347108">"identificador de chamada non definido"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"responder"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"desconectar"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auricular"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altofalante"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"iniciar reprodución en tempo real"</string> + <string name="crash_app" msgid="2548690390730057704">"activar excepción"</string> + <string name="update_notification" msgid="8677916482672588779">"actualiza a notificación en función do estilo da chamada en curso"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-gu/strings.xml b/testapps/transactionalVoipApp/res/values-gu/strings.xml index d1db7a1f7..60bb0b76f 100644 --- a/testapps/transactionalVoipApp/res/values-gu/strings.xml +++ b/testapps/transactionalVoipApp/res/values-gu/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional APIના પરીક્ષણની પ્રવૃત્તિ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"કૉલમાંની વ્યવહારિક પ્રવૃત્તિ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ફોન એકાઉન્ટ રજિસ્ટર કરો"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS (MT સિમ્યુલેટ કરવું + બૅકગ્રાઉન્ડમાં ઍપ) શરૂ કરો"</string> + <string name="start_outgoing" msgid="1441644037370361864">"આઉટગોઇંગ કૉલ શરૂ કરો"</string> + <string name="start_incoming" msgid="6444983300186361271">"ઇનકમિંગ કૉલ શરૂ કરો"</string> + <string name="get_call_id" msgid="5513943242738347108">"કૉલર ID સેટ કરેલું નથી"</string> + <string name="set_call_active" msgid="3365404393507589899">"સક્રિય તરીકે સેટ કરો"</string> + <string name="answer" msgid="5423590397665409939">"જવાબ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"નિષ્ક્રિય તરીકે સેટ કરો"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ડિસ્કનેક્ટ કરો"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ઇયરપીસ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"સ્પીકર"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"બ્લૂટૂથ"</string> + <string name="start_stream" msgid="3567634786280097431">"સ્ટ્રીમિંગ શરૂ કરો"</string> + <string name="crash_app" msgid="2548690390730057704">"અપવાદ થ્રો કરો"</string> + <string name="update_notification" msgid="8677916482672588779">"ચાલુ કૉલ શૈલી પર નોટિફિકેશન અપડેટ કરો"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-hi/strings.xml b/testapps/transactionalVoipApp/res/values-hi/strings.xml index c6c2efbf0..ba4262aa0 100644 --- a/testapps/transactionalVoipApp/res/values-hi/strings.xml +++ b/testapps/transactionalVoipApp/res/values-hi/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API से जुड़ी टेस्ट गतिविधि"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"कॉल में क्लाइंट और सर्वर के बीच हुई बातचीत से जुड़ी गतिविधि"</string> <string name="register_phone_account" msgid="1920315963082350332">"Phone Account में रजिस्टर करें"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS शुरू करें (बैकग्राउंड में MT + ऐप्लिकेशन को सिम्युलेट करें)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"आउटगोइंग कॉल शुरू करें"</string> + <string name="start_incoming" msgid="6444983300186361271">"इनकमिंग कॉल शुरू करें"</string> + <string name="get_call_id" msgid="5513943242738347108">"कॉल आईडी सेट नहीं है"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"जवाब"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"डिसकनेक्ट करें"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ईयरपीस"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"स्पीकर"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ब्लूटूथ"</string> + <string name="start_stream" msgid="3567634786280097431">"स्ट्रीमिंग शुरू करें"</string> + <string name="crash_app" msgid="2548690390730057704">"अपवाद जोड़ें"</string> + <string name="update_notification" msgid="8677916482672588779">"मौजूदा कॉल की स्टाइल के हिसाब से सूचनाओं को अपडेट करें"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-hr/strings.xml b/testapps/transactionalVoipApp/res/values-hr/strings.xml index de2e01da8..c324f6db7 100644 --- a/testapps/transactionalVoipApp/res/values-hr/strings.xml +++ b/testapps/transactionalVoipApp/res/values-hr/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Testna aktivnost API-ja za transakcije"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"transakcijska aktivnost u pozivu"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registracija telefonskog računa"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Pokretanje FGS-a (simulacija: MT i aplikacija u pozadini)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Pokretanje odlaznog poziva"</string> + <string name="start_incoming" msgid="6444983300186361271">"Pokretanje dolaznog poziva"</string> + <string name="get_call_id" msgid="5513943242738347108">"id poziva nije postavljen"</string> + <string name="set_call_active" msgid="3365404393507589899">"Postavljanje kao aktivno"</string> + <string name="answer" msgid="5423590397665409939">"odgovor"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Postavljanje kao neaktivno"</string> + <string name="disconnect_call" msgid="1349412380315371385">"prekid veze"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Slušalica"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"pokretanje streaminga"</string> + <string name="crash_app" msgid="2548690390730057704">"izbacivanje iznimke"</string> + <string name="update_notification" msgid="8677916482672588779">"ažuriranje obavijesti u stil poziva u tijeku"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-hu/strings.xml b/testapps/transactionalVoipApp/res/values-hu/strings.xml index 8b3b1bd97..205404e75 100644 --- a/testapps/transactionalVoipApp/res/values-hu/strings.xml +++ b/testapps/transactionalVoipApp/res/values-hu/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Tranzakciós API-teszttevékenység"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Hívás közbeni tranzakciós tevékenység"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefonáláshoz használt fiók regisztrálása"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Előtérben futó szolgáltatás indítása (gépi fordítás + alkalmazás szimulálása a háttérben)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Kimenő hívás indítása"</string> + <string name="start_incoming" msgid="6444983300186361271">"Bejövő hívás indítása"</string> + <string name="get_call_id" msgid="5513943242738347108">"nincs beállítva hívásazonosító"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"válasz"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"leválasztás"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Fülhallgató"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Hangszóró"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"streamelés indítása"</string> + <string name="crash_app" msgid="2548690390730057704">"kivétel dobása"</string> + <string name="update_notification" msgid="8677916482672588779">"értesítés frissítése a folyamatban lévő hívás stílusára"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-hy/strings.xml b/testapps/transactionalVoipApp/res/values-hy/strings.xml index 9d19ce155..85e6ae589 100644 --- a/testapps/transactionalVoipApp/res/values-hy/strings.xml +++ b/testapps/transactionalVoipApp/res/values-hy/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Գործարքային API-ների փորձարկման գործողություն"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Գործարքներ զանգի ժամանակ"</string> <string name="register_phone_account" msgid="1920315963082350332">"Հեռախոսի հաշվի գրանցում"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Գործարկել FGS-ը (ՄԹ-ի սիմուլացիա + հավելված ֆոնային ռեժիմում)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Սկսել ելքային զանգ"</string> + <string name="start_incoming" msgid="6444983300186361271">"Սկսել մուտքային զանգ"</string> + <string name="get_call_id" msgid="5513943242738347108">"զանգի նույնացուցիչ սահմանված չէ"</string> + <string name="set_call_active" msgid="3365404393507589899">"ակտիվացնել"</string> + <string name="answer" msgid="5423590397665409939">"պատասխանել"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"ապակտիվացնել"</string> + <string name="disconnect_call" msgid="1349412380315371385">"անջատել"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Լսափող"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Բարձրախոս"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"սկսել հեռարձակում"</string> + <string name="crash_app" msgid="2548690390730057704">"ուղարկել հաղորդագրություն բացառության մասին"</string> + <string name="update_notification" msgid="8677916482672588779">"ծանուցում ընթացիկ զանգի ոճի մասին"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-in/strings.xml b/testapps/transactionalVoipApp/res/values-in/strings.xml index 3ab9c6fe5..935f03617 100644 --- a/testapps/transactionalVoipApp/res/values-in/strings.xml +++ b/testapps/transactionalVoipApp/res/values-in/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktivitas pengujian API Transaksional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Aktivitas Transaksi Dalam Panggilan"</string> <string name="register_phone_account" msgid="1920315963082350332">"Daftarkan Akun Ponsel"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Mulai FGS (simulasikan MT + aplikasi di latar belakang)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Mulai Panggilan Keluar"</string> + <string name="start_incoming" msgid="6444983300186361271">"Mulai Panggilan Masuk"</string> + <string name="get_call_id" msgid="5513943242738347108">"id panggilan tidak ditetapkan"</string> + <string name="set_call_active" msgid="3365404393507589899">"setelAktif"</string> + <string name="answer" msgid="5423590397665409939">"jawab"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setelNonaktif"</string> + <string name="disconnect_call" msgid="1349412380315371385">"putuskan koneksi"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Earpiece"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"mulai streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"tampilkan pengecualian"</string> + <string name="update_notification" msgid="8677916482672588779">"perbarui notifikasi ke gaya panggilan yang sedang berlangsung"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-is/strings.xml b/testapps/transactionalVoipApp/res/values-is/strings.xml index 18c115db0..c0bcd2388 100644 --- a/testapps/transactionalVoipApp/res/values-is/strings.xml +++ b/testapps/transactionalVoipApp/res/values-is/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Prófun á virkni forritaskila færslna"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Virkni í símtali"</string> <string name="register_phone_account" msgid="1920315963082350332">"Skrá símareikning"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Ræsa FGS (líkja eftir MT + forriti í bakgrunni)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Hefja hringt símtal"</string> + <string name="start_incoming" msgid="6444983300186361271">"Hefja símtal sem berst"</string> + <string name="get_call_id" msgid="5513943242738347108">"númerabirting ekki stillt"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"svara"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"aftengja"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Eyrnatól"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Hátalari"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"hefja streymi"</string> + <string name="crash_app" msgid="2548690390730057704">"nota undantekningu"</string> + <string name="update_notification" msgid="8677916482672588779">"uppfæra tilkynningu í stíl símtals sem stendur yfir"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-it/strings.xml b/testapps/transactionalVoipApp/res/values-it/strings.xml index be0f1ec2b..36a2816bd 100644 --- a/testapps/transactionalVoipApp/res/values-it/strings.xml +++ b/testapps/transactionalVoipApp/res/values-it/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Attività di test dell\'API transazionale"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Attività di transazione durante la chiamata"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registra account telefono"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Avvia FGS (simulazione di MT + app in background)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Avvia chiamata in uscita"</string> + <string name="start_incoming" msgid="6444983300186361271">"Avvia chiamata in arrivo"</string> + <string name="get_call_id" msgid="5513943242738347108">"id chiamata non impostato"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"risposta"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"disconnetti"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auricolare"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altoparlante"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"avvia streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"genera eccezione"</string> + <string name="update_notification" msgid="8677916482672588779">"aggiorna la notifica allo stile di chiamata in corso"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-iw/strings.xml b/testapps/transactionalVoipApp/res/values-iw/strings.xml index 87d8cba1d..3accc06d8 100644 --- a/testapps/transactionalVoipApp/res/values-iw/strings.xml +++ b/testapps/transactionalVoipApp/res/values-iw/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API test Activity"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"בר ביצוע בפעילות השיחה"</string> <string name="register_phone_account" msgid="1920315963082350332">"רישום חשבון הטלפון"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"הפעלת FGS (סימולציה של MT + אפליקציה ברקע)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"התחלת שיחה יוצאת"</string> + <string name="start_incoming" msgid="6444983300186361271">"התחלת שיחה נכנסת"</string> + <string name="get_call_id" msgid="5513943242738347108">"מזהה השיחה לא הוגדר"</string> + <string name="set_call_active" msgid="3365404393507589899">"הגדרה כפעיל"</string> + <string name="answer" msgid="5423590397665409939">"תשובה"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"הגדרה כלא פעיל"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ניתוק"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"אוזניה"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"רמקול"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"התחלת השידור"</string> + <string name="crash_app" msgid="2548690390730057704">"חריגה להקפצה של הודעת שגיאה"</string> + <string name="update_notification" msgid="8677916482672588779">"עדכון ההתראה לסגנון של שיחה רציפה"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ja/strings.xml b/testapps/transactionalVoipApp/res/values-ja/strings.xml index a92473166..faaede609 100644 --- a/testapps/transactionalVoipApp/res/values-ja/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ja/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API テスト アクティビティ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transactional 通話アクティビティ"</string> <string name="register_phone_account" msgid="1920315963082350332">"スマートフォン アカウントを登録"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS を開始(MT + アプリをバックグラウンドでシミュレート)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"発信を開始"</string> + <string name="start_incoming" msgid="6444983300186361271">"着信を開始"</string> + <string name="get_call_id" msgid="5513943242738347108">"通話 ID が設定されていません"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"応答"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"切断"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"受話口"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"スピーカー"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"ストリーミングを開始"</string> + <string name="crash_app" msgid="2548690390730057704">"例外をスロー"</string> + <string name="update_notification" msgid="8677916482672588779">"通話中スタイルへの通知を更新"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ka/strings.xml b/testapps/transactionalVoipApp/res/values-ka/strings.xml index 10b82dc97..6d94f3e01 100644 --- a/testapps/transactionalVoipApp/res/values-ka/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ka/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ტრანზაქციული API ტესტის აქტივობა"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ტრანზაქციის ზარის აქტივობა"</string> <string name="register_phone_account" msgid="1920315963082350332">"ტელეფონის ანგარიშის რეგისტრაცია"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS-ის დაწყება (MT + აპის სიმულაცია ფონზე)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"დაიწყეთ გამავალი ზარი"</string> + <string name="start_incoming" msgid="6444983300186361271">"დაიწყეთ შემომავალი ზარი"</string> + <string name="get_call_id" msgid="5513943242738347108">"აბონენტის ID არ არის დაყენებული"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"პასუხი"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"კავშირის გაწყვეტა"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ყურმილი"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"დინამიკი"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"სტრიმინგის დაწყება"</string> + <string name="crash_app" msgid="2548690390730057704">"ხარვეზის გადასროლა"</string> + <string name="update_notification" msgid="8677916482672588779">"განაახლეთ შეტყობინება მიმდინარე ზარის სტილში"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-kk/strings.xml b/testapps/transactionalVoipApp/res/values-kk/strings.xml index 6dd023614..03fd03129 100644 --- a/testapps/transactionalVoipApp/res/values-kk/strings.xml +++ b/testapps/transactionalVoipApp/res/values-kk/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Транзакциялық API сынағына қатысты әрекет"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Қоңыраулар тарихындағы транзакциялық қолданба"</string> <string name="register_phone_account" msgid="1920315963082350332">"Телефон аккаунтын тіркеу"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS-ті бастау (MT мен қолданбаны фонда симуляциялау)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Шығыс қоңырауын бастау"</string> + <string name="start_incoming" msgid="6444983300186361271">"Кіріс қоңырауын бастау"</string> + <string name="get_call_id" msgid="5513943242738347108">"қоңырау идентификаторы орнатылмады"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"жауап беру"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ажырату"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Телефон динамигі"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Динамик"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"трансляцияны бастау"</string> + <string name="crash_app" msgid="2548690390730057704">"ерекше жағдай туралы хабарлау"</string> + <string name="update_notification" msgid="8677916482672588779">"жүріп жатқан қоңырау стиліндегі хабарландыруды жаңату"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-km/strings.xml b/testapps/transactionalVoipApp/res/values-km/strings.xml index fadb82a34..b3e45e408 100644 --- a/testapps/transactionalVoipApp/res/values-km/strings.xml +++ b/testapps/transactionalVoipApp/res/values-km/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"សកម្មភាពធ្វើតេស្ត API ប្រតិបត្តិការ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"សកម្មភាពប្រតិបត្តិការនៅក្នុងការហៅទូរសព្ទ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ចុះឈ្មោះគណនីទូរសព្ទ"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"ចាប់ផ្ដើម FGS (ត្រាប់តាម MT + កម្មវិធីនៅផ្ទៃខាងក្រោយ)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"ចាប់ផ្ដើមការហៅចេញ"</string> + <string name="start_incoming" msgid="6444983300186361271">"ចាប់ផ្ដើមការហៅចូល"</string> + <string name="get_call_id" msgid="5513943242738347108">"មិនបានកំណត់លេខសម្គាល់ការហៅទូរសព្ទទេ"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"ឆ្លើយ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ផ្ដាច់"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ឧបករណ៍ស្ដាប់សំឡេង"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ឧបករណ៍បំពងសំឡេង"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ប៊្លូធូស"</string> + <string name="start_stream" msgid="3567634786280097431">"ចាប់ផ្ដើមការផ្សាយ"</string> + <string name="crash_app" msgid="2548690390730057704">"បោះការលើកលែង"</string> + <string name="update_notification" msgid="8677916482672588779">"ធ្វើបច្ចុប្បន្នភាពការជូនដំណឹងចំពោះរចនាប័ទ្មនៃការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-kn/strings.xml b/testapps/transactionalVoipApp/res/values-kn/strings.xml index 21d515914..dd3fdd93f 100644 --- a/testapps/transactionalVoipApp/res/values-kn/strings.xml +++ b/testapps/transactionalVoipApp/res/values-kn/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ಟ್ರಾನ್ಸಾಕ್ಷನಲ್ API ಪರೀಕ್ಷಾ ಚಟುವಟಿಕೆ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ಕರೆ ಚಟುವಟಿಕೆಯಲ್ಲಿ ಟ್ರಾನ್ಸಾಕ್ಷನಲ್"</string> <string name="register_phone_account" msgid="1920315963082350332">"ಫೋನ್ ಖಾತೆಯನ್ನು ನೋಂದಾಯಿಸಿ"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ (MT + ಆ್ಯಪ್ ಅನ್ನು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಅನುಕರಿಸಿ)."</string> + <string name="start_outgoing" msgid="1441644037370361864">"ಹೊರಹೋಗುವ ಕರೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string> + <string name="start_incoming" msgid="6444983300186361271">"ಒಳಬರುವ ಕರೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string> + <string name="get_call_id" msgid="5513943242738347108">"ಕರೆಮಾಡುವವರ ID ಅನ್ನು ಸೆಟ್ ಮಾಡಿಲ್ಲ"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"ಉತ್ತರ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ಡಿಸ್ಕನೆಕ್ಟ್"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ಇಯರ್ಪೀಸ್"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ಸ್ಪೀಕರ್"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ಬ್ಲೂಟೂತ್"</string> + <string name="start_stream" msgid="3567634786280097431">"ಸ್ಟ್ರೀಮ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string> + <string name="crash_app" msgid="2548690390730057704">"ಥ್ರೋ ಎಕ್ಸೆಪ್ಶನ್"</string> + <string name="update_notification" msgid="8677916482672588779">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಕರೆ ಶೈಲಿಗೆ ನೋಟಿಫಿಕೇಶನ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಿ"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ko/strings.xml b/testapps/transactionalVoipApp/res/values-ko/strings.xml index efcce4955..762dc9c45 100644 --- a/testapps/transactionalVoipApp/res/values-ko/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ko/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"트랜잭션 API 테스트 활동"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"통화 중 거래 활동"</string> <string name="register_phone_account" msgid="1920315963082350332">"전화 계정 등록"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS 시작(MT 및 백그라운드 앱 시뮬레이션)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"발신 전화 시작"</string> + <string name="start_incoming" msgid="6444983300186361271">"수신 전화 시작"</string> + <string name="get_call_id" msgid="5513943242738347108">"통화 ID가 설정되지 않음"</string> + <string name="set_call_active" msgid="3365404393507589899">"활성으로 설정"</string> + <string name="answer" msgid="5423590397665409939">"답변"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"비활성으로 설정"</string> + <string name="disconnect_call" msgid="1349412380315371385">"연결 해제"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"스피커"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"스피커"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"블루투스"</string> + <string name="start_stream" msgid="3567634786280097431">"스트리밍 시작"</string> + <string name="crash_app" msgid="2548690390730057704">"예외 발생"</string> + <string name="update_notification" msgid="8677916482672588779">"진행 중인 통화 스타일로 알림 업데이트"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ky/strings.xml b/testapps/transactionalVoipApp/res/values-ky/strings.xml index 5e1abe439..47422a029 100644 --- a/testapps/transactionalVoipApp/res/values-ky/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ky/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Транзакциялык API сыноосунун активдүүлүгү"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Чалуу учурундагы транзакциялар"</string> <string name="register_phone_account" msgid="1920315963082350332">"Телефон аккаунтун каттоо"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS\'ти иштетүү (фондо MT + колдонмону симуляциялоо)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Чыгуучу чалууну баштоо"</string> + <string name="start_incoming" msgid="6444983300186361271">"Кирүүчү чалууну баштоо"</string> + <string name="get_call_id" msgid="5513943242738347108">"чалуунун идентификатору коюлган жок"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"жооп берүү"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ажыратуу"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Кулакчын"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Динамик"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"агымды баштоо"</string> + <string name="crash_app" msgid="2548690390730057704">"өзгөчө учурду түзүү"</string> + <string name="update_notification" msgid="8677916482672588779">"учурдагы чалуу үчүн жаңыртуу тууралуу билдирменин стили"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-lo/strings.xml b/testapps/transactionalVoipApp/res/values-lo/strings.xml index 37ea968da..1e1d247f7 100644 --- a/testapps/transactionalVoipApp/res/values-lo/strings.xml +++ b/testapps/transactionalVoipApp/res/values-lo/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ກິດຈະກໍາການທົດສອບ API ທຸລະກໍາ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ການເຄື່ອນໄຫວຂອງທຸລະກຳລະຫວ່າງການໂທ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ລົງທະບຽນບັນຊີໂທລະສັບ"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"ເລີ່ມ FGS (ຈຳລອງ MT + ແອັບໃນພື້ນຫຼັງ)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"ເລີ່ມສາຍໂທອອກ"</string> + <string name="start_incoming" msgid="6444983300186361271">"ເລີ່ມສາຍໂທເຂົ້າ"</string> + <string name="get_call_id" msgid="5513943242738347108">"ບໍ່ໄດ້ຕັ້ງໝາຍເລກຜູ້ໂທ"</string> + <string name="set_call_active" msgid="3365404393507589899">"ຕັ້ງຄ່າເປັນນຳໃຊ້ຢູ່"</string> + <string name="answer" msgid="5423590397665409939">"ຄຳຕອບ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"ຕັ້ງຄ່າເປັນບໍ່ໄດ້ນຳໃຊ້"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ຕັດການເຊື່ອມຕໍ່"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ຫູຟັງ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ລຳໂພງ"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"ເລີ່ມການສະຕຣີມ"</string> + <string name="crash_app" msgid="2548690390730057704">"ຂໍ້ຍົກເວັ້ນໃນການໂຍນ"</string> + <string name="update_notification" msgid="8677916482672588779">"ອັບເດດການແຈ້ງເຕືອນເປັນຮູບແບບການໂທທີ່ກຳລັງດຳເນີນການຢູ່"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-lt/strings.xml b/testapps/transactionalVoipApp/res/values-lt/strings.xml index 576887ac8..88cd414ba 100644 --- a/testapps/transactionalVoipApp/res/values-lt/strings.xml +++ b/testapps/transactionalVoipApp/res/values-lt/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Operacijų API testavimo veikla"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Operacijų skambutyje veikla"</string> <string name="register_phone_account" msgid="1920315963082350332">"Užregistruoti telefono paskyrą"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Pradėti FGS (modeliuoti MT ir programą fone)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Pradėti siunčiamąjį skambutį"</string> + <string name="start_incoming" msgid="6444983300186361271">"Pradėti gaunamąjį skambutį"</string> + <string name="get_call_id" msgid="5513943242738347108">"skambučio ID nenustatytas"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"atsakyti"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"atsijungti"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Garsiakalbis prie ausies"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Garsiakalbis"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"pradėti srautinį perdavimą"</string> + <string name="crash_app" msgid="2548690390730057704">"siųsti pranešimą apie išimtį"</string> + <string name="update_notification" msgid="8677916482672588779">"atnaujinti pranešimą į vykstančio skambučio stilių"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-lv/strings.xml b/testapps/transactionalVoipApp/res/values-lv/strings.xml index 898295124..5e91ffee6 100644 --- a/testapps/transactionalVoipApp/res/values-lv/strings.xml +++ b/testapps/transactionalVoipApp/res/values-lv/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transakciju API testa darbība"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Ar darījumiem saistītas darbības zvana laikā"</string> <string name="register_phone_account" msgid="1920315963082350332">"Reģistrēt tālruņa kontu"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Sākt FGS (simulēt mašīntulkojumu un lietotni fonā)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Sākt izejoša zvana simulāciju"</string> + <string name="start_incoming" msgid="6444983300186361271">"Sākt ienākoša zvana simulāciju"</string> + <string name="get_call_id" msgid="5513943242738347108">"zvana ID nav iestatīts"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"atbildēt"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"pārtraukt"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auss skaļrunis"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Skaļrunis"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"sākt straumēšanu"</string> + <string name="crash_app" msgid="2548690390730057704">"sūtīt ziņojumu par izņēmumu"</string> + <string name="update_notification" msgid="8677916482672588779">"atjaunināt paziņojumu atbilstoši pašreizējā zvana stilam"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-mk/strings.xml b/testapps/transactionalVoipApp/res/values-mk/strings.xml index 4e4fddc0f..d86879d3c 100644 --- a/testapps/transactionalVoipApp/res/values-mk/strings.xml +++ b/testapps/transactionalVoipApp/res/values-mk/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Активност на тестирање на API за трансакции"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Трансакциска активност во повикот"</string> <string name="register_phone_account" msgid="1920315963082350332">"Регистрирај телефонска сметка"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Започни FGS (симулирај MT + апликација во заднина)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Започни појдовен повик"</string> + <string name="start_incoming" msgid="6444983300186361271">"Започни дојдовен повик"</string> + <string name="get_call_id" msgid="5513943242738347108">"не е поставен ID на повикувач"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"одговори"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"прекини врска"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Слушалка"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Звучник"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"започни стриминг"</string> + <string name="crash_app" msgid="2548690390730057704">"отфрли исклучок"</string> + <string name="update_notification" msgid="8677916482672588779">"известување за ажурирање на стилот на тековниот повик"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ml/strings.xml b/testapps/transactionalVoipApp/res/values-ml/strings.xml index 1de25254a..6c70b2228 100644 --- a/testapps/transactionalVoipApp/res/values-ml/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ml/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ട്രാൻസാക്ഷണൽ API ടെസ്റ്റ് ആക്റ്റിവിറ്റി"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ട്രാൻസാക്ഷണൽ ഇൻ കോൾ ആക്റ്റിവിറ്റി"</string> <string name="register_phone_account" msgid="1920315963082350332">"ഫോൺ അക്കൗണ്ട് രജിസ്റ്റർ ചെയ്യുക"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS ആരംഭിക്കുക (പശ്ചാത്തലത്തിൽ മെഷീൻ ട്രാൻസ്ലേഷൻ + ആപ്പ് സിമുലേറ്റ് ചെയ്യുക)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"ഔട്ട്ഗോയിംഗ് കോൾ ആരംഭിക്കുക"</string> + <string name="start_incoming" msgid="6444983300186361271">"ഇൻകമിംഗ് കോൾ ആരംഭിക്കുക"</string> + <string name="get_call_id" msgid="5513943242738347108">"കോൾ ഐഡി സജ്ജീകരിച്ചിട്ടില്ല"</string> + <string name="set_call_active" msgid="3365404393507589899">"സജീവമെന്ന് സജ്ജീകരിക്കുക"</string> + <string name="answer" msgid="5423590397665409939">"ഉത്തരം നൽകുക"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"സജീവമല്ലെന്ന് സജ്ജീകരിക്കുക"</string> + <string name="disconnect_call" msgid="1349412380315371385">"വിച്ഛേദിക്കുക"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ഇയർഫോൺ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"സ്പീക്കർ"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"സ്ട്രീമിംഗ് ആരംഭിക്കുക"</string> + <string name="crash_app" msgid="2548690390730057704">"ഒഴിവാക്കൽ ത്രോ ചെയ്യുക"</string> + <string name="update_notification" msgid="8677916482672588779">"സജീവമായ കോൾ ശൈലിയിലേക്ക് അറിയിപ്പ് അപ്ഡേറ്റ് ചെയ്യുക"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-mn/strings.xml b/testapps/transactionalVoipApp/res/values-mn/strings.xml index a8fa6dd2a..fecb956c5 100644 --- a/testapps/transactionalVoipApp/res/values-mn/strings.xml +++ b/testapps/transactionalVoipApp/res/values-mn/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Гүйлгээний API-н туршилтын үйл ажиллагаа"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Дуудлагын үйл ажиллагааны гүйлгээ"</string> <string name="register_phone_account" msgid="1920315963082350332">"Утасны бүртгэл бүртгүүлэх"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS-г эхлүүлэх (дэвсгэрт MT + аппыг загварчлах)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Залгасан дуудлагыг эхлүүлэх"</string> + <string name="start_incoming" msgid="6444983300186361271">"Ирсэн дуудлагыг эхлүүлэх"</string> + <string name="get_call_id" msgid="5513943242738347108">"дуудлагын ID-г тохируулаагүй"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"хариулах"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"салгах"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Чихний спикер"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Чанга яригч"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"дамжуулалтыг эхлүүлэх"</string> + <string name="crash_app" msgid="2548690390730057704">"шидэх гажиг"</string> + <string name="update_notification" msgid="8677916482672588779">"үргэлжилж буй дуудлагын загварын шинэчлэлтийн мэдэгдэл"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-mr/strings.xml b/testapps/transactionalVoipApp/res/values-mr/strings.xml index 08a5a99d4..97bf66580 100644 --- a/testapps/transactionalVoipApp/res/values-mr/strings.xml +++ b/testapps/transactionalVoipApp/res/values-mr/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"व्यावहारिक API चाचणी अॅक्टिव्हिटी"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"कॉल अॅक्टिव्हिटी यामधील व्यवहार"</string> <string name="register_phone_account" msgid="1920315963082350332">"फोन खात्याची नोंदणी करा"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS सुरू करा (बॅकग्राउंडमध्ये MT + अॅप सिम्युलेट करा)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"आउटगोइंग कॉल सुरू करा"</string> + <string name="start_incoming" msgid="6444983300186361271">"इनकमिंग कॉल सुरू करा"</string> + <string name="get_call_id" msgid="5513943242738347108">"कॉल आयडी सेट केलेला नाही"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"उत्तर"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"डिस्कनेक्ट करा"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"इअरपिस"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"स्पीकर"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ब्लूटूथ"</string> + <string name="start_stream" msgid="3567634786280097431">"स्ट्रीम करणे सुरू करा"</string> + <string name="crash_app" msgid="2548690390730057704">"एक्सेप्शन जोडा"</string> + <string name="update_notification" msgid="8677916482672588779">"सुरू असलेल्या कॉल शैलीवर सूचना अपडेट करा"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ms/strings.xml b/testapps/transactionalVoipApp/res/values-ms/strings.xml index aed28d029..abcb70262 100644 --- a/testapps/transactionalVoipApp/res/values-ms/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ms/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktiviti ujian API transaksi"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaksi Aktiviti Dalam Panggilan"</string> <string name="register_phone_account" msgid="1920315963082350332">"Daftar Akaun Telefon"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Mulakan FGS (simulasi MT + apl pada latar)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Mulakan Panggilan Keluar"</string> + <string name="start_incoming" msgid="6444983300186361271">"Mulakan Panggilan Masuk"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID panggilan tidak ditetapkan"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"jawab"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"putuskan sambungan"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Alat dengar"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Pembesar suara"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"mulakan penstriman"</string> + <string name="crash_app" msgid="2548690390730057704">"buat pengecualian"</string> + <string name="update_notification" msgid="8677916482672588779">"kemas kinikan pemberitahuan kepada gaya panggilan keluar"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-my/strings.xml b/testapps/transactionalVoipApp/res/values-my/strings.xml index b0132426d..b8ee395f1 100644 --- a/testapps/transactionalVoipApp/res/values-my/strings.xml +++ b/testapps/transactionalVoipApp/res/values-my/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"အသိအမှတ်ပြုမှုဆိုင်ရာ API စမ်းသပ်လုပ်ဆောင်ချက်"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ခေါ်ဆိုမှုလုပ်ဆောင်ချက်ရှိ မှတ်တမ်းဆိုင်ရာ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ဖုန်းအကောင့် မှတ်ပုံတင်ရန်"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS (အသွင်တူ MT + နောက်ခံရှိ အက်ပ်) စတင်ရန်"</string> + <string name="start_outgoing" msgid="1441644037370361864">"အထွက် ခေါ်ဆိုမှု စတင်ရန်"</string> + <string name="start_incoming" msgid="6444983300186361271">"အဝင်ခေါ်ဆိုမှု စတင်ရန်"</string> + <string name="get_call_id" msgid="5513943242738347108">"ခေါ်ဆိုမှု id သတ်မှတ်မထားပါ"</string> + <string name="set_call_active" msgid="3365404393507589899">"ပြောနေသည်ဟု သတ်မှတ်ရန်"</string> + <string name="answer" msgid="5423590397665409939">"ဖြေကြားရန်"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"ပြောမနေပါဟု သတ်မှတ်ရန်"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"တယ်လီဖုန်းနားခွက်"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"စပီကာ"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ဘလူးတုသ်"</string> + <string name="start_stream" msgid="3567634786280097431">"တိုက်ရိုက်လွှင့်ခြင်း စတင်ရန်"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"လက်ရှိခေါ်ဆိုမှုပုံစံအတွက် အပ်ဒိတ်အကြောင်းကြားချက်"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-nb/strings.xml b/testapps/transactionalVoipApp/res/values-nb/strings.xml index 50e83abe9..22bb06fc6 100644 --- a/testapps/transactionalVoipApp/res/values-nb/strings.xml +++ b/testapps/transactionalVoipApp/res/values-nb/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Testaktivitet for Transactional API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaksjonell i samtale-aktivitet"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrer telefonkonto"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Start FGS (simuler MT + app i bakgrunnen)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Start utgående anrop"</string> + <string name="start_incoming" msgid="6444983300186361271">"Start innkommende anrop"</string> + <string name="get_call_id" msgid="5513943242738347108">"anrops-ID er ikke angitt"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"svar"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"koble fra"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Ørehøyttaler"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Høyttaler"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"start strømming"</string> + <string name="crash_app" msgid="2548690390730057704">"unntak – avbryt med en feil"</string> + <string name="update_notification" msgid="8677916482672588779">"oppdater varslingsstil til «Pågående anrop»"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ne/strings.xml b/testapps/transactionalVoipApp/res/values-ne/strings.xml index 1934bd2b5..e9bc805fd 100644 --- a/testapps/transactionalVoipApp/res/values-ne/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ne/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API को परीक्षणसम्बन्धी गतिविधि"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"कलमा क्लाइन्ट र सर्भरबिच गरिएको कुराकानीसम्बन्धी क्रियाकलाप"</string> <string name="register_phone_account" msgid="1920315963082350332">"फोन खाता दर्ता गर्नुहोस्"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS सुरु गर्नुहोस् (ब्याकग्राउन्डमा MT + एप सिमुलेट गर्नुहोस्)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"बहिर्गमन कल सुरु गर्नुहोस्"</string> + <string name="start_incoming" msgid="6444983300186361271">"आगमन कल सुरु गर्नुहोस्"</string> + <string name="get_call_id" msgid="5513943242738347108">"कल ID सेट गरिएको छैन"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"कल उठाउनुहोस्"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"डिस्कनेक्ट गर्नुहोस्"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"इयरपिस"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"स्पिकर"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ब्लुटुथ"</string> + <string name="start_stream" msgid="3567634786280097431">"स्ट्रिम गर्न थाल्नुहोस्"</string> + <string name="crash_app" msgid="2548690390730057704">"अपवाद देखाउने काम"</string> + <string name="update_notification" msgid="8677916482672588779">"कल गरिरहेका बेला सूचना जुन शैलीमा देखिन्छ सोही शैली प्रयोग गर्नुहोस्"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-nl/strings.xml b/testapps/transactionalVoipApp/res/values-nl/strings.xml index ae1409370..1ba3f9cef 100644 --- a/testapps/transactionalVoipApp/res/values-nl/strings.xml +++ b/testapps/transactionalVoipApp/res/values-nl/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Testactiviteit Transactional API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Beveiligd gesprek"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefoonaccount registreren"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Service op de voorgrond (FGS) starten (MT + app op de achtergrond simuleren)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Uitgaand gesprek starten"</string> + <string name="start_incoming" msgid="6444983300186361271">"Inkomend gesprek starten"</string> + <string name="get_call_id" msgid="5513943242738347108">"Beller-ID niet ingesteld"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"antwoord"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"loskoppelen"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Oortelefoon"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"streamen starten"</string> + <string name="crash_app" msgid="2548690390730057704">"uitzondering activeren"</string> + <string name="update_notification" msgid="8677916482672588779">"updatemelding naar actieve gespreksstijl"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-or/strings.xml b/testapps/transactionalVoipApp/res/values-or/strings.xml index 30d64e232..f3391ea3e 100644 --- a/testapps/transactionalVoipApp/res/values-or/strings.xml +++ b/testapps/transactionalVoipApp/res/values-or/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ଟ୍ରାଞ୍ଜେକସନାଲ API ପରୀକ୍ଷଣର କାର୍ଯ୍ୟକଳାପ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ଟ୍ରାଞ୍ଜେକସନାଲ ଇନ କଲ କାର୍ଯ୍ୟକଳାପ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ଫୋନ ଆକାଉଣ୍ଟର ପଞ୍ଜିକରଣ କରନ୍ତୁ"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS ଆରମ୍ଭ କରନ୍ତୁ (ପୃଷ୍ଠପଟରେ MT + ଆପକୁ ସିମୁଲେଟ କରନ୍ତୁ)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"ଆଉଟଗୋଇଂ କଲ ଆରମ୍ଭ କରନ୍ତୁ"</string> + <string name="start_incoming" msgid="6444983300186361271">"ଇନକମିଂ କଲ ଆରମ୍ଭ କରନ୍ତୁ"</string> + <string name="get_call_id" msgid="5513943242738347108">"କଲ ID ସେଟ କରାଯାଇନାହିଁ"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"ଉତ୍ତର ଦିଅନ୍ତୁ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ଡିସକନେକ୍ଟ କରନ୍ତୁ"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ଇୟରପିସ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ସ୍ପିକର"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ବ୍ଲୁଟୁଥ"</string> + <string name="start_stream" msgid="3567634786280097431">"ଷ୍ଟ୍ରିମିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string> + <string name="crash_app" msgid="2548690390730057704">"ଥ୍ରୋ ଏକ୍ସସେପସନ"</string> + <string name="update_notification" msgid="8677916482672588779">"ଚାଲିଥିବା କଲ ଷ୍ଟାଇଲ ପାଇଁ ବିଜ୍ଞପ୍ତିକୁ ଅପଡେଟ କରନ୍ତୁ"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-pa/strings.xml b/testapps/transactionalVoipApp/res/values-pa/strings.xml index a5647f8ae..76e367d7e 100644 --- a/testapps/transactionalVoipApp/res/values-pa/strings.xml +++ b/testapps/transactionalVoipApp/res/values-pa/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ਲੈਣ-ਦੇਣ API ਜਾਂਚ ਸਰਗਰਮੀ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ਲੈਣ-ਦੇਣ ਸੰਬੰਧੀ ਇਨ-ਕਾਲ ਸਰਗਰਮੀ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ਫ਼ੋਨ ਖਾਤਾ ਰਜਿਸਟਰ ਕਰੋ"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS ਸ਼ੁਰੂ ਕਰੋ (ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ MT + ਐਪ ਨੂੰ ਸਿਮੂਲੇਟ ਕਰੋ)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"ਆਊਟਗੋਇੰਗ ਕਾਲ ਸ਼ੁਰੂ ਕਰੋ"</string> + <string name="start_incoming" msgid="6444983300186361271">"ਇਨਕਮਿੰਗ ਕਾਲ ਸ਼ੁਰੂ ਕਰੋ"</string> + <string name="get_call_id" msgid="5513943242738347108">"ਕਾਲਰ ਆਈਡੀ ਸੈੱਟ ਨਹੀਂ ਹੈ"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"ਜਵਾਬ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ਈਯਰਪੀਸ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ਸਪੀਕਰ"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ਬਲੂਟੁੱਥ"</string> + <string name="start_stream" msgid="3567634786280097431">"ਸਟ੍ਰੀਮਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string> + <string name="crash_app" msgid="2548690390730057704">"ਅਪਵਾਦ ਸ਼ਾਮਲ ਕਰੋ"</string> + <string name="update_notification" msgid="8677916482672588779">"ਜਾਰੀ ਕਾਲ ਸਟਾਈਲ \'ਤੇ ਸੂਚਨਾ ਅੱਪਡੇਟ ਕਰੋ"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-pl/strings.xml b/testapps/transactionalVoipApp/res/values-pl/strings.xml index 73183865e..c6115b841 100644 --- a/testapps/transactionalVoipApp/res/values-pl/strings.xml +++ b/testapps/transactionalVoipApp/res/values-pl/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Czynność testowa dotycząca transakcji związanej z interfejsem API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Aktywność transakcyjna w trakcie rozmowy"</string> <string name="register_phone_account" msgid="1920315963082350332">"Zarejestruj konto telefonu"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Uruchom FGS (symulacja MT + aplikacja w tle)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Rozpocznij połączenie wychodzące"</string> + <string name="start_incoming" msgid="6444983300186361271">"Rozpocznij połączenie przychodzące"</string> + <string name="get_call_id" msgid="5513943242738347108">"nie ustawiono ID rozmówcy"</string> + <string name="set_call_active" msgid="3365404393507589899">"ustawAktywny"</string> + <string name="answer" msgid="5423590397665409939">"odpowiedź"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"ustawNieaktywny"</string> + <string name="disconnect_call" msgid="1349412380315371385">"rozłącz"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Słuchawka"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Głośnik"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"rozpocznij transmisję"</string> + <string name="crash_app" msgid="2548690390730057704">"wyjątek dotyczący zgłoszenia"</string> + <string name="update_notification" msgid="8677916482672588779">"zaktualizuj powiadomienie do stylu trwającej rozmowy"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml b/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml index 7bf74901b..a5b3ea050 100644 --- a/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml +++ b/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Atividade de teste da API transacional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transacional na atividade da chamada"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registar conta do telemóvel"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Iniciar FGS (simular TA + app em segundo plano)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Iniciar chamada feita"</string> + <string name="start_incoming" msgid="6444983300186361271">"Iniciar chamada recebida"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID da chamada não definido"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"atender"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"desligar"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Auricular"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altifalante"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Iniciar stream"</string> + <string name="crash_app" msgid="2548690390730057704">"acionar exceção"</string> + <string name="update_notification" msgid="8677916482672588779">"atualizar estilo de notificação para chamada em curso"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-pt/strings.xml b/testapps/transactionalVoipApp/res/values-pt/strings.xml index 88ca27f43..a09c64d9f 100644 --- a/testapps/transactionalVoipApp/res/values-pt/strings.xml +++ b/testapps/transactionalVoipApp/res/values-pt/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Atividade de teste da API transacional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Atividade em chamadas transacionais"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrar conta telefônica"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Iniciar FGS (simular MT + app em segundo plano)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Iniciar ligação efetuada"</string> + <string name="start_incoming" msgid="6444983300186361271">"Iniciar ligação recebida"</string> + <string name="get_call_id" msgid="5513943242738347108">"identificador de chamadas não definido"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"resposta"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"desconectar"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Minifone de ouvido"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Alto-falante"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Iniciar transmissão"</string> + <string name="crash_app" msgid="2548690390730057704">"gerar exceção"</string> + <string name="update_notification" msgid="8677916482672588779">"notificação de atualização para o estilo \"Chamada em andamento\""</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ro/strings.xml b/testapps/transactionalVoipApp/res/values-ro/strings.xml index 9e713df7c..261a5adcd 100644 --- a/testapps/transactionalVoipApp/res/values-ro/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ro/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Activitate de testare a API-ului tranzacțional"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Activitate tranzacțională în timpul apelului"</string> <string name="register_phone_account" msgid="1920315963082350332">"Înregistrează contul de telefon"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Pornește FGS (simulează MT + aplicația în fundal)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Inițiază un apel efectuat"</string> + <string name="start_incoming" msgid="6444983300186361271">"Inițiază un apel primit"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID-ul apelului nu este setat"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"răspuns"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"deconectează"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Cască"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Difuzor"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"începe streamingul"</string> + <string name="crash_app" msgid="2548690390730057704">"trimite excepție"</string> + <string name="update_notification" msgid="8677916482672588779">"actualizează notificarea la stilul de apel în desfășurare"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ru/strings.xml b/testapps/transactionalVoipApp/res/values-ru/strings.xml index 68f5a84e2..c05e7ea88 100644 --- a/testapps/transactionalVoipApp/res/values-ru/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ru/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Активность тестирования API транзакций"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Транзакции во время вызовов"</string> <string name="register_phone_account" msgid="1920315963082350332">"Зарегистрировать аккаунт телефона"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Запустить активную службу (симуляция МП + приложение в фоновом режиме)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Начать исходящий вызов"</string> + <string name="start_incoming" msgid="6444983300186361271">"Начать входящий вызов"</string> + <string name="get_call_id" msgid="5513943242738347108">"идентификатор вызова не задан"</string> + <string name="set_call_active" msgid="3365404393507589899">"Активировать"</string> + <string name="answer" msgid="5423590397665409939">"ответить"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Деактивировать"</string> + <string name="disconnect_call" msgid="1349412380315371385">"разъединить"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Динамик телефона"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Колонка"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Начать трансляцию"</string> + <string name="crash_app" msgid="2548690390730057704">"отправить сообщение об исключении"</string> + <string name="update_notification" msgid="8677916482672588779">"стиль уведомления об обновлении для текущего звонка"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-si/strings.xml b/testapps/transactionalVoipApp/res/values-si/strings.xml index 9ab07396a..d8b8a6ffa 100644 --- a/testapps/transactionalVoipApp/res/values-si/strings.xml +++ b/testapps/transactionalVoipApp/res/values-si/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ගනුදෙනු API පරීක්ෂණ ක්රියාකාරකම්"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"ඇමතුම් ක්රියාකාරකම්වල ගනුදෙනු"</string> <string name="register_phone_account" msgid="1920315963082350332">"දුරකථන ගිණුම ලියාපදිංචි කරන්න"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS අරඹන්න (පසුබිමේ MT + යෙදුම අනුකරණය කරන්න)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"පිටතට යන ඇමතුම අරඹන්න"</string> + <string name="start_incoming" msgid="6444983300186361271">"එන ඇමතුම අරඹන්න"</string> + <string name="get_call_id" msgid="5513943242738347108">"අමතුම්කරුගේ id සකසා නැත"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"පිළිතුරු දෙන්න"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"විසන්ධි කරන්න"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"සවන් කඩ"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ස්පීකරය"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"බ්ලූටූත්"</string> + <string name="start_stream" msgid="3567634786280097431">"ප්රවාහය අරඹන්න"</string> + <string name="crash_app" msgid="2548690390730057704">"ව්යතිරේකය දමන්න"</string> + <string name="update_notification" msgid="8677916482672588779">"පවතින ඇමතුම් විලාසයට යාවත්කාලීනයේ දැනුම්දීම"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-sk/strings.xml b/testapps/transactionalVoipApp/res/values-sk/strings.xml index 5b641e9ad..38478827b 100644 --- a/testapps/transactionalVoipApp/res/values-sk/strings.xml +++ b/testapps/transactionalVoipApp/res/values-sk/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Testovacia aktivita transakčného rozhrania API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transakčná aktivita počas hovoru"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrovať telefónny účet"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Spustiť FGS (simulácia MT a aplikácie na pozadí)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Začať odchádzajúci hovor"</string> + <string name="start_incoming" msgid="6444983300186361271">"Začať prichádzajúci hovor"</string> + <string name="get_call_id" msgid="5513943242738347108">"identifikátor hovoru nie je nastavený"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"prijať"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"odpojiť"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Slúchadlo"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Reproduktor"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"spustiť streamovanie"</string> + <string name="crash_app" msgid="2548690390730057704">"vyvolať výnimku"</string> + <string name="update_notification" msgid="8677916482672588779">"aktualizovať upozornenie na štýl prebiehajúceho hovoru"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-sl/strings.xml b/testapps/transactionalVoipApp/res/values-sl/strings.xml index 16f522daa..dec36222e 100644 --- a/testapps/transactionalVoipApp/res/values-sl/strings.xml +++ b/testapps/transactionalVoipApp/res/values-sl/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Preizkusna dejavnost transakcijskega API-ja"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transakcijska dejavnost v klicu"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registracija telefonskega računa"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Zaženi FGS (simuliraj strojni prevod + aplikacijo v ozadju)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Začni odhodni klic"</string> + <string name="start_incoming" msgid="6444983300186361271">"Začni dohodni klic"</string> + <string name="get_call_id" msgid="5513943242738347108">"id klica ni nastavljen"</string> + <string name="set_call_active" msgid="3365404393507589899">"Nastavi kot aktivno"</string> + <string name="answer" msgid="5423590397665409939">"sprejmi"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Nastavi kot neaktivno"</string> + <string name="disconnect_call" msgid="1349412380315371385">"prekini klic"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Slušalka"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvočnik"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"začni pretočno predvajanje"</string> + <string name="crash_app" msgid="2548690390730057704">"sprožitev izjeme"</string> + <string name="update_notification" msgid="8677916482672588779">"posodobi obvestilo na slog trenutnega klica"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-sq/strings.xml b/testapps/transactionalVoipApp/res/values-sq/strings.xml index 975477e98..ddaba66bd 100644 --- a/testapps/transactionalVoipApp/res/values-sq/strings.xml +++ b/testapps/transactionalVoipApp/res/values-sq/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktiviteti i testimit të API-së së transaksioneve"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Aktivitet transaksioni brenda telefonatës"</string> <string name="register_phone_account" msgid="1920315963082350332">"Regjistro llogarinë e telefonit"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Nis shërbimin FGS (simulo përkthimin kompjuterik dhe aplikacionin në sfond)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Nis një telefonatë dalëse"</string> + <string name="start_incoming" msgid="6444983300186361271">"Nis një telefonatë hyrëse"</string> + <string name="get_call_id" msgid="5513943242738347108">"ID-ja e telefonatës nuk është caktuar"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"përgjigju"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"shkëput"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Receptori"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altoparlanti"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"nis transmetimin"</string> + <string name="crash_app" msgid="2548690390730057704">"gjenero një përjashtim"</string> + <string name="update_notification" msgid="8677916482672588779">"përditëso njoftimin me stilin e telefonatës në vazhdim"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-sr/strings.xml b/testapps/transactionalVoipApp/res/values-sr/strings.xml index dd5a3c0d9..cd413f41f 100644 --- a/testapps/transactionalVoipApp/res/values-sr/strings.xml +++ b/testapps/transactionalVoipApp/res/values-sr/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Активност тестирања трансакционог API-ја"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Активност позива у вези са трансакцијама"</string> <string name="register_phone_account" msgid="1920315963082350332">"Региструј налог телефона"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Покрени FGS (симулирајте MT + апликацију у позадини)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Започните одлазни позив"</string> + <string name="start_incoming" msgid="6444983300186361271">"Започните долазни позив"</string> + <string name="get_call_id" msgid="5513943242738347108">"ИД позива није подешен"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"одговори"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"прекини везу"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Слушалица"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Звучник"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"почните да стримујете"</string> + <string name="crash_app" msgid="2548690390730057704">"избацити изузетак"</string> + <string name="update_notification" msgid="8677916482672588779">"ажурирајте обавештење на стил актуелног позива"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-sv/strings.xml b/testapps/transactionalVoipApp/res/values-sv/strings.xml index f97e5a92d..f74b775da 100644 --- a/testapps/transactionalVoipApp/res/values-sv/strings.xml +++ b/testapps/transactionalVoipApp/res/values-sv/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktiviteten Test av transaktions-API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaktioner i samtalsaktivitet"</string> <string name="register_phone_account" msgid="1920315963082350332">"Registrera telefonkonto"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Starta FGS (simulera MT + app i bakgrunden)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Starta utgående samtal"</string> + <string name="start_incoming" msgid="6444983300186361271">"Starta inkommande samtal"</string> + <string name="get_call_id" msgid="5513943242738347108">"nummerpresentatör inte inställd"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"svara"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"koppla från"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Lur"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Högtalare"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"starta streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"utlös undantag"</string> + <string name="update_notification" msgid="8677916482672588779">"uppdatera avisering till format för pågående samtal"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-sw/strings.xml b/testapps/transactionalVoipApp/res/values-sw/strings.xml index acba9c387..b7d0d0f70 100644 --- a/testapps/transactionalVoipApp/res/values-sw/strings.xml +++ b/testapps/transactionalVoipApp/res/values-sw/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Shughuli za jaribio la API ya Uthibitishaji"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Shughuli ya Muamala Kwenye Simu"</string> <string name="register_phone_account" msgid="1920315963082350332">"Sajili Akaunti ya Simu"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Anzisha FGS (kuiga Tafsiri ya Mashine na programu katika hali ya chinichini)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Anzisha Uigaji wa Simu Unayopiga"</string> + <string name="start_incoming" msgid="6444983300186361271">"Anzisha Uigaji wa Simu Uliyopigiwa"</string> + <string name="get_call_id" msgid="5513943242738347108">"kitambulisho cha anayepiga hakijawekwa"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"jibu"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ondoa"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Spika ya sikioni"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Spika"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"anzisha kutiririsha"</string> + <string name="crash_app" msgid="2548690390730057704">"hitilafu wakati wa kutekeleza programu"</string> + <string name="update_notification" msgid="8677916482672588779">"sasisha arifa kwenye mtindo wa simu inayoendelea"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ta/strings.xml b/testapps/transactionalVoipApp/res/values-ta/strings.xml index 4a01a584c..39b410a30 100644 --- a/testapps/transactionalVoipApp/res/values-ta/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ta/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API சோதனை செயல்பாடு"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"டிரான்சாக்ஷனல் இன் கால் ஆக்டிவிட்டி"</string> <string name="register_phone_account" msgid="1920315963082350332">"மொபைல் கணக்கைப் பதிவுசெய்தல்"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGSஸைத் தொடங்கு (MT + ஆப்ஸைப் பின்னணியில் சிமுலேட் செய்)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"வெளிச்செல்லும் அழைப்பைத் தொடங்கு"</string> + <string name="start_incoming" msgid="6444983300186361271">"உள்வரும் அழைப்பைத் தொடங்கு"</string> + <string name="get_call_id" msgid="5513943242738347108">"அழைப்பு ஐடி அமைக்கப்படவில்லை"</string> + <string name="set_call_active" msgid="3365404393507589899">"செயலில் அமை"</string> + <string name="answer" msgid="5423590397665409939">"பதில்"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"செயலற்ற நிலையில் அமை"</string> + <string name="disconnect_call" msgid="1349412380315371385">"துண்டி"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ஒலி கேட்கும் பகுதி"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ஸ்பீக்கர்"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"புளூடூத்"</string> + <string name="start_stream" msgid="3567634786280097431">"ஸ்ட்ரீமிங்கைத் தொடங்கு"</string> + <string name="crash_app" msgid="2548690390730057704">"விதிவிலக்கைத் தொடங்கு"</string> + <string name="update_notification" msgid="8677916482672588779">"செயலில் உள்ள அழைப்பு ஸ்டைலுக்கான அறிவிப்பைப் புதுப்பிக்கவும்"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-te/strings.xml b/testapps/transactionalVoipApp/res/values-te/strings.xml index 060086feb..f4560ab17 100644 --- a/testapps/transactionalVoipApp/res/values-te/strings.xml +++ b/testapps/transactionalVoipApp/res/values-te/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"లావాదేవీల API టెస్ట్ యాక్టివిటీ"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"కాల్ యాక్టివిటీలో లావాదేవీ"</string> <string name="register_phone_account" msgid="1920315963082350332">"ఫోన్ ఖాతాను రిజిస్టర్ చేయండి"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS (అనుకరణ MT + బ్యాక్గ్రౌండ్లో యాప్)ను ప్రారంభించండి"</string> + <string name="start_outgoing" msgid="1441644037370361864">"అవుట్గోయింగ్ కాల్ను ప్రారంభించండి"</string> + <string name="start_incoming" msgid="6444983300186361271">"ఇన్కమింగ్ కాల్ను ప్రారంభించండి"</string> + <string name="get_call_id" msgid="5513943242738347108">"కాల్ id సెట్ చేయబడలేదు"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"సమాధానం"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"డిస్కనెక్ట్ చేయండి"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ఇయర్పీస్"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"స్పీకర్"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"బ్లూటూత్"</string> + <string name="start_stream" msgid="3567634786280097431">"స్ట్రీమింగ్ను ప్రారంభించండి"</string> + <string name="crash_app" msgid="2548690390730057704">"మినహాయింపు వేయండి"</string> + <string name="update_notification" msgid="8677916482672588779">"జరుగుతున్న కాల్ స్టయిల్కి నోటిఫికేషన్ను అప్డేట్ చేయండి"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-th/strings.xml b/testapps/transactionalVoipApp/res/values-th/strings.xml index 09ad2c59f..545110b22 100644 --- a/testapps/transactionalVoipApp/res/values-th/strings.xml +++ b/testapps/transactionalVoipApp/res/values-th/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"กิจกรรมการทดสอบ API ธุรกรรม"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"กิจกรรมธุรกรรมระหว่างการโทร"</string> <string name="register_phone_account" msgid="1920315963082350332">"ลงทะเบียนบัญชีของโทรศัพท์"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"เริ่ม FGS (จําลอง MT + แอปในพื้นหลัง)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"เริ่มสายโทรออก"</string> + <string name="start_incoming" msgid="6444983300186361271">"เริ่มสายเรียกเข้า"</string> + <string name="get_call_id" msgid="5513943242738347108">"ไม่ได้ตั้งค่าหมายเลขผู้โทร"</string> + <string name="set_call_active" msgid="3365404393507589899">"ตั้งค่าเป็นใช้งานอยู่"</string> + <string name="answer" msgid="5423590397665409939">"คำตอบ"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"ตั้งค่าเป็นไม่ใช้งาน"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ยกเลิกการเชื่อมต่อ"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"หูฟังโทรศัพท์"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"ลำโพง"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"บลูทูธ"</string> + <string name="start_stream" msgid="3567634786280097431">"เริ่มสตรีมมิง"</string> + <string name="crash_app" msgid="2548690390730057704">"ส่งข้อยกเว้น"</string> + <string name="update_notification" msgid="8677916482672588779">"อัปเดตการแจ้งเตือนไปยังรูปแบบการโทรที่ดำเนินอยู่"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-tl/strings.xml b/testapps/transactionalVoipApp/res/values-tl/strings.xml index fa0bfe5c7..6cc2a2b22 100644 --- a/testapps/transactionalVoipApp/res/values-tl/strings.xml +++ b/testapps/transactionalVoipApp/res/values-tl/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Aktibidad ng pansubok na Transactional API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Transaksyonal na In Call na Aktibidad"</string> <string name="register_phone_account" msgid="1920315963082350332">"Irehistro ang Phone Account"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Simulan ang FGS (i-simulate ang MT + app sa background)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Magsimula ng Papalabas na Tawag"</string> + <string name="start_incoming" msgid="6444983300186361271">"Magsimula ng Papasok na Tawag"</string> + <string name="get_call_id" msgid="5513943242738347108">"hindi naitakda ang call id"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"sagutin"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"idiskonekta"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Earpiece"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"simulan ang streaming"</string> + <string name="crash_app" msgid="2548690390730057704">"throw exception"</string> + <string name="update_notification" msgid="8677916482672588779">"i-update ang notification sa istilo ng kasalukuyang tawag"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-tr/strings.xml b/testapps/transactionalVoipApp/res/values-tr/strings.xml index 489f2e748..ec230481f 100644 --- a/testapps/transactionalVoipApp/res/values-tr/strings.xml +++ b/testapps/transactionalVoipApp/res/values-tr/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API test etkinliği"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Görüşme İçin İşlem Etkinliği"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefon Hesabını Kaydet"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Ön plan hizmetlerini (FGS) başlat (makine çevirisi + arka plandaki uygulamayı simüle et)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Giden Arama Başlat"</string> + <string name="start_incoming" msgid="6444983300186361271">"Gelen Arama Başlat"</string> + <string name="get_call_id" msgid="5513943242738347108">"arama kimliği ayarlanmadı"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"yanıtla"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"bağlantıyı kes"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Kulaklık"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Hoparlör"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"yayın başlat"</string> + <string name="crash_app" msgid="2548690390730057704">"istisna gönder"</string> + <string name="update_notification" msgid="8677916482672588779">"bildirimi devam eden arama stiline güncelle"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-uk/strings.xml b/testapps/transactionalVoipApp/res/values-uk/strings.xml index ffae40d3c..0069f3d7f 100644 --- a/testapps/transactionalVoipApp/res/values-uk/strings.xml +++ b/testapps/transactionalVoipApp/res/values-uk/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Тестування API підтвердження"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Трансакції під час викликів"</string> <string name="register_phone_account" msgid="1920315963082350332">"Зареєструвати обліковий запис телефона"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Запустити активний сервіс (симуляція МП + додаток у фоновому режимі)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Почати вихідний виклик"</string> + <string name="start_incoming" msgid="6444983300186361271">"Почати вхідний виклик"</string> + <string name="get_call_id" msgid="5513943242738347108">"ідентифікатор виклику не налаштовано"</string> + <string name="set_call_active" msgid="3365404393507589899">"позначити як активний"</string> + <string name="answer" msgid="5423590397665409939">"відповідь"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"позначити як неактивний"</string> + <string name="disconnect_call" msgid="1349412380315371385">"від’єднати"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Динамік"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Колонка"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Почати трансляцію"</string> + <string name="crash_app" msgid="2548690390730057704">"надіслати повідомлення про виняток"</string> + <string name="update_notification" msgid="8677916482672588779">"стиль сповіщення про оновлення для поточного дзвінка"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-ur/strings.xml b/testapps/transactionalVoipApp/res/values-ur/strings.xml index 0f5de18bf..e41027ad8 100644 --- a/testapps/transactionalVoipApp/res/values-ur/strings.xml +++ b/testapps/transactionalVoipApp/res/values-ur/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"ٹرانزیکشنل API ٹیسٹ کی سرگرمی"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"کال کی سرگرمی میں ٹرانزیکشنل"</string> <string name="register_phone_account" msgid="1920315963082350332">"فون کے اکاؤنٹ کو رجسٹر کریں"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS شروع کریں ( بیک گراؤنڈ میں MT + ایپ کی نقل کریں)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"آؤٹ گوئنگ کال شروع کریں"</string> + <string name="start_incoming" msgid="6444983300186361271">"اِن کمنگ کال شروع کریں"</string> + <string name="get_call_id" msgid="5513943242738347108">"کال ID سیٹ نہیں ہے"</string> + <string name="set_call_active" msgid="3365404393507589899">"فعال پر سیٹ کریں"</string> + <string name="answer" msgid="5423590397665409939">"جواب"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"غیر فعال پر سیٹ کریں"</string> + <string name="disconnect_call" msgid="1349412380315371385">"غیر منسلک کریں"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"ایئر پیس"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"اسپیکر"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"بلوٹوتھ"</string> + <string name="start_stream" msgid="3567634786280097431">"سلسلہ بندی شروع کریں"</string> + <string name="crash_app" msgid="2548690390730057704">"تھرو ایکسیپشن"</string> + <string name="update_notification" msgid="8677916482672588779">"اطلاع کو جاری کال طرز پر اپ ڈیٹ کریں"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-uz/strings.xml b/testapps/transactionalVoipApp/res/values-uz/strings.xml index f12eac78b..faa0b4bdc 100644 --- a/testapps/transactionalVoipApp/res/values-uz/strings.xml +++ b/testapps/transactionalVoipApp/res/values-uz/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Tranzaksiyaviy API sinovi faoliyati"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Chaqiruvda tranzaksiya faoliyati"</string> <string name="register_phone_account" msgid="1920315963082350332">"Telefon hisobini ro‘yxatdan o‘tkazish"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"FGS boshlash (MT + fonda ilova simulyatsiyasi)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Chiquvchi chaqiruvni boshlash"</string> + <string name="start_incoming" msgid="6444983300186361271">"Kiruvchi chaqiruvni boshlash"</string> + <string name="get_call_id" msgid="5513943242738347108">"chaqiruv id belgilanmagan"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"javob berish"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"uzish"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Quloq karnaychasi"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Karnay"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"strimingni boshlash"</string> + <string name="crash_app" msgid="2548690390730057704">"istisno berish"</string> + <string name="update_notification" msgid="8677916482672588779">"bildirishnomani joriy chaqiruv uslubida yangilash"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-vi/strings.xml b/testapps/transactionalVoipApp/res/values-vi/strings.xml index a4b78a0d7..a54d54408 100644 --- a/testapps/transactionalVoipApp/res/values-vi/strings.xml +++ b/testapps/transactionalVoipApp/res/values-vi/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Hoạt động kiểm tra cho API Xác nhận trao đổi"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Hoạt động giao dịch trong cuộc gọi"</string> <string name="register_phone_account" msgid="1920315963082350332">"Đăng ký tài khoản điện thoại"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Khởi động FGS (mô phỏng MT + ứng dụng trong nền)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Bắt đầu cuộc gọi đi"</string> + <string name="start_incoming" msgid="6444983300186361271">"Bắt đầu cuộc gọi đến"</string> + <string name="get_call_id" msgid="5513943242738347108">"chưa đặt mã cuộc gọi"</string> + <string name="set_call_active" msgid="3365404393507589899">"Đặt thành đang hoạt động"</string> + <string name="answer" msgid="5423590397665409939">"trả lời"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"Đặt thành không hoạt động"</string> + <string name="disconnect_call" msgid="1349412380315371385">"ngắt kết nối"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Loa tai nghe"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Loa"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"bắt đầu phát trực tuyến"</string> + <string name="crash_app" msgid="2548690390730057704">"đưa ra trường hợp ngoại lệ"</string> + <string name="update_notification" msgid="8677916482672588779">"cập nhật thông báo thành kiểu cuộc gọi đang diễn ra"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml b/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml index 3b64e5cb5..a74cbb539 100644 --- a/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml +++ b/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"事务性 API 测试活动"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> - <string name="register_phone_account" msgid="1920315963082350332">"注册电话帐号"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"通话活动中的事务"</string> + <string name="register_phone_account" msgid="1920315963082350332">"注册电话账号"</string> + <string name="start_foreground_service" msgid="8968755699895128574">"启动 FGS(在后台模拟 MT + 应用)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"开始去电"</string> + <string name="start_incoming" msgid="6444983300186361271">"开始来电"</string> + <string name="get_call_id" msgid="5513943242738347108">"未设置来电显示/本机号码"</string> + <string name="set_call_active" msgid="3365404393507589899">"setActive"</string> + <string name="answer" msgid="5423590397665409939">"回复"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"断开连接"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"手机听筒"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"扬声器"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"蓝牙"</string> + <string name="start_stream" msgid="3567634786280097431">"开始直播"</string> + <string name="crash_app" msgid="2548690390730057704">"抛出异常"</string> + <string name="update_notification" msgid="8677916482672588779">"将通知更新为当前通话样式"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml b/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml index 5f03449df..e00caa948 100644 --- a/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml +++ b/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Transactional API 測試活動"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"交易來電活動"</string> <string name="register_phone_account" msgid="1920315963082350332">"註冊電話帳戶"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"開始 FGS (模擬 MT + 背景應用程式)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"開始撥出電話"</string> + <string name="start_incoming" msgid="6444983300186361271">"開始來電"</string> + <string name="get_call_id" msgid="5513943242738347108">"未設定來電顯示"</string> + <string name="set_call_active" msgid="3365404393507589899">"設為使用中"</string> + <string name="answer" msgid="5423590397665409939">"接聽"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"設為停用"</string> + <string name="disconnect_call" msgid="1349412380315371385">"解除連結"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"聽筒"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"喇叭"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"藍牙"</string> + <string name="start_stream" msgid="3567634786280097431">"開始串流播放"</string> + <string name="crash_app" msgid="2548690390730057704">"擲回例外狀況"</string> + <string name="update_notification" msgid="8677916482672588779">"更新通知至通話中樣式"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml b/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml index aaad5a388..1a6da94d7 100644 --- a/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml +++ b/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"交易 API 測試活動"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"通話活動交易資訊"</string> <string name="register_phone_account" msgid="1920315963082350332">"註冊電話帳戶"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"啟動 FGS (在背景模擬機器翻譯和應用程式)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"開始模擬撥出電話"</string> + <string name="start_incoming" msgid="6444983300186361271">"開始模擬來電"</string> + <string name="get_call_id" msgid="5513943242738347108">"未設定通話 ID"</string> + <string name="set_call_active" msgid="3365404393507589899">"設為使用中"</string> + <string name="answer" msgid="5423590397665409939">"接聽"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"設為閒置"</string> + <string name="disconnect_call" msgid="1349412380315371385">"掛斷"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"耳機"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"喇叭"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"藍牙"</string> + <string name="start_stream" msgid="3567634786280097431">"開始串流播放"</string> + <string name="crash_app" msgid="2548690390730057704">"擲回例外狀況"</string> + <string name="update_notification" msgid="8677916482672588779">"將通知更新為通話中樣式"</string> </resources> diff --git a/testapps/transactionalVoipApp/res/values-zu/strings.xml b/testapps/transactionalVoipApp/res/values-zu/strings.xml index 199d54e08..cd86e811c 100644 --- a/testapps/transactionalVoipApp/res/values-zu/strings.xml +++ b/testapps/transactionalVoipApp/res/values-zu/strings.xml @@ -18,31 +18,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="2907804426411305091">"Umsebenzi wokuhlolwa kwe-Transactional API"</string> - <!-- no translation found for in_call_activity_name (7545884666442897585) --> - <skip /> + <string name="in_call_activity_name" msgid="7545884666442897585">"Okwenziwayo Emsebenzini Wekholi"</string> <string name="register_phone_account" msgid="1920315963082350332">"Bhalisa I-akhawunti Yefoni"</string> - <!-- no translation found for start_foreground_service (8968755699895128574) --> - <skip /> - <!-- no translation found for start_outgoing (1441644037370361864) --> - <skip /> - <!-- no translation found for start_incoming (6444983300186361271) --> - <skip /> - <!-- no translation found for get_call_id (5513943242738347108) --> - <skip /> - <!-- no translation found for set_call_active (3365404393507589899) --> - <skip /> - <!-- no translation found for answer (5423590397665409939) --> - <skip /> - <!-- no translation found for set_call_inactive (7106775211368705195) --> - <skip /> - <!-- no translation found for disconnect_call (1349412380315371385) --> - <skip /> - <!-- no translation found for request_earpiece_endpoint (6649571985089296573) --> - <skip /> - <!-- no translation found for request_speaker_endpoint (1033259535289845405) --> - <skip /> - <!-- no translation found for request_bluetooth_endpoint (5933254250623451836) --> - <skip /> - <!-- no translation found for start_stream (3567634786280097431) --> - <skip /> + <string name="start_foreground_service" msgid="8968755699895128574">"Qala ama-FGS (lingisa i-app ye-MT + ngemuva)"</string> + <string name="start_outgoing" msgid="1441644037370361864">"Qala ikholi ephumela ngaphandle"</string> + <string name="start_incoming" msgid="6444983300186361271">"Qala Ikholi Engenayo"</string> + <string name="get_call_id" msgid="5513943242738347108">"I-ID yekholi ayisethiwe"</string> + <string name="set_call_active" msgid="3365404393507589899">"I-setActive"</string> + <string name="answer" msgid="5423590397665409939">"impendulo"</string> + <string name="set_call_inactive" msgid="7106775211368705195">"I-setInactive"</string> + <string name="disconnect_call" msgid="1349412380315371385">"nqamula"</string> + <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Isipikha sendlebe"</string> + <string name="request_speaker_endpoint" msgid="1033259535289845405">"Isipikha"</string> + <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"I-Bluetooth"</string> + <string name="start_stream" msgid="3567634786280097431">"Qala ukusakaza-bukhoma"</string> + <string name="crash_app" msgid="2548690390730057704">"phonsela okuhlukile"</string> + <string name="update_notification" msgid="8677916482672588779">"buyekeza isaziso kusitayela sekholi eqhubekayo"</string> </resources> diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java index 5da7f31a3..54aedc4f1 100644 --- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java +++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java @@ -381,7 +381,7 @@ public class AnalyticsTests extends TelecomSystemTest { waitForHandlerAction( mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); waitForHandlerAction( mTelecomSystem.getCallsManager().getCallAudioManager() @@ -391,7 +391,7 @@ public class AnalyticsTests extends TelecomSystemTest { mInCallServiceFixtureX.getInCallAdapter().setAudioRoute(CallAudioState.ROUTE_SPEAKER, null); waitForHandlerAction( mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); waitForHandlerAction( mTelecomSystem.getCallsManager().getCallAudioManager() diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java index bd81a2ffe..0b9ee656e 100644 --- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java +++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java @@ -39,19 +39,16 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.IContentProvider; -import android.content.pm.PackageManager; -import android.media.AudioDeviceInfo; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.drawable.Icon; +import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.net.Uri; import android.os.Binder; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; import android.os.Process; import android.os.UserHandle; -import android.os.UserManager; import android.provider.BlockedNumberContract; import android.telecom.Call; import android.telecom.CallAudioState; @@ -72,6 +69,8 @@ import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.internal.telecom.IInCallAdapter; +import com.android.server.telecom.InCallController; + import android.telecom.CallerInfo; import com.google.common.base.Predicate; @@ -110,6 +109,7 @@ public class BasicCallTests extends TelecomSystemTest { doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt()); mPackageManager = mContext.getPackageManager(); when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid()); + when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); } @Override @@ -626,6 +626,48 @@ public class BasicCallTests extends TelecomSystemTest { @LargeTest @Test + public void testIncomingThenOutgoingCalls_AssociatedUsersNotEqual() throws Exception { + when(mFeatureFlags.associatedUserRefactorForWorkProfile()).thenReturn(true); + InCallServiceFixture.setIgnoreOverrideAdapterFlag(true); + + // Receive incoming call via mPhoneAccountMultiUser + IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", + mPhoneAccountMultiUser.getAccountHandle(), mConnectionServiceFixtureA); + waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), + TEST_TIMEOUT); + // Make outgoing call on mPhoneAccountMultiUser (unassociated sim to simulate guest/ + // secondary user scenario where both MO/MT calls exist). + IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", + mPhoneAccountMultiUser.getAccountHandle(), mConnectionServiceFixtureA); + waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), + TEST_TIMEOUT); + + // Outgoing call should be on hold while incoming call is made active + mConnectionServiceFixtureA.mConnectionById.get(incoming.mConnectionId).state = + Connection.STATE_HOLDING; + + // Swap calls and verify that outgoing call is now the active call while the incoming call + // is the held call. + mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId); + waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), + TEST_TIMEOUT); + assertEquals(Call.STATE_HOLDING, + mInCallServiceFixtureX.getCall(outgoing.mCallId).getState()); + assertEquals(Call.STATE_ACTIVE, + mInCallServiceFixtureX.getCall(incoming.mCallId).getState()); + + // Ensure no issues with call disconnect. + mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); + mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); + assertEquals(Call.STATE_DISCONNECTING, + mInCallServiceFixtureX.getCall(incoming.mCallId).getState()); + assertEquals(Call.STATE_DISCONNECTING, + mInCallServiceFixtureX.getCall(outgoing.mCallId).getState()); + InCallServiceFixture.setIgnoreOverrideAdapterFlag(false); + } + + @LargeTest + @Test public void testAudioManagerOperations() throws Exception { AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble() .getApplicationContext().getSystemService(Context.AUDIO_SERVICE); @@ -648,15 +690,15 @@ public class BasicCallTests extends TelecomSystemTest { mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null); waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); ArgumentCaptor<AudioDeviceInfo> infoArgumentCaptor = ArgumentCaptor.forClass(AudioDeviceInfo.class); - verify(audioManager, timeout(TEST_TIMEOUT)).setCommunicationDevice( - infoArgumentCaptor.capture()); + verify(audioManager, timeout(TEST_TIMEOUT).atLeast(1)) + .setCommunicationDevice(infoArgumentCaptor.capture()); assertEquals(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, infoArgumentCaptor.getValue().getType()); mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null); waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); // setSpeakerPhoneOn(false) gets called once during the call initiation phase verify(audioManager, timeout(TEST_TIMEOUT).atLeast(1)) .clearCommunicationDevice(); @@ -667,7 +709,7 @@ public class BasicCallTests extends TelecomSystemTest { waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() .getCallAudioModeStateMachine().getHandler(), TEST_TIMEOUT); waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); verify(audioManager, timeout(TEST_TIMEOUT)) .abandonAudioFocusForCall(); verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) @@ -995,6 +1037,7 @@ public class BasicCallTests extends TelecomSystemTest { call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle()); assert(call.isVideoCallingSupportedByPhoneAccount()); assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); + call.setIsCreateConnectionComplete(true); } /** @@ -1018,6 +1061,7 @@ public class BasicCallTests extends TelecomSystemTest { call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle()); assert(!call.isVideoCallingSupportedByPhoneAccount()); assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState()); + call.setIsCreateConnectionComplete(true); } /** @@ -1195,7 +1239,7 @@ public class BasicCallTests extends TelecomSystemTest { .getState()); mInCallServiceFixtureX.mInCallAdapter.mute(true); waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); assertTrue(mTelecomSystem.getCallsManager().getAudioState().isMuted()); // Make an emergency call. @@ -1204,14 +1248,14 @@ public class BasicCallTests extends TelecomSystemTest { assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(emergencyCall.mCallId) .getState()); waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); // Should be unmute automatically. assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted()); // Toggle mute during an emergency call. mTelecomSystem.getCallsManager().getCallAudioManager().toggleMute(); waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() - .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); + .getCallAudioRouteAdapter().getAdapterHandler(), TEST_TIMEOUT); // Should keep unmute. assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted()); @@ -1339,7 +1383,6 @@ public class BasicCallTests extends TelecomSystemTest { public void testValidateStatusHintsImage_addExistingConnection() throws Exception { IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214", mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); - Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection; // Modify existing connection with StatusHints image exploit Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java index 7d77013d9..e3d4ec2f3 100644 --- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java +++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java @@ -24,7 +24,6 @@ import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; -import android.content.BroadcastReceiver; import android.content.Intent; import android.media.AudioDeviceInfo; import android.media.AudioManager; @@ -32,6 +31,7 @@ import android.os.Bundle; import android.os.Parcel; import android.test.suitebuilder.annotation.SmallTest; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.bluetooth.BluetoothDeviceManager; import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; @@ -52,6 +52,7 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -77,6 +78,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { BluetoothDeviceManager mBluetoothDeviceManager; BluetoothProfile.ServiceListener serviceListenerUnderTest; BluetoothStateReceiver receiverUnderTest; + CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; ArgumentCaptor<BluetoothLeAudio.Callback> leAudioCallbacksTest; private BluetoothDevice device1; @@ -104,8 +106,11 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { when(mBluetoothHearingAid.getHiSyncId(device4)).thenReturn(100L); mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); - mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapter); + mCommunicationDeviceTracker = new CallAudioCommunicationDeviceTracker(mContext); + mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapter, + mCommunicationDeviceTracker, mFeatureFlags); mBluetoothDeviceManager.setBluetoothRouteManager(mRouteManager); + mCommunicationDeviceTracker.setBluetoothRouteManager(mRouteManager); mockAudioManager = mContext.getSystemService(AudioManager.class); @@ -115,7 +120,8 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { serviceCaptor.capture(), eq(BluetoothProfile.HEADSET)); serviceListenerUnderTest = serviceCaptor.getValue(); - receiverUnderTest = new BluetoothStateReceiver(mBluetoothDeviceManager, mRouteManager); + receiverUnderTest = new BluetoothStateReceiver(mBluetoothDeviceManager, + mRouteManager, mCommunicationDeviceTracker, mFeatureFlags); mBluetoothDeviceManager.setHeadsetServiceForTesting(mBluetoothHeadset); mBluetoothDeviceManager.setHearingAidServiceForTesting(mBluetoothHearingAid); @@ -126,6 +132,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { verify(mBluetoothLeAudio).registerCallback(any(), leAudioCallbacksTest.capture()); when(mSpeakerInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER); + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(false); } @Override @@ -413,8 +420,8 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); - AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); - when(mockAudioDeviceInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_HEARING_AID); + AudioDeviceInfo mockAudioDeviceInfo = createMockAudioDeviceInfo(device5.getAddress(), + AudioDeviceInfo.TYPE_HEARING_AID); List<AudioDeviceInfo> devices = new ArrayList<>(); devices.add(mockAudioDeviceInfo); @@ -434,7 +441,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { when(mockAudioManager.getCommunicationDevice()).thenReturn(mockAudioDeviceInfo); mBluetoothDeviceManager.disconnectAudio(); - verify(mockAudioManager).clearCommunicationDevice(); + verify(mockAudioManager, atLeastOnce()).clearCommunicationDevice(); } @SmallTest @@ -448,8 +455,8 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); - AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); - when(mockAudioDeviceInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_BLE_HEADSET); + AudioDeviceInfo mockAudioDeviceInfo = createMockAudioDeviceInfo(device5.getAddress(), + AudioDeviceInfo.TYPE_BLE_HEADSET); List<AudioDeviceInfo> devices = new ArrayList<>(); devices.add(mockAudioDeviceInfo); @@ -470,7 +477,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); mBluetoothDeviceManager.disconnectAudio(); - verify(mockAudioManager).clearCommunicationDevice(); + verify(mockAudioManager, atLeastOnce()).clearCommunicationDevice(); } @SmallTest @@ -508,7 +515,86 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { @SmallTest @Test + public void testConnectMultipleLeAudioDevices() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + receiverUnderTest.setIsInCall(true); + receiverUnderTest.onReceive(mContext, + buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, + BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); + leAudioCallbacksTest.getValue().onGroupNodeAdded(device1, 1); + receiverUnderTest.onReceive(mContext, + buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, + BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); + leAudioCallbacksTest.getValue().onGroupNodeAdded(device2, 1); + when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), + eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); + + List<AudioDeviceInfo> devices = new ArrayList<>(); + AudioDeviceInfo leAudioDevice1 = createMockAudioDeviceInfo(device1.getAddress(), + AudioDeviceInfo.TYPE_BLE_HEADSET); + AudioDeviceInfo leAudioDevice2 = createMockAudioDeviceInfo(device2.getAddress(), + AudioDeviceInfo.TYPE_BLE_HEADSET); + devices.add(leAudioDevice1); + devices.add(leAudioDevice2); + + when(mockAudioManager.getAvailableCommunicationDevices()) + .thenReturn(devices); + when(mockAudioManager.setCommunicationDevice(any(AudioDeviceInfo.class))) + .thenReturn(true); + + // Connect LE audio device + mBluetoothDeviceManager.connectAudio(device1.getAddress(), false); + verify(mAdapter).setActiveDevice(device1, BluetoothAdapter.ACTIVE_DEVICE_ALL); + verify(mBluetoothHeadset, never()).connectAudio(); + verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), + eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); + // Verify that we set the communication device for device 1 + verify(mockAudioManager).setCommunicationDevice(leAudioDevice1); + + // Change active device to other LE audio device + receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device2, + BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); + + // Verify call to clearLeAudioCommunicationDevice + verify(mRouteManager).onAudioLost(eq(DEVICE_ADDRESS_1)); + // Verify that we set the communication device for device2 + verify(mockAudioManager).setCommunicationDevice(leAudioDevice2); + } + + @SmallTest + @Test + public void testClearCommunicationDeviceOnActiveDeviceChange() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + receiverUnderTest.setIsInCall(true); + + List<AudioDeviceInfo> devices = new ArrayList<>(); + AudioDeviceInfo leAudioDevice1 = createMockAudioDeviceInfo(device1.getAddress(), + AudioDeviceInfo.TYPE_BLE_HEADSET); + devices.add(leAudioDevice1); + + when(mockAudioManager.getAvailableCommunicationDevices()) + .thenReturn(devices); + when(mockAudioManager.setCommunicationDevice(any(AudioDeviceInfo.class))) + .thenReturn(true); + + // Pretend that the speaker device is currently the requested device set for communication. + // This test ensures that the set/clear communication logic for audio switching in/out of BT + // is properly working when the receiver processes an active device change intent. + mCommunicationDeviceTracker.setTestCommunicationDevice(TYPE_BUILTIN_SPEAKER); + + // Notify that LE audio device has been turned on + receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device1, + BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); + // Verify call to clear speaker communication device + verify(mockAudioManager).clearCommunicationDevice(); + // Verify that LE audio communication device was set after clearing the speaker device + verify(mockAudioManager).setCommunicationDevice(leAudioDevice1); + } + + @SmallTest + @Test public void testConnectDualModeEarbud() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); receiverUnderTest.setIsInCall(true); // LE Audio earbuds connected @@ -527,11 +613,11 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); - AudioDeviceInfo mockAudioDevice5Info = mock(AudioDeviceInfo.class); - when(mockAudioDevice5Info.getAddress()).thenReturn(device5.getAddress()); + AudioDeviceInfo mockAudioDevice5Info = createMockAudioDeviceInfo(device5.getAddress(), + AudioDeviceInfo.TYPE_BLE_HEADSET); + AudioDeviceInfo mockAudioDevice6Info = createMockAudioDeviceInfo(device6.getAddress(), + AudioDeviceInfo.TYPE_BLE_HEADSET); when(mockAudioDevice5Info.getType()).thenReturn(AudioDeviceInfo.TYPE_BLE_HEADSET); - AudioDeviceInfo mockAudioDevice6Info = mock(AudioDeviceInfo.class); - when(mockAudioDevice6Info.getAddress()).thenReturn(device6.getAddress()); when(mockAudioDevice6Info.getType()).thenReturn(AudioDeviceInfo.TYPE_BLE_HEADSET); List<AudioDeviceInfo> devices = new ArrayList<>(); devices.add(mockAudioDevice5Info); @@ -572,6 +658,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { verify(mBluetoothHeadset, never()).connectAudio(); verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); + verify(mockAudioManager, times(1)).clearCommunicationDevice(); // Reconnect other LE Audio earbud devices.add(mockAudioDevice5Info); @@ -582,7 +669,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { // Disconnects audio mBluetoothDeviceManager.disconnectAudio(); - verify(mockAudioManager, times(1)).clearCommunicationDevice(); + verify(mockAudioManager, times(2)).clearCommunicationDevice(); verify(mBluetoothHeadset, times(1)).disconnectAudio(); // TEST 2: HFP preferred for DUPLEX @@ -592,7 +679,8 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL))).thenReturn(true); mBluetoothDeviceManager.connectAudio(device5.getAddress(), false); verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL); - verify(mAdapter, times(1)).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL); + verify(mAdapter, times(1)).setActiveDevice(device5, + BluetoothAdapter.ACTIVE_DEVICE_ALL); verify(mBluetoothHeadset).connectAudio(); mBluetoothDeviceManager.disconnectAudio(); verify(mBluetoothHeadset, times(2)).disconnectAudio(); @@ -600,23 +688,28 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { @SmallTest @Test - public void testClearHearingAidCommunicationDevice() { - AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); - when(mockAudioDeviceInfo.getAddress()).thenReturn(DEVICE_ADDRESS_1); - when(mockAudioDeviceInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_HEARING_AID); - List<AudioDeviceInfo> devices = new ArrayList<>(); - devices.add(mockAudioDeviceInfo); + public void testClearHearingAidCommunicationDeviceLegacy() { + assertClearHearingAidOrLeCommunicationDevice(false, AudioDeviceInfo.TYPE_HEARING_AID); + } - when(mockAudioManager.getAvailableCommunicationDevices()) - .thenReturn(devices); - when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo))) - .thenReturn(true); + @SmallTest + @Test + public void testClearHearingAidCommunicationDeviceWithFlag() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + assertClearHearingAidOrLeCommunicationDevice(true, AudioDeviceInfo.TYPE_HEARING_AID); + } - mBluetoothDeviceManager.setHearingAidCommunicationDevice(); - when(mockAudioManager.getCommunicationDevice()).thenReturn(mSpeakerInfo); - mBluetoothDeviceManager.clearHearingAidCommunicationDevice(); - verify(mRouteManager).onAudioLost(eq(DEVICE_ADDRESS_1)); - assertFalse(mBluetoothDeviceManager.isHearingAidSetAsCommunicationDevice()); + @SmallTest + @Test + public void testClearLeAudioCommunicationDeviceLegacy() { + assertClearHearingAidOrLeCommunicationDevice(false, AudioDeviceInfo.TYPE_BLE_HEADSET); + } + + @SmallTest + @Test + public void testClearLeAudioCommunicationDeviceWithFlag() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + assertClearHearingAidOrLeCommunicationDevice(true, AudioDeviceInfo.TYPE_BLE_HEADSET); } @SmallTest @@ -644,22 +737,67 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase { when(mBluetoothLeAudio.isInbandRingtoneEnabled(1)).thenReturn(true); when(mBluetoothLeAudio.getGroupId(eq(device3))).thenReturn(1); receiverUnderTest.onReceive(mContext, - buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, - BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); - receiverUnderTest.onReceive(mContext, - buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, - BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); - receiverUnderTest.onReceive(mContext, buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); leAudioCallbacksTest.getValue().onGroupNodeAdded(device3, 1); - when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device3); when(mRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(device3); when(mRouteManager.isCachedLeAudioDevice(eq(device3))).thenReturn(true); - assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices()); + when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device3); + when(mRouteManager.getMostRecentlyReportedActiveDevice()).thenReturn(device3); + assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); assertTrue(mBluetoothDeviceManager.isInbandRingingEnabled()); } + private void assertClearHearingAidOrLeCommunicationDevice( + boolean flagEnabled, int device_type + ) { + AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); + when(mockAudioDeviceInfo.getAddress()).thenReturn(DEVICE_ADDRESS_1); + when(mockAudioDeviceInfo.getType()).thenReturn(device_type); + List<AudioDeviceInfo> devices = new ArrayList<>(); + devices.add(mockAudioDeviceInfo); + + when(mockAudioManager.getAvailableCommunicationDevices()) + .thenReturn(devices); + when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo))) + .thenReturn(true); + + if (flagEnabled) { + BluetoothDevice btDevice = device_type == AudioDeviceInfo.TYPE_BLE_HEADSET + ? device1 : null; + mCommunicationDeviceTracker.setCommunicationDevice(device_type, btDevice); + } else { + if (device_type == AudioDeviceInfo.TYPE_BLE_HEADSET) { + mBluetoothDeviceManager.setLeAudioCommunicationDevice(); + } else { + mBluetoothDeviceManager.setHearingAidCommunicationDevice(); + } + } + when(mockAudioManager.getCommunicationDevice()).thenReturn(mSpeakerInfo); + if (flagEnabled) { + mCommunicationDeviceTracker.clearCommunicationDevice(device_type); + assertFalse(mCommunicationDeviceTracker.isAudioDeviceSetForType(device_type)); + } else { + if (device_type == AudioDeviceInfo.TYPE_BLE_HEADSET) { + mBluetoothDeviceManager.clearLeAudioCommunicationDevice(); + assertFalse(mBluetoothDeviceManager.isLeAudioCommunicationDevice()); + } else { + mBluetoothDeviceManager.clearHearingAidCommunicationDevice(); + assertFalse(mBluetoothDeviceManager.isHearingAidSetAsCommunicationDevice()); + } + } + verify(mRouteManager).onAudioLost(eq(DEVICE_ADDRESS_1)); + } + + private AudioDeviceInfo createMockAudioDeviceInfo(String address, int audioType) { + AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); + when(mockAudioDeviceInfo.getType()).thenReturn(audioType); + if (address != null) { + when(mockAudioDeviceInfo.getAddress()).thenReturn(address); + } + return mockAudioDeviceInfo; + } + private Intent buildConnectionActionIntent(int state, BluetoothDevice device, int deviceType) { String intentString; diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java index 1a6fb8811..e1ef08ae2 100644 --- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java +++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java @@ -16,6 +16,16 @@ package com.android.server.telecom.tests; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; @@ -28,7 +38,10 @@ import android.os.Parcel; import android.telecom.Log; import android.test.suitebuilder.annotation.SmallTest; +import android.media.AudioDeviceInfo; + import com.android.internal.os.SomeArgs; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.Timeouts; import com.android.server.telecom.bluetooth.BluetoothDeviceManager; @@ -46,23 +59,20 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(JUnit4.class) public class BluetoothRouteManagerTest extends TelecomTestCase { private static final int TEST_TIMEOUT = 1000; static final BluetoothDevice DEVICE1 = makeBluetoothDevice("00:00:00:00:00:01"); static final BluetoothDevice DEVICE2 = makeBluetoothDevice("00:00:00:00:00:02"); static final BluetoothDevice DEVICE3 = makeBluetoothDevice("00:00:00:00:00:03"); - static final BluetoothDevice HEARING_AID_DEVICE = makeBluetoothDevice("00:00:00:00:00:04"); + static final BluetoothDevice HEARING_AID_DEVICE_LEFT = makeBluetoothDevice("CA:FE:DE:CA:00:01"); + static final BluetoothDevice HEARING_AID_DEVICE_RIGHT = + makeBluetoothDevice("CA:FE:DE:CA:00:02"); + // See HearingAidService#getActiveDevices + // Note: It is really important that the left HA is the first one. The left HA is always + // in the first index (0) and the right one in the second index (1). + static final BluetoothDevice[] HEARING_AIDS = + new BluetoothDevice[]{HEARING_AID_DEVICE_LEFT, HEARING_AID_DEVICE_RIGHT}; @Mock private BluetoothAdapter mBluetoothAdapter; @Mock private BluetoothDeviceManager mDeviceManager; @@ -71,6 +81,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { @Mock private BluetoothLeAudio mBluetoothLeAudio; @Mock private Timeouts.Adapter mTimeoutsAdapter; @Mock private BluetoothRouteManager.BluetoothStateListener mListener; + @Mock private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; @Override @Before @@ -86,6 +97,59 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { @SmallTest @Test + public void testConnectLeftHearingAidWhenLeftIsActive() { + BluetoothRouteManager sm = setupStateMachine( + BluetoothRouteManager.AUDIO_OFF_STATE_NAME, HEARING_AID_DEVICE_LEFT); + sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, + BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); + when(mDeviceManager.connectAudio(anyString(), anyBoolean())).thenReturn(true); + when(mDeviceManager.isHearingAidSetAsCommunicationDevice()).thenReturn(true); + + setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); + when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class))) + .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); + + executeRoutingAction(sm, + BluetoothRouteManager.NEW_DEVICE_CONNECTED, HEARING_AID_DEVICE_LEFT.getAddress()); + + executeRoutingAction(sm, + BluetoothRouteManager.CONNECT_BT, HEARING_AID_DEVICE_LEFT.getAddress()); + + assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + + ":" + HEARING_AID_DEVICE_LEFT.getAddress(), sm.getCurrentState().getName()); + + sm.quitNow(); + } + + @SmallTest + @Test + public void testConnectRightHearingAidWhenLeftIsActive() { + BluetoothRouteManager sm = setupStateMachine( + BluetoothRouteManager.AUDIO_OFF_STATE_NAME, HEARING_AID_DEVICE_RIGHT); + sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, + BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); + when(mDeviceManager.connectAudio(anyString(), anyBoolean())).thenReturn(true); + when(mDeviceManager.isHearingAidSetAsCommunicationDevice()).thenReturn(true); + + + setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); + when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class))) + .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); + + executeRoutingAction(sm, + BluetoothRouteManager.NEW_DEVICE_CONNECTED, HEARING_AID_DEVICE_LEFT.getAddress()); + + executeRoutingAction(sm, + BluetoothRouteManager.CONNECT_BT, HEARING_AID_DEVICE_LEFT.getAddress()); + + assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + + ":" + HEARING_AID_DEVICE_LEFT.getAddress(), sm.getCurrentState().getName()); + + sm.quitNow(); + } + + @SmallTest + @Test public void testConnectBtRetryWhileNotConnected() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null); @@ -112,15 +176,15 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1); setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, - new BluetoothDevice[]{HEARING_AID_DEVICE}, new BluetoothDevice[]{DEVICE2}, - DEVICE1, HEARING_AID_DEVICE, DEVICE2); + HEARING_AIDS, new BluetoothDevice[]{DEVICE2}, + DEVICE1, HEARING_AIDS, DEVICE2); sm.onActiveDeviceChanged(DEVICE1, BluetoothDeviceManager.DEVICE_TYPE_HEADSET); sm.onActiveDeviceChanged(DEVICE2, BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO); - sm.onActiveDeviceChanged(HEARING_AID_DEVICE, + sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress()); - verifyConnectionAttempt(HEARING_AID_DEVICE, 0); + verifyConnectionAttempt(HEARING_AID_DEVICE_LEFT, 0); verifyConnectionAttempt(DEVICE1, 0); verifyConnectionAttempt(DEVICE2, 0); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX @@ -171,11 +235,52 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { sm.quitNow(); } + @SmallTest + @Test + public void testSkipInactiveBtDeviceWhenEvaluateActualState() { + BluetoothRouteManager sm = setupStateMachine( + BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, HEARING_AID_DEVICE_LEFT); + setupConnectedDevices(null, HEARING_AIDS, + null, null, HEARING_AIDS, null); + executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, + HEARING_AID_DEVICE_LEFT.getAddress()); + assertEquals(BluetoothRouteManager.AUDIO_OFF_STATE_NAME, sm.getCurrentState().getName()); + sm.quitNow(); + } + + @SmallTest + @Test + public void testConnectBtWithoutAddress() { + when(mFeatureFlags.useActualAddressToEnterConnectingState()).thenReturn(true); + BluetoothRouteManager sm = setupStateMachine( + BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1); + setupConnectedDevices(new BluetoothDevice[]{DEVICE1, DEVICE2}, null, null, null, null, + null); + when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis( + nullable(ContentResolver.class))).thenReturn(0L); + when(mBluetoothHeadset.connectAudio()).thenReturn(BluetoothStatusCodes.ERROR_UNKNOWN); + executeRoutingAction(sm, BluetoothRouteManager.CONNECT_BT, null); + // Wait 3 times: the first connection attempt is accounted for in executeRoutingAction, + // so wait twice for the retry attempt, again to make sure there are only three attempts, + // and once more for good luck. + waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); + verifyConnectionAttempt(DEVICE1, 1); + assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + + ":" + DEVICE1.getAddress(), + sm.getCurrentState().getName()); + sm.getHandler().removeMessages(BluetoothRouteManager.CONNECTION_TIMEOUT); + sm.quitNow(); + } + private BluetoothRouteManager setupStateMachine(String initialState, BluetoothDevice initialDevice) { resetMocks(); BluetoothRouteManager sm = new BluetoothRouteManager(mContext, - new TelecomSystem.SyncRoot() { }, mDeviceManager, mTimeoutsAdapter); + new TelecomSystem.SyncRoot() { }, mDeviceManager, + mTimeoutsAdapter, mCommunicationDeviceTracker, mFeatureFlags); sm.setListener(mListener); sm.setInitialStateForTesting(initialState, initialDevice); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -185,10 +290,11 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { private void setupConnectedDevices(BluetoothDevice[] hfpDevices, BluetoothDevice[] hearingAidDevices, BluetoothDevice[] leAudioDevices, - BluetoothDevice hfpActiveDevice, BluetoothDevice hearingAidActiveDevice, + BluetoothDevice hfpActiveDevice, BluetoothDevice[] hearingAidActiveDevices, BluetoothDevice leAudioDevice) { if (hfpDevices == null) hfpDevices = new BluetoothDevice[]{}; if (hearingAidDevices == null) hearingAidDevices = new BluetoothDevice[]{}; + if (hearingAidActiveDevices == null) hearingAidActiveDevices = new BluetoothDevice[]{}; if (leAudioDevice == null) leAudioDevices = new BluetoothDevice[]{}; when(mDeviceManager.getNumConnectedDevices()).thenReturn( @@ -207,7 +313,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { when(mBluetoothHearingAid.getConnectedDevices()) .thenReturn(Arrays.asList(hearingAidDevices)); when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID))) - .thenReturn(Arrays.asList(hearingAidActiveDevice, null)); + .thenReturn(Arrays.asList(hearingAidActiveDevices)); when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.LE_AUDIO))) .thenReturn(Arrays.asList(leAudioDevice, null)); } diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java index 0f9ffc11c..65854af35 100644 --- a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java +++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java @@ -28,6 +28,7 @@ import android.telecom.Log; import android.test.suitebuilder.annotation.SmallTest; import com.android.internal.os.SomeArgs; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.Timeouts; import com.android.server.telecom.bluetooth.BluetoothDeviceManager; @@ -263,6 +264,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase { @Mock private BluetoothLeAudio mBluetoothLeAudio; @Mock private Timeouts.Adapter mTimeoutsAdapter; @Mock private BluetoothRouteManager.BluetoothStateListener mListener; + @Mock private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; @Override @Before @@ -416,7 +418,8 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase { when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis( nullable(ContentResolver.class))).thenReturn(100000L); BluetoothRouteManager sm = new BluetoothRouteManager(mContext, - new TelecomSystem.SyncRoot() { }, mDeviceManager, mTimeoutsAdapter); + new TelecomSystem.SyncRoot() { }, mDeviceManager, + mTimeoutsAdapter, mCommunicationDeviceTracker, mFeatureFlags); sm.setListener(mListener); sm.setInitialStateForTesting(initialState, initialDevice); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); diff --git a/tests/src/com/android/server/telecom/tests/CallAnomalyWatchdogTest.java b/tests/src/com/android/server/telecom/tests/CallAnomalyWatchdogTest.java index 7e197fe65..86d24f96f 100644 --- a/tests/src/com/android/server/telecom/tests/CallAnomalyWatchdogTest.java +++ b/tests/src/com/android/server/telecom/tests/CallAnomalyWatchdogTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import android.content.ComponentName; import android.net.Uri; +import android.os.UserHandle; import android.telecom.DisconnectCause; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; @@ -123,6 +124,7 @@ public class CallAnomalyWatchdogTest extends TelecomTestCase { mCallAnomalyWatchdog = new CallAnomalyWatchdog(mTestScheduledExecutorService, mLock, mTimeouts, mMockClockProxy, mMockEmergencyCallDiagnosticLogger); mCallAnomalyWatchdog.setAnomalyReporterAdapter(mAnomalyReporterAdapter); + when(mMockCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT); } @Override @@ -862,6 +864,7 @@ public class CallAnomalyWatchdogTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, false /* isConference */, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); } }
\ No newline at end of file diff --git a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java index 3d06ad090..0a75c3a8d 100644 --- a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java +++ b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java @@ -36,6 +36,7 @@ import com.android.server.telecom.RingbackPlayer; import com.android.server.telecom.Ringer; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; +import com.android.server.telecom.flags.FeatureFlags; import org.junit.After; import org.junit.Before; @@ -59,6 +60,7 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -78,6 +80,8 @@ public class CallAudioManagerTest extends TelecomTestCase { @Mock private BluetoothStateReceiver mBluetoothStateReceiver; @Mock private TelecomSystem.SyncRoot mLock; + @Mock private FeatureFlags mFlags; + private CallAudioManager mCallAudioManager; @Override @@ -87,12 +91,13 @@ public class CallAudioManagerTest extends TelecomTestCase { doAnswer((invocation) -> { InCallTonePlayer mockInCallTonePlayer = mock(InCallTonePlayer.class); doAnswer((invocation2) -> { - mCallAudioManager.setIsTonePlaying(true); + mCallAudioManager.setIsTonePlaying(invocation.getArgument(0), true); return true; }).when(mockInCallTonePlayer).startTone(); return mockInCallTonePlayer; - }).when(mPlayerFactory).createPlayer(anyInt()); + }).when(mPlayerFactory).createPlayer(any(Call.class), anyInt()); when(mCallsManager.getLock()).thenReturn(mLock); + when(mFlags.ensureAudioModeUpdatesOnForegroundCallChange()).thenReturn(true); mCallAudioManager = new CallAudioManager( mCallAudioRouteStateMachine, mCallsManager, @@ -101,7 +106,8 @@ public class CallAudioManagerTest extends TelecomTestCase { mRinger, mRingbackPlayer, mBluetoothStateReceiver, - mDtmfLocalTonePlayer); + mDtmfLocalTonePlayer, + mFlags); } @Override @@ -204,7 +210,7 @@ public class CallAudioManagerTest extends TelecomTestCase { assertMessageArgEquality(correctArgs, captor.getValue()); disconnectCall(call); - stopTone(); + stopTone(call); mCallAudioManager.onCallRemoved(call); verifyProperCleanup(); @@ -241,7 +247,7 @@ public class CallAudioManagerTest extends TelecomTestCase { mCallAudioManager.onCallStateChanged(call, CallState.ANSWERED, CallState.ACTIVE); disconnectCall(call); - stopTone(); + stopTone(call); mCallAudioManager.onCallRemoved(call); verifyProperCleanup(); @@ -277,25 +283,40 @@ public class CallAudioManagerTest extends TelecomTestCase { verify(mCallAudioModeStateMachine, times(2)).sendMessageWithArgs( eq(CallAudioModeStateMachine.NEW_ACTIVE_OR_DIALING_CALL), captor.capture()); assertMessageArgEquality(expectedArgs, captor.getValue()); - verify(mCallAudioModeStateMachine, times(2)).sendMessageWithArgs( - anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); - + if (mFlags.ensureAudioModeUpdatesOnForegroundCallChange()) { + // Expect another invocation due to audio mode change signal. + verify(mCallAudioModeStateMachine, times(3)).sendMessageWithArgs( + anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + } else { + verify(mCallAudioModeStateMachine, times(2)).sendMessageWithArgs( + anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + } when(call.getState()).thenReturn(CallState.ACTIVE); mCallAudioManager.onCallStateChanged(call, CallState.DIALING, CallState.ACTIVE); verify(mCallAudioModeStateMachine, times(3)).sendMessageWithArgs( eq(CallAudioModeStateMachine.NEW_ACTIVE_OR_DIALING_CALL), captor.capture()); assertMessageArgEquality(expectedArgs, captor.getValue()); - verify(mCallAudioModeStateMachine, times(3)).sendMessageWithArgs( - anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); - + if (mFlags.ensureAudioModeUpdatesOnForegroundCallChange()) { + verify(mCallAudioModeStateMachine, times(4)).sendMessageWithArgs( + anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + } else { + verify(mCallAudioModeStateMachine, times(3)).sendMessageWithArgs( + anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + } disconnectCall(call); - stopTone(); + stopTone(call); mCallAudioManager.onCallRemoved(call); verifyProperCleanup(); } + @Test + public void testSingleOutgoingCallWithoutAudioModeUpdateOnForegroundCallChange() { + when(mFlags.ensureAudioModeUpdatesOnForegroundCallChange()).thenReturn(false); + testSingleOutgoingCall(); + } + @MediumTest @Test public void testRingbackStartStop() { @@ -327,8 +348,14 @@ public class CallAudioManagerTest extends TelecomTestCase { verify(mCallAudioModeStateMachine, times(2)).sendMessageWithArgs( eq(CallAudioModeStateMachine.NEW_ACTIVE_OR_DIALING_CALL), captor.capture()); assertMessageArgEquality(expectedArgs, captor.getValue()); - verify(mCallAudioModeStateMachine, times(2)).sendMessageWithArgs( - anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + if (mFlags.ensureAudioModeUpdatesOnForegroundCallChange()) { + // Expect an extra time due to audio mode change signal + verify(mCallAudioModeStateMachine, times(3)).sendMessageWithArgs( + anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + } else { + verify(mCallAudioModeStateMachine, times(2)).sendMessageWithArgs( + anyInt(), any(CallAudioModeStateMachine.MessageArgs.class)); + } // Ensure we started ringback. verify(mRingbackPlayer).startRingbackForCall(any(Call.class)); @@ -350,6 +377,12 @@ public class CallAudioManagerTest extends TelecomTestCase { verify(mRingbackPlayer, times(1)).startRingbackForCall(any(Call.class)); } + @Test + public void testRingbackStartStopWithoutAudioModeUpdateOnForegroundCallChange() { + when(mFlags.ensureAudioModeUpdatesOnForegroundCallChange()).thenReturn(false); + testRingbackStartStop(); + } + @SmallTest @Test public void testNewCallGoesToAudioProcessing() { @@ -495,7 +528,7 @@ public class CallAudioManagerTest extends TelecomTestCase { mCallAudioManager.onCallStateChanged(call, CallState.AUDIO_PROCESSING, CallState.DISCONNECTED); - verify(mPlayerFactory, never()).createPlayer(anyInt()); + verify(mPlayerFactory, never()).createPlayer(any(Call.class), anyInt()); CallAudioModeStateMachine.MessageArgs expectedArgs2 = new Builder() .setHasActiveOrDialingCalls(false) .setHasRingingCalls(false) @@ -526,7 +559,7 @@ public class CallAudioManagerTest extends TelecomTestCase { mCallAudioManager.onCallStateChanged(call, CallState.AUDIO_PROCESSING, CallState.SIMULATED_RINGING); - verify(mPlayerFactory, never()).createPlayer(anyInt()); + verify(mPlayerFactory, never()).createPlayer(any(Call.class), anyInt()); CallAudioModeStateMachine.MessageArgs expectedArgs = new Builder() .setHasActiveOrDialingCalls(false) .setHasRingingCalls(true) @@ -555,7 +588,7 @@ public class CallAudioManagerTest extends TelecomTestCase { mCallAudioManager.onCallStateChanged(call, CallState.AUDIO_PROCESSING, CallState.ACTIVE); - verify(mPlayerFactory, never()).createPlayer(anyInt()); + verify(mPlayerFactory, never()).createPlayer(any(Call.class), anyInt()); CallAudioModeStateMachine.MessageArgs expectedArgs = new Builder() .setHasActiveOrDialingCalls(true) .setHasRingingCalls(false) @@ -584,7 +617,7 @@ public class CallAudioManagerTest extends TelecomTestCase { mCallAudioManager.onCallStateChanged(call, CallState.SIMULATED_RINGING, CallState.ACTIVE); - verify(mPlayerFactory, never()).createPlayer(anyInt()); + verify(mPlayerFactory, never()).createPlayer(any(Call.class), anyInt()); CallAudioModeStateMachine.MessageArgs expectedArgs = new Builder() .setHasActiveOrDialingCalls(true) .setHasRingingCalls(false) @@ -643,7 +676,7 @@ public class CallAudioManagerTest extends TelecomTestCase { mCallAudioManager.onCallStateChanged(call, CallState.SIMULATED_RINGING, CallState.DISCONNECTED); - verify(mPlayerFactory, never()).createPlayer(anyInt()); + verify(mPlayerFactory, never()).createPlayer(any(Call.class), anyInt()); CallAudioModeStateMachine.MessageArgs expectedArgs2 = new Builder() .setHasActiveOrDialingCalls(false) .setHasRingingCalls(false) @@ -702,6 +735,77 @@ public class CallAudioManagerTest extends TelecomTestCase { assertFalse(captor.getValue().isStreaming); } + @SmallTest + @Test + public void testTriggerAudioManagerModeChange() { + if (!mFlags.ensureAudioModeUpdatesOnForegroundCallChange()) { + // Skip if the new behavior isn't in use. + return; + } + // Start with an incoming PSTN call + Call pstnCall = mock(Call.class); + when(pstnCall.getState()).thenReturn(CallState.RINGING); + when(pstnCall.getIsVoipAudioMode()).thenReturn(false); + ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor = makeNewCaptor(); + + // Add the call + mCallAudioManager.onCallAdded(pstnCall); + verify(mCallAudioModeStateMachine).sendMessageWithArgs( + eq(CallAudioModeStateMachine.FOREGROUND_VOIP_MODE_CHANGE), captor.capture()); + CallAudioModeStateMachine.MessageArgs expectedArgs = + new Builder() + .setHasActiveOrDialingCalls(false) + .setHasRingingCalls(true) + .setHasHoldingCalls(false) + .setIsTonePlaying(false) + .setHasAudioProcessingCalls(false) + .setForegroundCallIsVoip(false) + .setSession(null) + .setForegroundCallIsVoip(false) + .build(); + assertMessageArgEquality(expectedArgs, captor.getValue()); + clearInvocations(mCallAudioModeStateMachine); // Avoid verifying for previous calls + + // Make call active; don't expect there to be an audio mode transition. + when(pstnCall.getState()).thenReturn(CallState.ACTIVE); + mCallAudioManager.onCallStateChanged(pstnCall, CallState.RINGING, CallState.ACTIVE); + verify(mCallAudioModeStateMachine, never()).sendMessageWithArgs( + eq(CallAudioModeStateMachine.FOREGROUND_VOIP_MODE_CHANGE), + any(CallAudioModeStateMachine.MessageArgs.class)); + clearInvocations(mCallAudioModeStateMachine); // Avoid verifying for previous calls + + // Add a new Voip call in ringing state; this should not result in a direct audio mode + // change. + Call voipCall = mock(Call.class); + when(voipCall.getState()).thenReturn(CallState.RINGING); + when(voipCall.getIsVoipAudioMode()).thenReturn(true); + mCallAudioManager.onCallAdded(voipCall); + verify(mCallAudioModeStateMachine, never()).sendMessageWithArgs( + eq(CallAudioModeStateMachine.FOREGROUND_VOIP_MODE_CHANGE), + any(CallAudioModeStateMachine.MessageArgs.class)); + clearInvocations(mCallAudioModeStateMachine); // Avoid verifying for previous calls + + // Make voip call active and set the PSTN call to locally disconnecting; the new foreground + // call will be the voip call. + when(pstnCall.isLocallyDisconnecting()).thenReturn(true); + when(voipCall.getState()).thenReturn(CallState.ACTIVE); + mCallAudioManager.onCallStateChanged(voipCall, CallState.RINGING, CallState.ACTIVE); + verify(mCallAudioModeStateMachine).sendMessageWithArgs( + eq(CallAudioModeStateMachine.FOREGROUND_VOIP_MODE_CHANGE), captor.capture()); + CallAudioModeStateMachine.MessageArgs expectedArgs2 = + new Builder() + .setHasActiveOrDialingCalls(true) + .setHasRingingCalls(false) + .setHasHoldingCalls(false) + .setIsTonePlaying(false) + .setHasAudioProcessingCalls(false) + .setForegroundCallIsVoip(false) + .setSession(null) + .setForegroundCallIsVoip(true) + .build(); + assertMessageArgEquality(expectedArgs2, captor.getValue()); + } + private Call createSimulatedRingingCall() { Call call = mock(Call.class); when(call.getState()).thenReturn(CallState.SIMULATED_RINGING); @@ -765,7 +869,7 @@ public class CallAudioManagerTest extends TelecomTestCase { "", "", "", ToneGenerator.TONE_PROP_PROMPT)); mCallAudioManager.onCallStateChanged(call, CallState.ACTIVE, CallState.DISCONNECTED); - verify(mPlayerFactory).createPlayer(InCallTonePlayer.TONE_CALL_ENDED); + verify(mPlayerFactory).createPlayer(any(Call.class), eq(InCallTonePlayer.TONE_CALL_ENDED)); correctArgs = new Builder() .setHasActiveOrDialingCalls(false) .setHasRingingCalls(false) @@ -782,10 +886,10 @@ public class CallAudioManagerTest extends TelecomTestCase { assertMessageArgEquality(correctArgs, captor.getValue()); } - private void stopTone() { + private void stopTone(Call call) { ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor = ArgumentCaptor.forClass(CallAudioModeStateMachine.MessageArgs.class); - mCallAudioManager.setIsTonePlaying(false); + mCallAudioManager.setIsTonePlaying(call, false); CallAudioModeStateMachine.MessageArgs correctArgs = new Builder() .setHasActiveOrDialingCalls(false) .setHasRingingCalls(false) diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java index d7854a5a9..cddf2ad85 100644 --- a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java +++ b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java @@ -16,14 +16,30 @@ package com.android.server.telecom.tests; +import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST; +import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.HandlerThread; import android.test.suitebuilder.annotation.SmallTest; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioModeStateMachine; -import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallAudioModeStateMachine.MessageArgs.Builder; +import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.SystemStateHelper; import org.junit.After; @@ -31,18 +47,9 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(JUnit4.class) public class CallAudioModeStateMachineTest extends TelecomTestCase { private static final int TEST_TIMEOUT = 1000; @@ -51,6 +58,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Mock private AudioManager mAudioManager; @Mock private CallAudioManager mCallAudioManager; @Mock private CallAudioRouteStateMachine mCallAudioRouteStateMachine; + @Mock private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; private HandlerThread mTestThread; @@ -60,8 +68,9 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { mTestThread = new HandlerThread("CallAudioModeStateMachineTest"); mTestThread.start(); super.setUp(); - when(mCallAudioManager.getCallAudioRouteStateMachine()) + when(mCallAudioManager.getCallAudioRouteAdapter()) .thenReturn(mCallAudioRouteStateMachine); + when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); } @Override @@ -76,7 +85,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testNoFocusWhenRingerSilenced() throws Throwable { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -108,7 +117,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testSwitchToStreamingMode() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -138,7 +147,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testExitStreamingMode() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ENTER_STREAMING_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -166,7 +175,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testNoRingWhenDeviceIsAtEar() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); sm.sendMessage(CallAudioModeStateMachine.NEW_HOLDING_CALL, new Builder() @@ -202,7 +211,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testRegainFocusWhenHfpIsConnectedSilenced() throws Throwable { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -246,7 +255,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testDoNotRingTwiceWhenHfpConnected() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -284,7 +293,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testStartRingingAfterHfpConnectedIfNotAlreadyPlaying() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); @@ -318,7 +327,46 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { verify(mCallAudioManager, times(2)).startRinging(); } + @SmallTest + @Test + public void testAudioFocusRequestWithResolveHiddenDependencies() { + CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); + when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true); + ArgumentCaptor<AudioFocusRequest> captor = ArgumentCaptor.forClass(AudioFocusRequest.class); + sm.setCallAudioManager(mCallAudioManager); + + resetMocks(); + when(mCallAudioManager.startRinging()).thenReturn(true); + when(mCallAudioManager.isRingtonePlaying()).thenReturn(false); + + sm.sendMessage(CallAudioModeStateMachine.ENTER_RING_FOCUS_FOR_TESTING); + waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); + verify(mAudioManager).requestAudioFocus(captor.capture()); + assertTrue(areAudioFocusRequestsMatch(captor.getValue(), RING_AUDIO_FOCUS_REQUEST)); + + sm.sendMessage(CallAudioModeStateMachine.ENTER_CALL_FOCUS_FOR_TESTING); + waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); + verify(mAudioManager, atLeast(1)).requestAudioFocus(captor.capture()); + AudioFocusRequest request = captor.getValue(); + assertTrue(areAudioFocusRequestsMatch(request, CALL_AUDIO_FOCUS_REQUEST)); + + sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); + } + private void resetMocks() { clearInvocations(mCallAudioManager, mAudioManager); } + + private boolean areAudioFocusRequestsMatch(AudioFocusRequest r1, AudioFocusRequest r2) { + if ((r1 == null) || (r2 == null)) { + return false; + } + + if (r1.getFocusGain() != r2.getFocusGain()) { + return false; + } + + return r1.getAudioAttributes().equals(r2.getAudioAttributes()); + } } diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java index c7e5aa9b3..3690d5f11 100644 --- a/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java +++ b/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java @@ -16,10 +16,15 @@ package com.android.server.telecom.tests; +import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST; +import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST; + +import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.HandlerThread; import android.test.suitebuilder.annotation.SmallTest; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioModeStateMachine; import com.android.server.telecom.CallAudioModeStateMachine.MessageArgs; @@ -37,6 +42,7 @@ import java.util.Collection; import java.util.List; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; @@ -103,6 +109,7 @@ public class CallAudioModeTransitionTests extends TelecomTestCase { @Mock private SystemStateHelper mSystemStateHelper; @Mock private AudioManager mAudioManager; @Mock private CallAudioManager mCallAudioManager; + @Mock private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; private final ModeTestParameters mParams; private HandlerThread mTestThread; @@ -130,13 +137,14 @@ public class CallAudioModeTransitionTests extends TelecomTestCase { @SmallTest public void modeTransitionTest() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, - mAudioManager, mTestThread.getLooper()); + mAudioManager, mTestThread.getLooper(), mFeatureFlags, mCommunicationDeviceTracker); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(mParams.initialAudioState); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); resetMocks(); when(mCallAudioManager.startRinging()).thenReturn(true); + when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); if (mParams.initialAudioState == CallAudioModeStateMachine.ENTER_AUDIO_PROCESSING_FOCUS_FOR_TESTING) { when(mAudioManager.getMode()) diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java index 4a9b7421f..1fa14a559 100644 --- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java +++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java @@ -16,6 +16,27 @@ package com.android.server.telecom.tests; +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.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; @@ -29,15 +50,16 @@ import android.telecom.CallAudioState; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; -import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.Call; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; +import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallsManager; import com.android.server.telecom.ConnectionServiceWrapper; -import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.StatusBarNotifier; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.WiredHeadsetManager; +import com.android.server.telecom.bluetooth.BluetoothRouteManager; import org.junit.After; import org.junit.Before; @@ -50,6 +72,7 @@ import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -57,25 +80,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(JUnit4.class) public class CallAudioRouteStateMachineTest extends TelecomTestCase { @@ -95,12 +99,14 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { @Mock Call fakeSelfManagedCall; @Mock Call fakeCall; @Mock CallAudioManager mockCallAudioManager; + @Mock BluetoothDevice mockWatchDevice; private CallAudioManager.AudioServiceFactory mAudioServiceFactory; private static final int TEST_TIMEOUT = 500; private AudioManager mockAudioManager; private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; private HandlerThread mThreadHandler; + CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; @Override @Before @@ -111,6 +117,8 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mThreadHandler.start(); mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); mockAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + mCommunicationDeviceTracker = new CallAudioCommunicationDeviceTracker(mContext); + mCommunicationDeviceTracker.setBluetoothRouteManager(mockBluetoothRouteManager); mAudioServiceFactory = new CallAudioManager.AudioServiceFactory() { @Override @@ -130,9 +138,12 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { when(fakeSelfManagedCall.isAlive()).thenReturn(true); when(fakeSelfManagedCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL); when(fakeSelfManagedCall.isSelfManaged()).thenReturn(true); + when(mFeatureFlags.transitRouteBeforeAudioDisconnectBt()).thenReturn(false); doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class), any(CallAudioState.class)); + when(mFeatureFlags.ignoreAutoRouteToWatchDevice()).thenReturn(false); + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(false); } @Override @@ -155,7 +166,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT, mThreadHandler.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); // Since we don't know if we're on a platform with an earpiece or not, all we can do // is ensure the stateMachine construction didn't fail. But at least we exercised the @@ -174,11 +187,63 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + Set<Call> trackedCalls = new HashSet<>(Arrays.asList(fakeCall, fakeSelfManagedCall)); + when(mockCallsManager.getTrackedCalls()).thenReturn(trackedCalls); + + // start state --> ROUTE_EARPIECE + CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); + stateMachine.initialize(initState); + + stateMachine.setCallAudioManager(mockCallAudioManager); + + assertEquals(stateMachine.getCurrentCallAudioState().getRoute(), + CallAudioRouteStateMachine.ROUTE_EARPIECE); + + // ROUTE_EARPIECE --> ROUTE_SPEAKER + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_SPEAKER, + CallAudioRouteStateMachine.SPEAKER_ON); + + stateMachine.sendMessageWithSessionInfo( + CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); + + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // assert expected end state + assertEquals(stateMachine.getCurrentCallAudioState().getRoute(), + CallAudioRouteStateMachine.ROUTE_SPEAKER); + // should update the audio route on all tracked calls ... + verify(mockConnectionServiceWrapper, times(trackedCalls.size())) + .onCallAudioStateChanged(any(), any()); + } + + @SmallTest + @Test + public void testSystemAudioStateIsNotUpdatedFlagOff() { + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); Set<Call> trackedCalls = new HashSet<>(Arrays.asList(fakeCall, fakeSelfManagedCall)); when(mockCallsManager.getTrackedCalls()).thenReturn(trackedCalls); + when(mFeatureFlags.availableRoutesNeverUpdatedAfterSetSystemAudioState()).thenReturn(false); // start state --> ROUTE_EARPIECE CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, @@ -200,12 +265,69 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + CallAudioState expectedCallAudioState = stateMachine.getLastKnownCallAudioState(); + // assert expected end state assertEquals(stateMachine.getCurrentCallAudioState().getRoute(), CallAudioRouteStateMachine.ROUTE_SPEAKER); // should update the audio route on all tracked calls ... verify(mockConnectionServiceWrapper, times(trackedCalls.size())) .onCallAudioStateChanged(any(), any()); + + assertNotEquals(expectedCallAudioState, stateMachine.getCurrentCallAudioState()); + } + + @SmallTest + @Test + public void testSystemAudioStateIsUpdatedFlagOn() { + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + Set<Call> trackedCalls = new HashSet<>(Arrays.asList(fakeCall, fakeSelfManagedCall)); + when(mockCallsManager.getTrackedCalls()).thenReturn(trackedCalls); + when(mFeatureFlags.availableRoutesNeverUpdatedAfterSetSystemAudioState()).thenReturn(true); + + // start state --> ROUTE_EARPIECE + CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); + stateMachine.initialize(initState); + + stateMachine.setCallAudioManager(mockCallAudioManager); + + assertEquals(stateMachine.getCurrentCallAudioState().getRoute(), + CallAudioRouteStateMachine.ROUTE_EARPIECE); + + // ROUTE_EARPIECE --> ROUTE_SPEAKER + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_SPEAKER, + CallAudioRouteStateMachine.SPEAKER_ON); + + stateMachine.sendMessageWithSessionInfo( + CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); + + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + CallAudioState expectedCallAudioState = stateMachine.getLastKnownCallAudioState(); + + // assert expected end state + assertEquals(stateMachine.getCurrentCallAudioState().getRoute(), + CallAudioRouteStateMachine.ROUTE_SPEAKER); + // should update the audio route on all tracked calls ... + verify(mockConnectionServiceWrapper, times(trackedCalls.size())) + .onCallAudioStateChanged(any(), any()); + + assertEquals(expectedCallAudioState, stateMachine.getCurrentCallAudioState()); } @MediumTest @@ -219,7 +341,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); @@ -263,7 +388,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); @@ -286,14 +414,14 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioState expectedMiddleState = new CallAudioState(false, CallAudioState.ROUTE_WIRED_HEADSET, CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_SPEAKER); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verifyNewSystemCallAudioState(initState, expectedMiddleState); resetMocks(); stateMachine.sendMessageWithSessionInfo( CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verifyNewSystemCallAudioState(expectedMiddleState, initState); } @@ -308,7 +436,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); @@ -329,7 +460,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioState.ROUTE_EARPIECE, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verifyNewSystemCallAudioState(initState, expectedEndState); resetMocks(); stateMachine.sendMessageWithSessionInfo( @@ -337,7 +468,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { stateMachine.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState()); } @@ -352,7 +483,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); Collection<BluetoothDevice> availableDevices = Collections.singleton(bluetoothDevice1); @@ -377,12 +511,12 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, null, availableDevices); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verifyNewSystemCallAudioState(initState, expectedMidState); // clear out the handler state before resetting mocks in order to avoid introducing a // CallAudioState that has a null list of supported BT devices - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); resetMocks(); // Now, switch back to BT explicitly @@ -400,9 +534,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, bluetoothDevice1, availableDevices); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); // second wait needed for the BT_AUDIO_CONNECTED message - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verifyNewSystemCallAudioState(expectedMidState, expectedEndState); stateMachine.sendMessageWithSessionInfo( @@ -412,9 +546,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { stateMachine.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); // second wait needed for the BT_AUDIO_CONNECTED message - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); // Verify that we're still on bluetooth. assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState()); } @@ -430,7 +564,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); @@ -445,13 +582,13 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, CallAudioRouteStateMachine.RINGING_FOCUS); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(nullable(String.class)); stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, CallAudioRouteStateMachine.ACTIVE_FOCUS); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(nullable(String.class)); } @@ -466,7 +603,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); setInBandRing(false); when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); @@ -480,7 +620,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioRouteStateMachine.RINGING_FOCUS); // Wait for the state machine to finish transiting to ActiveEarpiece before hooking up // bluetooth mocks - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); when(mockBluetoothRouteManager.getConnectedDevices()) @@ -489,7 +629,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED); stateMachine.sendMessageWithSessionInfo( CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null); CallAudioState expectedEndState = new CallAudioState(false, @@ -500,14 +640,17 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, CallAudioRouteStateMachine.ACTIVE_FOCUS); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(null); when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice()) .thenReturn(bluetoothDevice1); stateMachine.sendMessage(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); - verify(mockCallAudioManager, times(1)).onRingerModeChange(); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + // It is possible that this will be called twice from ActiveBluetoothRoute#enter. The extra + // call to setBluetoothOn will trigger BT_AUDIO_CONNECTED, which also ends up invoking + // CallAudioManager#onRingerModeChange. + verify(mockCallAudioManager, atLeastOnce()).onRingerModeChange(); } @SmallTest @@ -521,7 +664,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); List<BluetoothDevice> availableDevices = Arrays.asList(bluetoothDevice1, bluetoothDevice2, bluetoothDevice3); @@ -547,17 +693,80 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.USER_SWITCH_BLUETOOTH, 0, bluetoothDevice2.getAddress()); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verify(mockBluetoothRouteManager).connectBluetoothAudio(bluetoothDevice2.getAddress()); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); CallAudioState expectedEndState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, bluetoothDevice2, availableDevices); - verifyNewSystemCallAudioState(initState, expectedEndState); + assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState()); + } + + @SmallTest + @Test + public void testCallDisconnectedWhenAudioRoutedToBluetooth() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + List<BluetoothDevice> availableDevices = Arrays.asList(bluetoothDevice1); + + when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false); + when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); + when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); + when(mockBluetoothRouteManager.getConnectedDevices()).thenReturn(availableDevices); + when(mockBluetoothRouteManager.isInbandRingingEnabled()).thenReturn(true); + when(mFeatureFlags.transitRouteBeforeAudioDisconnectBt()).thenReturn(true); + doAnswer(invocation -> { + when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice()) + .thenReturn(bluetoothDevice1); + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); + return null; + }).when(mockBluetoothRouteManager).connectBluetoothAudio(bluetoothDevice1.getAddress()); + doAnswer(invocation -> { + when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice()) + .thenReturn(bluetoothDevice1); + stateMachine.sendMessageWithSessionInfo( + CallAudioRouteStateMachine.BT_AUDIO_DISCONNECTED); + return null; + }).when(mockBluetoothRouteManager).disconnectAudio(); + + CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, null, + availableDevices); + stateMachine.initialize(initState); + + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.NO_FOCUS, bluetoothDevice1.getAddress()); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + verify(mockBluetoothRouteManager).disconnectAudio(); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + CallAudioState expectedEndState = new CallAudioState(false, + CallAudioState.ROUTE_BLUETOOTH, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, + bluetoothDevice1, + availableDevices); + + assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState()); } @SmallTest @@ -571,7 +780,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false); CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, @@ -580,13 +792,13 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { // Raise a dock connect event. stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_DOCK); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); assertTrue(!stateMachine.isInActiveState()); verify(mockAudioManager, never()).setSpeakerphoneOn(eq(true)); // Raise a dock disconnect event. stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.DISCONNECT_DOCK); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); assertTrue(!stateMachine.isInActiveState()); verify(mockAudioManager, never()).setSpeakerphoneOn(eq(false)); } @@ -602,7 +814,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false); @@ -614,7 +829,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { // Switch to active, pretending that a call came in. stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, CallAudioRouteStateMachine.ACTIVE_FOCUS); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); // Make sure that we've successfully switched to the active speaker route and that we've // called setSpeakerOn @@ -636,7 +851,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mockStatusBarNotifier, mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, - Runnable::run /** do async stuff sync for test purposes */); + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); List<BluetoothDevice> availableDevices = Arrays.asList(bluetoothDevice1, bluetoothDevice2); @@ -658,7 +876,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { // Switch to active, pretending that a call came in. stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, CallAudioRouteStateMachine.ACTIVE_FOCUS); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); // Make sure that we've successfully switched to the active BT route and that we've // called connectAudio on the right device. @@ -669,6 +887,112 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { @SmallTest @Test + public void testSetAndClearEarpieceCommunicationDevice() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + AudioDeviceInfo earpiece = mock(AudioDeviceInfo.class); + when(earpiece.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE); + when(earpiece.getAddress()).thenReturn(""); + List<AudioDeviceInfo> devices = new ArrayList<>(); + devices.add(earpiece); + + when(mockAudioManager.getAvailableCommunicationDevices()) + .thenReturn(devices); + when(mockAudioManager.setCommunicationDevice(eq(earpiece))) + .thenReturn(true); + when(mockAudioManager.getCommunicationDevice()).thenReturn(earpiece); + + CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER | + CallAudioState.ROUTE_WIRED_HEADSET); + stateMachine.initialize(initState); + + // Switch to active + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // Make sure that we've successfully switched to the active earpiece and that we set the + // communication device. + assertTrue(stateMachine.isInActiveState()); + ArgumentCaptor<AudioDeviceInfo> infoArgumentCaptor = ArgumentCaptor.forClass( + AudioDeviceInfo.class); + verify(mockAudioManager).setCommunicationDevice(infoArgumentCaptor.capture()); + assertEquals(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, + infoArgumentCaptor.getValue().getType()); + + // Route earpiece to speaker + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_SPEAKER, + CallAudioRouteStateMachine.SPEAKER_ON); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // Assert that communication device was cleared + verify(mockAudioManager).clearCommunicationDevice(); + } + + @SmallTest + @Test + public void testSetAndClearWiredHeadsetCommunicationDevice() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + verifySetAndClearHeadsetCommunicationDevice(AudioDeviceInfo.TYPE_WIRED_HEADSET); + } + + @SmallTest + @Test + public void testSetAndClearUsbHeadsetCommunicationDevice() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + verifySetAndClearHeadsetCommunicationDevice(AudioDeviceInfo.TYPE_USB_HEADSET); + } + + @SmallTest + @Test + public void testActiveFocusRouteSwitchFromQuiescentBluetooth() { + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + // Start the route in quiescent and ensure that a switch to ACTIVE_FOCUS transitions to + // the corresponding active route even when there aren't any active BT devices available. + CallAudioState initState = new CallAudioState(false, + CallAudioState.ROUTE_BLUETOOTH, + CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE); + stateMachine.initialize(initState); + + // Switch to active + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // Make sure that we've successfully switched to the active route on BT + assertTrue(stateMachine.isInActiveState()); + } + + @SmallTest + @Test public void testInitializationWithEarpieceNoHeadsetNoBluetooth() { CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); @@ -752,7 +1076,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, mThreadHandler.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.initialize(); assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); } @@ -769,7 +1095,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, mThreadHandler.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, @@ -780,12 +1108,12 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { CallAudioState expectedEndState = new CallAudioState(false, CallAudioState.ROUTE_STREAMING, CallAudioState.ROUTE_STREAMING); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); verifyNewSystemCallAudioState(initState, expectedEndState); resetMocks(); stateMachine.sendMessageWithSessionInfo( CallAudioRouteStateMachine.STREAMING_FORCE_DISABLED); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); assertEquals(initState, stateMachine.getCurrentCallAudioState()); } @@ -805,7 +1133,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mAudioServiceFactory, CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, mThreadHandler.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, @@ -830,6 +1160,154 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); } + @MediumTest + @Test + public void testIgnoreImplicitBTSwitchWhenDeviceIsWatch() { + when(mFeatureFlags.ignoreAutoRouteToWatchDevice()).thenReturn(true); + when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + AudioDeviceInfo headset = mock(AudioDeviceInfo.class); + when(headset.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); + when(headset.getAddress()).thenReturn(""); + List<AudioDeviceInfo> devices = new ArrayList<>(); + devices.add(headset); + + when(mockAudioManager.getAvailableCommunicationDevices()) + .thenReturn(devices); + when(mockAudioManager.setCommunicationDevice(eq(headset))) + .thenReturn(true); + when(mockAudioManager.getCommunicationDevice()).thenReturn(headset); + + CallAudioState initState = new CallAudioState(false, + CallAudioState.ROUTE_WIRED_HEADSET, CallAudioState.ROUTE_WIRED_HEADSET + | CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); + stateMachine.initialize(initState); + + // Switch to active + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // Make sure that we've successfully switched to the active headset. + assertTrue(stateMachine.isInActiveState()); + ArgumentCaptor<AudioDeviceInfo> infoArgumentCaptor = ArgumentCaptor.forClass( + AudioDeviceInfo.class); + verify(mockAudioManager).setCommunicationDevice(infoArgumentCaptor.capture()); + assertEquals(AudioDeviceInfo.TYPE_WIRED_HEADSET, infoArgumentCaptor.getValue().getType()); + + // Set up watch device as only available BT device. + Collection<BluetoothDevice> availableDevices = Collections.singleton(mockWatchDevice); + + when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); + when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); + when(mockBluetoothRouteManager.getConnectedDevices()).thenReturn(availableDevices); + when(mockBluetoothRouteManager.isWatch(any(BluetoothDevice.class))).thenReturn(true); + + // Disconnect wired headset to force switch to BT (verify that we ignore the implicit switch + // to BT when the watch is the only connected device and that we move into the next + // available route. + stateMachine.sendMessageWithSessionInfo( + CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, + null, availableDevices); + assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); + } + + @SmallTest + @Test + public void testQuiescentBluetoothRouteResetMute() { + when(mFeatureFlags.resetMuteWhenEnteringQuiescentBtRoute()).thenReturn(true); + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + CallAudioState initState = new CallAudioState(false, + CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_SPEAKER + | CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); + stateMachine.initialize(initState); + + // Switch to active and mute + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + assertTrue(stateMachine.isInActiveState()); + + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.MUTE_ON); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + CallAudioState expectedState = new CallAudioState(true, + CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_SPEAKER + | CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); + assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); + + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.NO_FOCUS); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + expectedState = new CallAudioState(false, + CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_SPEAKER + | CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); + // TODO: Re-enable this part of the test; this is now failing because we have to + // revert ag/23783145. + // assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); + } + + @SmallTest + @Test + public void testSupportRouteMaskUpdateWhenBtAudioConnected() { + when(mFeatureFlags.updateRouteMaskWhenBtConnected()).thenReturn(true); + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + CallAudioState initState = new CallAudioState(false, + CallAudioState.ROUTE_EARPIECE, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); + stateMachine.initialize(initState); + + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, + CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER + | CallAudioState.ROUTE_BLUETOOTH); + assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); + } + private void initializationTestHelper(CallAudioState expectedState, int earpieceControl) { when(mockWiredHeadsetManager.isPluggedIn()).thenReturn( @@ -848,7 +1326,9 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { mAudioServiceFactory, earpieceControl, mThreadHandler.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.initialize(); assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); } @@ -888,4 +1368,59 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase { doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class), any(CallAudioState.class)); } + + private void verifySetAndClearHeadsetCommunicationDevice(int audioType) { + CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( + mContext, + mockCallsManager, + mockBluetoothRouteManager, + mockWiredHeadsetManager, + mockStatusBarNotifier, + mAudioServiceFactory, + CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, + mThreadHandler.getLooper(), + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); + stateMachine.setCallAudioManager(mockCallAudioManager); + + AudioDeviceInfo headset = mock(AudioDeviceInfo.class); + when(headset.getType()).thenReturn(audioType); + when(headset.getAddress()).thenReturn(""); + List<AudioDeviceInfo> devices = new ArrayList<>(); + devices.add(headset); + + when(mockAudioManager.getAvailableCommunicationDevices()) + .thenReturn(devices); + when(mockAudioManager.setCommunicationDevice(eq(headset))) + .thenReturn(true); + when(mockAudioManager.getCommunicationDevice()).thenReturn(headset); + + CallAudioState initState = new CallAudioState(false, + CallAudioState.ROUTE_WIRED_HEADSET, + CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_EARPIECE); + stateMachine.initialize(initState); + + // Switch to active + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // Make sure that we've successfully switched to the active headset and that we set the + // communication device. + assertTrue(stateMachine.isInActiveState()); + ArgumentCaptor<AudioDeviceInfo> infoArgumentCaptor = ArgumentCaptor.forClass( + AudioDeviceInfo.class); + verify(mockAudioManager).setCommunicationDevice(infoArgumentCaptor.capture()); + assertEquals(audioType, infoArgumentCaptor.getValue().getType()); + + // Route out of headset route + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, + CallAudioRouteStateMachine.ACTIVE_FOCUS); + stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.USER_SWITCH_EARPIECE); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + + // Assert that communication device was cleared + verify(mockAudioManager).clearCommunicationDevice(); + } } diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java index cf684debb..25c4e9f15 100644 --- a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java +++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -40,6 +41,7 @@ import android.telecom.CallAudioState; import android.test.suitebuilder.annotation.SmallTest; import com.android.server.telecom.Call; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallsManager; @@ -155,6 +157,7 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { @Mock StatusBarNotifier mockStatusBarNotifier; @Mock Call fakeCall; @Mock CallAudioManager mockCallAudioManager; + private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; private CallAudioManager.AudioServiceFactory mAudioServiceFactory; private static final int TEST_TIMEOUT = 500; private AudioManager mockAudioManager; @@ -174,6 +177,8 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { mHandlerThread.start(); mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); mockAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + mCommunicationDeviceTracker = new CallAudioCommunicationDeviceTracker(mContext); + mCommunicationDeviceTracker.setBluetoothRouteManager(mockBluetoothRouteManager); mAudioServiceFactory = new CallAudioManager.AudioServiceFactory() { @Override @@ -270,7 +275,9 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { mAudioServiceFactory, mParams.earpieceControl, mHandlerThread.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); setupMocksForParams(stateMachine, mParams); @@ -288,17 +295,17 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { if (mParams.initialRoute == CallAudioState.ROUTE_BLUETOOTH) { stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED); } - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); // Clear invocations on mocks to discard stuff from initialization clearInvocations(); sendActionToStateMachine(stateMachine); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); - Handler h = stateMachine.getHandler(); + Handler h = stateMachine.getAdapterHandler(); waitForHandlerAction(h, TEST_TIMEOUT); stateMachine.quitStateMachine(); @@ -311,7 +318,7 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { break; case ON: if (mParams.expectedBluetoothDevice == null) { - verify(mockBluetoothRouteManager).connectBluetoothAudio(null); + verify(mockBluetoothRouteManager, atLeastOnce()).connectBluetoothAudio(null); } else { verify(mockBluetoothRouteManager).connectBluetoothAudio( mParams.expectedBluetoothDevice.getAddress()); @@ -367,7 +374,9 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { mAudioServiceFactory, mParams.earpieceControl, mHandlerThread.getLooper(), - Runnable::run /** do async stuff sync for test purposes */); + Runnable::run /** do async stuff sync for test purposes */, + mCommunicationDeviceTracker, + mFeatureFlags); stateMachine.setCallAudioManager(mockCallAudioManager); // Set up bluetooth and speakerphone state @@ -388,8 +397,8 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase { // Omit the focus-getting statement sendActionToStateMachine(stateMachine); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); - waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); + waitForHandlerAction(stateMachine.getAdapterHandler(), TEST_TIMEOUT); stateMachine.quitStateMachine(); diff --git a/tests/src/com/android/server/telecom/tests/CallEndpointControllerTest.java b/tests/src/com/android/server/telecom/tests/CallEndpointControllerTest.java index f4008aa83..9101a19eb 100644 --- a/tests/src/com/android/server/telecom/tests/CallEndpointControllerTest.java +++ b/tests/src/com/android/server/telecom/tests/CallEndpointControllerTest.java @@ -17,6 +17,7 @@ package com.android.server.telecom.tests; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -50,7 +51,9 @@ import org.mockito.Mock; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; @RunWith(JUnit4.class) public class CallEndpointControllerTest extends TelecomTestCase { @@ -81,6 +84,9 @@ public class CallEndpointControllerTest extends TelecomTestCase { availableBluetooth1); private static final CallAudioState audioState7 = new CallAudioState(false, CallAudioState.ROUTE_STREAMING, CallAudioState.ROUTE_ALL, null, availableBluetooth1); + private static final CallAudioState audioState8 = new CallAudioState(false, + CallAudioState.ROUTE_EARPIECE, CallAudioState.ROUTE_ALL, bluetoothDevice1, + availableBluetooth2); private CallEndpointController mCallEndpointController; @@ -177,6 +183,74 @@ public class CallEndpointControllerTest extends TelecomTestCase { verify(mConnectionService, never()).onMuteStateChanged(any(), anyBoolean()); } + /** + * Ensure that {@link CallAudioManager#setAudioRoute(int, String)} is invoked when the user + * requests to switch to a bluetooth CallEndpoint. This is an edge case where bluetooth is not + * the current CallEndpoint but the CallAudioState shows the bluetooth device is + * active/available. + */ + @Test + public void testSwitchFromEarpieceToBluetooth() { + // simulate an audio state where the EARPIECE is active but a bluetooth device is active. + mCallEndpointController.onCallAudioStateChanged(null, audioState8 /* Ear but BT active */); + CallEndpoint btEndpoint = mCallEndpointController.getAvailableEndpoints().stream() + .filter(e -> e.getEndpointType() == CallEndpoint.TYPE_BLUETOOTH) + .toList().get(0); // get the only available BT endpoint + + // verify the CallEndpointController shows EARPIECE active + BT endpoint is active device + assertEquals(CallEndpoint.TYPE_EARPIECE, + mCallEndpointController.getCurrentCallEndpoint().getEndpointType()); + assertNotNull(btEndpoint); + + // request an endpoint change from earpiece to the bluetooth + doReturn(audioState8).when(mCallAudioManager).getCallAudioState(); + mCallEndpointController.requestCallEndpointChange(btEndpoint, mResultReceiver); + + // verify the transaction was successful and CallAudioManager#setAudioRoute was called + verify(mResultReceiver, never()).send(eq(CallEndpoint.ENDPOINT_OPERATION_FAILED), any()); + verify(mCallAudioManager, times(1)).setAudioRoute(eq(CallAudioState.ROUTE_BLUETOOTH), + eq(bluetoothDevice1.getAddress())); + } + + + /** + * Ensure that {@link CallAudioManager#setAudioRoute(int, String)} is invoked when the user + * requests to switch to from one bluetooth device to another. + */ + @Test + public void testBtDeviceSwitch() { + // bluetoothDevice1 should start as active and bluetoothDevice2 is available + mCallEndpointController.onCallAudioStateChanged(null, audioState2 /* BT active D1 */); + CallEndpoint currentEndpoint = mCallEndpointController.getCurrentCallEndpoint(); + List<CallEndpoint> btEndpoints = mCallEndpointController.getAvailableEndpoints().stream() + .filter(e -> e.getEndpointType() == CallEndpoint.TYPE_BLUETOOTH) + .toList(); // get the only available BT endpoint + + // verify the initial state of the test + assertEquals(2, btEndpoints.size()); + assertEquals(CallEndpoint.TYPE_BLUETOOTH, currentEndpoint.getEndpointType()); + + CallEndpoint otherBluetoothEndpoint = null; + for (CallEndpoint e : btEndpoints) { + if (!e.equals(currentEndpoint)) { + otherBluetoothEndpoint = e; + } + } + + assertNotNull(otherBluetoothEndpoint); + assertNotEquals(currentEndpoint, otherBluetoothEndpoint); + + // request an endpoint change from BT D1 --> BT D2 + doReturn(audioState2).when(mCallAudioManager).getCallAudioState(); + mCallEndpointController.requestCallEndpointChange(otherBluetoothEndpoint, mResultReceiver); + + // verify the transaction was successful and CallAudioManager#setAudioRoute was called + verify(mResultReceiver, never()).send(eq(CallEndpoint.ENDPOINT_OPERATION_FAILED), any()); + verify(mCallAudioManager, times(1)) + .setAudioRoute(eq(CallAudioState.ROUTE_BLUETOOTH), + eq(bluetoothDevice2.getAddress())); + } + @Test public void testAvailableEndpointChanged() throws Exception { mCallEndpointController.onCallAudioStateChanged(audioState1, audioState6); diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java index c68cbbf0b..c09d138d5 100644 --- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java +++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -36,6 +37,7 @@ import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; +import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Resources; import android.location.Country; @@ -73,6 +75,7 @@ import com.android.server.telecom.HandoverState; import com.android.server.telecom.MissedCallNotifier; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.TelephonyUtil; +import com.android.server.telecom.flags.FeatureFlags; import org.junit.After; import org.junit.Before; @@ -127,13 +130,16 @@ public class CallLogManagerTest extends TelecomTestCase { @Mock AnomalyReporterAdapter mAnomalyReporterAdapter; + @Mock + FeatureFlags mFeatureFlags; + @Override @Before public void setUp() throws Exception { super.setUp(); mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); mCallLogManager = new CallLogManager(mContext, mMockPhoneAccountRegistrar, - mMissedCallNotifier, mAnomalyReporterAdapter); + mMissedCallNotifier, mAnomalyReporterAdapter, mFeatureFlags); mDefaultAccountHandle = new PhoneAccountHandle( new ComponentName("com.android.server.telecom.tests", "CallLogManagerTest"), TEST_PHONE_ACCOUNT_ID, @@ -184,6 +190,9 @@ public class CallLogManagerTest extends TelecomTestCase { when(userManager.getUserInfo(eq(CURRENT_USER_ID))).thenReturn(userInfo); when(userManager.getUserInfo(eq(OTHER_USER_ID))).thenReturn(otherUserInfo); when(userManager.getUserInfo(eq(MANAGED_USER_ID))).thenReturn(managedProfileUserInfo); + PackageManager packageManager = mContext.getPackageManager(); + when(packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false); + when(mFeatureFlags.telecomLogExternalWearableCalls()).thenReturn(false); } @Override @@ -360,6 +369,7 @@ public class CallLogManagerTest extends TelecomTestCase { VIA_NUMBER_STRING, // viaNumber null ); + when(mFeatureFlags.addCallUriForMissedCalls()).thenReturn(true); mCallLogManager.onCallStateChanged(fakeIncomingCall, CallState.ACTIVE, CallState.DISCONNECTED); ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); @@ -369,7 +379,7 @@ public class CallLogManagerTest extends TelecomTestCase { @MediumTest @Test - public void testLogCallDirectionMissed() { + public void testLogCallDirectionMissedAddCallUriForMissedCallsFlagOff() { when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); Call fakeMissedCall = makeFakeCall( @@ -385,6 +395,7 @@ public class CallLogManagerTest extends TelecomTestCase { VIA_NUMBER_STRING, // viaNumber null ); + when(mFeatureFlags.addCallUriForMissedCalls()).thenReturn(false); mCallLogManager.onCallStateChanged(fakeMissedCall, CallState.ACTIVE, CallState.DISCONNECTED); @@ -393,7 +404,39 @@ public class CallLogManagerTest extends TelecomTestCase { Integer.valueOf(CallLog.Calls.MISSED_TYPE)); // Timeout needed because showMissedCallNotification is called from onPostExecute. verify(mMissedCallNotifier, timeout(TEST_TIMEOUT_MILLIS)) - .showMissedCallNotification(any(MissedCallNotifier.CallInfo.class)); + .showMissedCallNotification(any(MissedCallNotifier.CallInfo.class), + /* uri= */ eq(null)); + } + + @MediumTest + @Test + public void testLogCallDirectionMissedAddCallUriForMissedCallsFlagOn() { + when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) + .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); + Call fakeMissedCall = makeFakeCall( + DisconnectCause.MISSED, // disconnectCauseCode + false, // isConference + true, // isIncoming + 1L, // creationTimeMillis + 1000L, // ageMillis + TEL_PHONEHANDLE, // callHandle + mDefaultAccountHandle, // phoneAccountHandle + NO_VIDEO_STATE, // callVideoState + POST_DIAL_STRING, // postDialDigits + VIA_NUMBER_STRING, // viaNumber + null + ); + when(mFeatureFlags.addCallUriForMissedCalls()).thenReturn(true); + + mCallLogManager.onCallStateChanged(fakeMissedCall, CallState.ACTIVE, + CallState.DISCONNECTED); + ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); + assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), + Integer.valueOf(CallLog.Calls.MISSED_TYPE)); + // Timeout needed because showMissedCallNotification is called from onPostExecute. + verify(mMissedCallNotifier, timeout(TEST_TIMEOUT_MILLIS)) + .showMissedCallNotification(any(MissedCallNotifier.CallInfo.class), + /* uri= */ any(Uri.class)); } @MediumTest @@ -791,6 +834,34 @@ public class CallLogManagerTest extends TelecomTestCase { assertEquals(1, insertedValues.getAsInteger(Calls.IS_READ).intValue()); } + @Test + public void testLogCallWhenExternalCallOnWatch() { + when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) + .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); + PackageManager packageManager = mContext.getPackageManager(); + when(packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true); + when(mFeatureFlags.telecomLogExternalWearableCalls()).thenReturn(true); + Call fakeMissedCall = makeFakeCall( + DisconnectCause.REJECTED, // disconnectCauseCode + false, // isConference + true, // isIncoming + 1L, // creationTimeMillis + 1000L, // ageMillis + TEL_PHONEHANDLE, // callHandle + mDefaultAccountHandle, // phoneAccountHandle + NO_VIDEO_STATE, // callVideoState + POST_DIAL_STRING, // postDialDigits + VIA_NUMBER_STRING, // viaNumber + null + ); + when(fakeMissedCall.isExternalCall()).thenReturn(true); + + mCallLogManager.onCallStateChanged(fakeMissedCall, CallState.ACTIVE, + CallState.DISCONNECTED); + verifyInsertionWithCapture(CURRENT_USER_ID); + } + + @SmallTest @Test public void testCountryIso_setCache() { @@ -896,6 +967,56 @@ public class CallLogManagerTest extends TelecomTestCase { @SmallTest @Test + public void testDoNotLogCallExtra() { + when(mFeatureFlags.telecomSkipLogBasedOnExtra()).thenReturn(true); + Call fakeCall = makeFakeCall( + DisconnectCause.LOCAL, // disconnectCauseCode + false, // isConference + true, // isIncoming + 1L, // creationTimeMillis + 1000L, // ageMillis + TEL_PHONEHANDLE, // callHandle + mDefaultAccountHandle, // phoneAccountHandle + NO_VIDEO_STATE, // callVideoState + POST_DIAL_STRING, // postDialDigits + VIA_NUMBER_STRING, // viaNumber + UserHandle.of(CURRENT_USER_ID) + ); + Bundle extras = new Bundle(); + extras.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); + when(fakeCall.getExtras()).thenReturn(extras); + + assertFalse(mCallLogManager.shouldLogDisconnectedCall(fakeCall, CallState.DISCONNECTED, + false /* isCanceled */)); + } + + @SmallTest + @Test + public void testIgnoresDoNotLogCallExtra_whenFlagDisabled() { + when(mFeatureFlags.telecomSkipLogBasedOnExtra()).thenReturn(false); + Call fakeCall = makeFakeCall( + DisconnectCause.LOCAL, // disconnectCauseCode + false, // isConference + true, // isIncoming + 1L, // creationTimeMillis + 1000L, // ageMillis + TEL_PHONEHANDLE, // callHandle + mDefaultAccountHandle, // phoneAccountHandle + NO_VIDEO_STATE, // callVideoState + POST_DIAL_STRING, // postDialDigits + VIA_NUMBER_STRING, // viaNumber + UserHandle.of(CURRENT_USER_ID) + ); + Bundle extras = new Bundle(); + extras.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); + when(fakeCall.getExtras()).thenReturn(extras); + + assertTrue(mCallLogManager.shouldLogDisconnectedCall(fakeCall, CallState.DISCONNECTED, + false /* isCanceled */)); + } + + @SmallTest + @Test public void testDoNotLogConferenceWithChildren() { Call fakeCall = makeFakeCall( DisconnectCause.LOCAL, // disconnectCauseCode diff --git a/tests/src/com/android/server/telecom/tests/CallTest.java b/tests/src/com/android/server/telecom/tests/CallTest.java index 997e7dd2a..7a773748a 100644 --- a/tests/src/com/android/server/telecom/tests/CallTest.java +++ b/tests/src/com/android/server/telecom/tests/CallTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.argThat; @@ -34,10 +33,12 @@ import static org.mockito.Mockito.verify; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; +import android.os.UserHandle; import android.telecom.CallAttributes; import android.telecom.CallerInfo; import android.telecom.Connection; @@ -117,6 +118,7 @@ public class CallTest extends TelecomTestCase { doReturn(new ComponentName(mContext, CallTest.class)) .when(mMockConnectionService).getComponentName(); doReturn(mMockToast).when(mMockToastProxy).makeText(any(), anyInt(), anyInt()); + doReturn(UserHandle.CURRENT).when(mMockCallsManager).getCurrentUserHandle(); } @After @@ -200,7 +202,8 @@ public class CallTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, false /* isConference */, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); // To start with connection creation isn't complete. assertFalse(call.isCreateConnectionComplete()); @@ -338,7 +341,8 @@ public class CallTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, true /* isConference */, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); assertFalse(call.wasDndCheckComputedForCall()); assertFalse(call.isCallSuppressedByDoNotDisturb()); @@ -364,7 +368,8 @@ public class CallTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, true /* isConference */, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); assertNull(call.getConnectionServiceWrapper()); assertFalse(call.isTransactionalCall()); @@ -394,7 +399,8 @@ public class CallTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, true /* isConference */, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); // setup call.setIsTransactionalCall(true); @@ -728,6 +734,52 @@ public class CallTest extends TelecomTestCase { })); } + @Test + @SmallTest + public void testExcludesInCallServiceFromDoNotLogCallExtra() { + Call call = createCall("any"); + Bundle extra = new Bundle(); + extra.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); + + call.putInCallServiceExtras(extra, "packageName"); + + assertFalse(call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)); + } + + @Test + @SmallTest + public void testExcludesConnectionServiceWithoutModifyStatePermissionFromDoNotLogCallExtra() { + PackageManager packageManager = mContext.getPackageManager(); + Bundle extra = new Bundle(); + extra.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); + String packageName = SIM_1_HANDLE.getComponentName().getPackageName(); + doReturn(PackageManager.PERMISSION_DENIED) + .when(packageManager) + .checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, packageName); + Call call = createCall("any"); + + call.putConnectionServiceExtras(extra); + + assertFalse(call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)); + } + + @Test + @SmallTest + public void testDoesNotExcludeConnectionServiceWithModifyStatePermissionFromDoNotLogCallExtra() { + String packageName = SIM_1_HANDLE.getComponentName().getPackageName(); + Bundle extra = new Bundle(); + extra.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); + PackageManager packageManager = mContext.getPackageManager(); + doReturn(PackageManager.PERMISSION_GRANTED) + .when(packageManager) + .checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, packageName); + Call call = createCall("any"); + + call.putConnectionServiceExtras(extra); + + assertTrue(call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)); + } + private Call createCall(String id) { return createCall(id, Call.CALL_DIRECTION_UNDEFINED); } @@ -748,6 +800,7 @@ public class CallTest extends TelecomTestCase { false, false, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); } } diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java index 56cf22fee..6e0e660bf 100644 --- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java +++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java @@ -17,10 +17,8 @@ package com.android.server.telecom.tests; import static android.provider.CallLog.Calls.USER_MISSED_NOT_RUNNING; - import static junit.framework.Assert.assertNotNull; import static junit.framework.TestCase.fail; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -43,6 +41,7 @@ import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static java.lang.Thread.sleep; import android.Manifest; import android.content.ComponentName; @@ -54,6 +53,7 @@ import android.media.AudioManager; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.OutcomeReceiver; import android.os.Process; @@ -61,6 +61,7 @@ import android.os.ResultReceiver; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.BlockedNumberContract; import android.telecom.CallException; import android.telecom.CallScreeningService; @@ -80,10 +81,12 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; import android.widget.Toast; +import com.android.internal.telecom.IConnectionService; import com.android.server.telecom.AnomalyReporterAdapter; import com.android.server.telecom.AsyncRingtonePlayer; import com.android.server.telecom.Call; import com.android.server.telecom.CallAnomalyWatchdog; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioModeStateMachine; import com.android.server.telecom.CallAudioRouteStateMachine; @@ -97,6 +100,7 @@ import com.android.server.telecom.ClockProxy; import com.android.server.telecom.ConnectionServiceFocusManager; import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory; import com.android.server.telecom.ConnectionServiceWrapper; +import com.android.server.telecom.CreateConnectionResponse; import com.android.server.telecom.DefaultDialerCache; import com.android.server.telecom.EmergencyCallDiagnosticLogger; import com.android.server.telecom.EmergencyCallHelper; @@ -123,6 +127,9 @@ import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; import com.android.server.telecom.callfiltering.BlockedNumbersAdapter; import com.android.server.telecom.callfiltering.CallFilteringResult; +import com.android.server.telecom.callfiltering.IncomingCallFilterGraph; +import com.android.server.telecom.flags.FeatureFlags; +import com.android.server.telecom.flags.Flags; import com.android.server.telecom.ui.AudioProcessingNotification; import com.android.server.telecom.ui.CallStreamingNotification; import com.android.server.telecom.ui.DisconnectedCallNotifier; @@ -131,6 +138,7 @@ import com.android.server.telecom.voip.TransactionManager; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -276,8 +284,13 @@ public class CallsManagerTest extends TelecomTestCase { @Mock private Ringer.AccessibilityManagerAdapter mAccessibilityManagerAdapter; @Mock private BlockedNumbersAdapter mBlockedNumbersAdapter; @Mock private PhoneCapability mPhoneCapability; + @Mock private CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; @Mock private CallStreamingNotification mCallStreamingNotification; + @Mock private FeatureFlags mFeatureFlags; + @Mock private IncomingCallFilterGraph mIncomingCallFilterGraph; + @Mock private IConnectionService mIConnectionService; + @Rule public SetFlagsRule mSetRlagsRule = new SetFlagsRule(); private CallsManager mCallsManager; @Override @@ -296,8 +309,8 @@ public class CallsManagerTest extends TelecomTestCase { when(mCallEndpointControllerFactory.create(any(), any(), any())).thenReturn( mCallEndpointController); when(mCallAudioRouteStateMachineFactory.create(any(), any(), any(), any(), any(), any(), - anyInt(), any())).thenReturn(mCallAudioRouteStateMachine); - when(mCallAudioModeStateMachineFactory.create(any(), any())) + anyInt(), any(), any(), any())).thenReturn(mCallAudioRouteStateMachine); + when(mCallAudioModeStateMachineFactory.create(any(), any(), any(), any())) .thenReturn(mCallAudioModeStateMachine); when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis()); when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); @@ -350,7 +363,10 @@ public class CallsManagerTest extends TelecomTestCase { mBlockedNumbersAdapter, TransactionManager.getTestInstance(), mEmergencyCallDiagnosticLogger, - mCallStreamingNotification); + mCommunicationDeviceTracker, + mCallStreamingNotification, + mFeatureFlags, + (call, listener, context, timeoutsAdapter, lock) -> mIncomingCallFilterGraph); when(mPhoneAccountRegistrar.getPhoneAccount( eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT); @@ -362,11 +378,17 @@ public class CallsManagerTest extends TelecomTestCase { eq(WORK_HANDLE), any())).thenReturn(WORK_ACCOUNT); when(mToastFactory.makeText(any(), anyInt(), anyInt())).thenReturn(mToast); when(mToastFactory.makeText(any(), any(), anyInt())).thenReturn(mToast); + when(mIConnectionService.asBinder()).thenReturn(mock(IBinder.class)); + + mComponentContextFixture.addConnectionService( + SIM_1_ACCOUNT.getAccountHandle().getComponentName(), mIConnectionService); } @Override @After public void tearDown() throws Exception { + mComponentContextFixture.removeConnectionService( + SIM_1_ACCOUNT.getAccountHandle().getComponentName(), mIConnectionService); super.tearDown(); } @@ -393,7 +415,8 @@ public class CallsManagerTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, false /* isConference */, mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); ongoingCall.setState(CallState.ACTIVE, "just cuz"); return ongoingCall; } @@ -1320,8 +1343,9 @@ public class CallsManagerTest extends TelecomTestCase { @SmallTest @Test - public void testNoFilteringOfCallsWhenPhoneAccountRequestsSkipped() { + public void testDndFilterAppliesOfCallsWhenPhoneAccountRequestsSkipped() { // GIVEN an incoming call which is from a PhoneAccount that requested to skip filtering. + when(mFeatureFlags.skipFilterPhoneAccountPerformDndFilter()).thenReturn(true); Call incomingCall = addSpyCall(SIM_1_HANDLE, CallState.NEW); Bundle extras = new Bundle(); extras.putBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING, true); @@ -1341,7 +1365,35 @@ public class CallsManagerTest extends TelecomTestCase { // WHEN the incoming call is successfully added. mCallsManager.onSuccessfulIncomingCall(incomingCall); - // THEN the incoming call is not using call filtering + // THEN the incoming call is still applying Dnd filter. + verify(incomingCall).setIsUsingCallFiltering(eq(true)); + } + + @SmallTest + @Test + public void testNoFilterAppliesOfCallsWhenFlagNotEnabled() { + // Flag is not enabled. + when(mFeatureFlags.skipFilterPhoneAccountPerformDndFilter()).thenReturn(false); + Call incomingCall = addSpyCall(SIM_1_HANDLE, CallState.NEW); + Bundle extras = new Bundle(); + extras.putBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING, true); + PhoneAccount skipRequestedAccount = new PhoneAccount.Builder(SIM_2_HANDLE, "Skipper") + .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION + | PhoneAccount.CAPABILITY_CALL_PROVIDER) + .setExtras(extras) + .setIsEnabled(true) + .build(); + when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(SIM_1_HANDLE)) + .thenReturn(skipRequestedAccount); + doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD); + doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD); + doReturn(false).when(incomingCall).isSelfManaged(); + doReturn(true).when(incomingCall).setState(anyInt(), any()); + + // WHEN the incoming call is successfully added. + mCallsManager.onSuccessfulIncomingCall(incomingCall); + + // THEN the incoming call is not applying filter. verify(incomingCall).setIsUsingCallFiltering(eq(false)); } @@ -2398,7 +2450,7 @@ public class CallsManagerTest extends TelecomTestCase { mCallsManager.onCallFilteringComplete(callSpy, result, false /* timeout */); verify(mMissedCallNotifier).showMissedCallNotification( - any(MissedCallNotifier.CallInfo.class)); + any(MissedCallNotifier.CallInfo.class), /* uri= */ eq(null)); } @Test @@ -2502,6 +2554,32 @@ public class CallsManagerTest extends TelecomTestCase { assertEquals(DEFAULT_CALL_SCREENING_APP, outgoingCall.getPostCallPackageName()); } + /** + * Verify the only call state set from calling onSuccessfulOutgoingCall is CallState.DIALING. + */ + @SmallTest + @Test + public void testOutgoingCallStateIsSetToAPreviousStateAndIgnored() { + when(mFeatureFlags.fixAudioFlickerForOutgoingCalls()).thenReturn(true); + Call outgoingCall = addSpyCall(CallState.CONNECTING); + mCallsManager.onSuccessfulOutgoingCall(outgoingCall, CallState.NEW); + verify(outgoingCall, never()).setState(eq(CallState.NEW), any()); + verify(outgoingCall, times(1)).setState(eq(CallState.DIALING), any()); + } + + /** + * Verify a ConnectionService can start the call in the active state and avoid the dialing state + */ + @SmallTest + @Test + public void testOutgoingCallStateCanAvoidDialingAndGoStraightToActive() { + when(mFeatureFlags.fixAudioFlickerForOutgoingCalls()).thenReturn(true); + Call outgoingCall = addSpyCall(CallState.CONNECTING); + mCallsManager.onSuccessfulOutgoingCall(outgoingCall, CallState.ACTIVE); + verify(outgoingCall, never()).setState(eq(CallState.DIALING), any()); + verify(outgoingCall, times(1)).setState(eq(CallState.ACTIVE), any()); + } + @SmallTest @Test public void testRejectIncomingCallOnPAHInactive_SecondaryUser() throws Exception { @@ -2511,9 +2589,7 @@ public class CallsManagerTest extends TelecomTestCase { WORK_HANDLE.getUserHandle(), service); UserManager um = mContext.getSystemService(UserManager.class); - UserHandle newUser = new UserHandle(11); - when(mCallsManager.getCurrentUserHandle()).thenReturn(newUser); - when(um.isUserAdmin(eq(newUser.getIdentifier()))).thenReturn(false); + when(um.isUserAdmin(anyInt())).thenReturn(false); when(um.isQuietModeEnabled(eq(WORK_HANDLE.getUserHandle()))).thenReturn(false); when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(eq(WORK_HANDLE))) .thenReturn(WORK_ACCOUNT); @@ -2529,14 +2605,17 @@ public class CallsManagerTest extends TelecomTestCase { @Test public void testRejectIncomingCallOnPAHInactive_ProfilePaused() throws Exception { ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class); - doReturn(SIM_2_HANDLE.getComponentName()).when(service).getComponentName(); - mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(), - SIM_2_HANDLE.getUserHandle(), service); + doReturn(WORK_HANDLE.getComponentName()).when(service).getComponentName(); + mCallsManager.addConnectionServiceRepositoryCache(WORK_HANDLE.getComponentName(), + WORK_HANDLE.getUserHandle(), service); UserManager um = mContext.getSystemService(UserManager.class); - when(um.isQuietModeEnabled(eq(SIM_2_HANDLE.getUserHandle()))).thenReturn(true); + when(um.isUserAdmin(anyInt())).thenReturn(true); + when(um.isQuietModeEnabled(eq(WORK_HANDLE.getUserHandle()))).thenReturn(true); + when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(eq(WORK_HANDLE))) + .thenReturn(WORK_ACCOUNT); Call newCall = mCallsManager.processIncomingCallIntent( - SIM_2_HANDLE, new Bundle(), false); + WORK_HANDLE, new Bundle(), false); verify(service, timeout(TEST_TIMEOUT)).createConnectionFailed(any()); assertFalse(newCall.isInECBM()); @@ -2573,9 +2652,7 @@ public class CallsManagerTest extends TelecomTestCase { when(mEmergencyCallHelper.isLastOutgoingEmergencyCallPAH(eq(WORK_HANDLE))) .thenReturn(true); UserManager um = mContext.getSystemService(UserManager.class); - UserHandle newUser = new UserHandle(11); - when(mCallsManager.getCurrentUserHandle()).thenReturn(newUser); - when(um.isUserAdmin(eq(newUser.getIdentifier()))).thenReturn(false); + when(um.isUserAdmin(anyInt())).thenReturn(false); when(um.isQuietModeEnabled(eq(WORK_HANDLE.getUserHandle()))).thenReturn(false); when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(eq(WORK_HANDLE))) .thenReturn(WORK_ACCOUNT); @@ -2738,8 +2815,9 @@ public class CallsManagerTest extends TelecomTestCase { public void testQueryCurrentLocationCheckOnReceiveResult() throws Exception { ConnectionServiceWrapper service = new ConnectionServiceWrapper( new ComponentName(mContext.getPackageName(), - mContext.getPackageName().getClass().getName()), - null, mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null); + mContext.getPackageName().getClass().getName()), null, + mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null, + mFeatureFlags); CompletableFuture<String> resultFuture = new CompletableFuture<>(); try { @@ -2759,6 +2837,37 @@ public class CallsManagerTest extends TelecomTestCase { assertTrue(result.contains("onReceiveResult")); } + @Test + public void testConnectionServiceCreateConnectionTimeout() throws Exception { + mSetRlagsRule.enableFlags(Flags.FLAG_UNBIND_TIMEOUT_CONNECTIONS); + ConnectionServiceWrapper service = new ConnectionServiceWrapper( + SIM_1_ACCOUNT.getAccountHandle().getComponentName(), null, + mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null, + mFeatureFlags); + TestScheduledExecutorService scheduledExecutorService = new TestScheduledExecutorService(); + service.setScheduledExecutorService(scheduledExecutorService); + Call call = addSpyCall(); + service.addCall(call); + when(call.isCreateConnectionComplete()).thenReturn(false); + CreateConnectionResponse response = mock(CreateConnectionResponse.class); + + service.createConnection(call, response); + waitUntilConditionIsTrueOrTimeout(new Condition() { + @Override + public Object expected() { + return true; + } + + @Override + public Object actual() { + return scheduledExecutorService.isRunnableScheduledAtTime(15000L); + } + }, 5000L, "Expected job failed to schedule"); + scheduledExecutorService.advanceTime(15000L); + verify(response).handleCreateConnectionFailure( + eq(new DisconnectCause(DisconnectCause.ERROR))); + } + @SmallTest @Test public void testOnFailedOutgoingCallUnholdsCallAfterLocallyDisconnect() { @@ -2983,7 +3092,6 @@ public class CallsManagerTest extends TelecomTestCase { Call call = addSpyCall(CONNECTION_MGR_1_HANDLE, CallState.NEW); when(call.getHandoverDestinationCall()).thenReturn(destinationCall); when(call.getHandoverState()).thenReturn(HandoverState.HANDOVER_FROM_STARTED); - mCallsManager.createActionSetCallStateAndPerformAction( call, CallState.DISCONNECTED, ""); @@ -3323,7 +3431,8 @@ public class CallsManagerTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, false /* isConference */, mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); ongoingCall.setState(initialState, "just cuz"); if (targetPhoneAccount == SELF_MANAGED_HANDLE || targetPhoneAccount == SELF_MANAGED_2_HANDLE) { @@ -3355,4 +3464,19 @@ public class CallsManagerTest extends TelecomTestCase { when(mockTelephonyManager.getPhoneCapability()).thenReturn(mPhoneCapability); when(mPhoneCapability.getMaxActiveVoiceSubscriptions()).thenReturn(num); } + + private void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout, + String description) throws InterruptedException { + final long start = System.currentTimeMillis(); + while (!condition.expected().equals(condition.actual()) + && System.currentTimeMillis() - start < timeout) { + sleep(50); + } + assertEquals(description, condition.expected(), condition.actual()); + } + + protected interface Condition { + Object expected(); + Object actual(); + } } diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java index cc22de291..c732720ec 100644 --- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java +++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java @@ -16,6 +16,7 @@ package com.android.server.telecom.tests; +import com.android.server.telecom.flags.FeatureFlags; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -27,6 +28,8 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import android.Manifest; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.app.AppOpsManager; import android.app.NotificationManager; import android.app.StatusBarManager; @@ -55,6 +58,7 @@ import android.location.CountryDetector; import android.location.LocationManager; import android.media.AudioDeviceInfo; import android.media.AudioManager; +import android.net.Uri; import android.os.BugreportManager; import android.os.Bundle; import android.os.DropBoxManager; @@ -81,8 +85,10 @@ import android.test.mock.MockContext; import android.util.DisplayMetrics; import android.view.accessibility.AccessibilityManager; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -409,12 +415,23 @@ public class ComponentContextFixture implements TestFixture<Context> { } @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) { + // Override so that this can be verified via spy. + } + + @Override public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options) { // Override so that this can be verified via spy. } @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, + int appOp) { + // Override so that this can be verified via spy. + } + + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { @@ -617,8 +634,9 @@ public class ComponentContextFixture implements TestFixture<Context> { private TelecomManager mTelecomManager = mock(TelecomManager.class); - public ComponentContextFixture() { + public ComponentContextFixture(FeatureFlags featureFlags) { MockitoAnnotations.initMocks(this); + when(featureFlags.telecomResolveHiddenDependencies()).thenReturn(true); when(mResources.getConfiguration()).thenReturn(mResourceConfiguration); when(mResources.getString(anyInt())).thenReturn(""); when(mResources.getStringArray(anyInt())).thenReturn(new String[0]); @@ -701,7 +719,7 @@ public class ComponentContextFixture implements TestFixture<Context> { } }).when(mAppOpsManager).checkPackage(anyInt(), anyString()); - when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true); + when(mNotificationManager.matchesCallFilter(any(Uri.class))).thenReturn(true); when(mCarrierConfigManager.getConfig()).thenReturn(new PersistableBundle()); when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(new PersistableBundle()); @@ -735,6 +753,14 @@ public class ComponentContextFixture implements TestFixture<Context> { mServiceInfoByComponentName.put(componentName, serviceInfo); } + public void removeConnectionService( + ComponentName componentName, + IConnectionService service) + throws Exception { + removeService(ConnectionService.SERVICE_INTERFACE, componentName, service); + mServiceInfoByComponentName.remove(componentName); + } + public void addInCallService( ComponentName componentName, IInCallService service, @@ -756,6 +782,8 @@ public class ComponentContextFixture implements TestFixture<Context> { componentName.getPackageName() }); when(mPackageManager.checkPermission(eq(Manifest.permission.CONTROL_INCALL_EXPERIENCE), eq(componentName.getPackageName()))).thenReturn(PackageManager.PERMISSION_GRANTED); + when(mPackageManager.checkPermission(eq(Manifest.permission.INTERACT_ACROSS_USERS), + eq(componentName.getPackageName()))).thenReturn(PackageManager.PERMISSION_GRANTED); when(mPermissionCheckerManager.checkPermission( eq(Manifest.permission.CONTROL_INCALL_EXPERIENCE), any(AttributionSourceState.class), anyString(), anyBoolean(), anyBoolean(), @@ -794,6 +822,11 @@ public class ComponentContextFixture implements TestFixture<Context> { when(mResources.getStringArray(eq(id))).thenReturn(value); } + public void putRawResource(int id, String content) { + when(mResources.openRawResource(id)) + .thenReturn(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))); + } + public void setTelecomManager(TelecomManager telecomManager) { mTelecomManager = telecomManager; } @@ -828,6 +861,12 @@ public class ComponentContextFixture implements TestFixture<Context> { mComponentNameByService.put(service, name); } + private void removeService(String action, ComponentName name, IInterface service) { + mComponentNamesByAction.remove(action, name); + mServiceByComponentName.remove(name); + mComponentNameByService.remove(service); + } + private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) { List<ResolveInfo> result = new ArrayList<>(); for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) { diff --git a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java index 8a85a8786..c356b8fcc 100644 --- a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java +++ b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java @@ -38,6 +38,7 @@ import com.android.server.telecom.ConnectionServiceWrapper; import com.android.server.telecom.CreateConnectionProcessor; import com.android.server.telecom.CreateConnectionResponse; import com.android.server.telecom.PhoneAccountRegistrar; +import com.android.server.telecom.flags.FeatureFlags; import org.junit.After; import org.junit.Before; @@ -123,7 +124,7 @@ public class CreateConnectionProcessorTest extends TelecomTestCase { mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall, mMockConnectionServiceRepository, mMockCreateConnectionResponse, - mMockAccountRegistrar, mContext); + mMockAccountRegistrar, mContext, mFeatureFlags); mAccountToSub = new HashMap<>(); phoneAccounts = new ArrayList<>(); @@ -842,7 +843,7 @@ public class CreateConnectionProcessorTest extends TelecomTestCase { ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class); when(mMockConnectionServiceRepository.getService( eq(makeQuickConnectionServiceComponentName()), - any(UserHandle.class))).thenReturn(wrapper); + any(UserHandle.class), any(FeatureFlags.class))).thenReturn(wrapper); return wrapper; } diff --git a/tests/src/com/android/server/telecom/tests/EmergencyCallDiagnosticLoggerTest.java b/tests/src/com/android/server/telecom/tests/EmergencyCallDiagnosticLoggerTest.java index 3cb819672..c63a3d5bf 100644 --- a/tests/src/com/android/server/telecom/tests/EmergencyCallDiagnosticLoggerTest.java +++ b/tests/src/com/android/server/telecom/tests/EmergencyCallDiagnosticLoggerTest.java @@ -35,6 +35,7 @@ import android.content.ComponentName; import android.net.Uri; import android.os.BugreportManager; import android.os.DropBoxManager; +import android.os.UserHandle; import android.telecom.DisconnectCause; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; @@ -128,6 +129,7 @@ public class EmergencyCallDiagnosticLoggerTest extends TelecomTestCase { when(mTimeouts.getDaysBackToSearchEmergencyDiagnosticEntries()). thenReturn(DAYS_BACK_TO_SEARCH_EMERGENCY_DIAGNOSTIC_ENTRIES); when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis()); + when(mMockCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT); mEmergencyCallDiagnosticLogger = new EmergencyCallDiagnosticLogger(mTm, mBrm, mTimeouts, mDbm, Runnable::run, mClockProxy); @@ -171,7 +173,8 @@ public class EmergencyCallDiagnosticLoggerTest extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, false /* isConference */, mMockClockProxy, - mMockToastProxy); + mMockToastProxy, + mFeatureFlags); } /** diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java index 683a5e205..faae1484d 100644 --- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java +++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java @@ -28,7 +28,6 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.matches; import static org.mockito.ArgumentMatchers.nullable; @@ -36,7 +35,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -143,6 +141,8 @@ public class InCallControllerTests extends TelecomTestCase { @Mock PackageManager mMockPackageManager; @Mock PermissionCheckerManager mMockPermissionCheckerManager; @Mock Call mMockCall; + @Mock Call mMockSystemCall1; + @Mock Call mMockSystemCall2; @Mock Resources mMockResources; @Mock AppOpsManager mMockAppOpsManager; @Mock MockContext mMockContext; @@ -236,7 +236,7 @@ public class InCallControllerTests extends TelecomTestCase { "com.android.server.telecom.tests", null)); mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager, mMockSystemStateHelper, mDefaultDialerCache, mTimeoutsAdapter, - mEmergencyCallHelper, mCarModeTracker, mClockProxy); + mEmergencyCallHelper, mCarModeTracker, mClockProxy, mFeatureFlags); // Capture the broadcast receiver registered. doAnswer(invocation -> { mRegisteredReceiver = invocation.getArgument(0); @@ -588,6 +588,7 @@ public class InCallControllerTests extends TelecomTestCase { when(mMockCall.isEmergencyCall()).thenReturn(true); when(mMockCall.isIncoming()).thenReturn(true); when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE); + when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE); when(mMockContext.getSystemService(eq(UserManager.class))) .thenReturn(mMockUserManager); when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true); @@ -617,6 +618,7 @@ public class InCallControllerTests extends TelecomTestCase { when(mMockCall.isInECBM()).thenReturn(true); when(mMockCall.isIncoming()).thenReturn(true); when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE); + when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE); when(mMockContext.getSystemService(eq(UserManager.class))) .thenReturn(mMockUserManager); when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true); @@ -647,6 +649,7 @@ public class InCallControllerTests extends TelecomTestCase { when(mMockCall.isInECBM()).thenReturn(true); when(mMockCall.isIncoming()).thenReturn(true); when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE); + when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE); when(mMockContext.getSystemService(eq(UserManager.class))) .thenReturn(mMockUserManager); when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false); @@ -1839,6 +1842,67 @@ public class InCallControllerTests extends TelecomTestCase { assertNull(mInCallController.getInCallServiceConnections().get(testUser)); } + @Test + public void testRemoveAllServiceConnections_MultiUser() throws Exception { + when(mFeatureFlags.associatedUserRefactorForWorkProfile()).thenReturn(true); + setupMocks(false /* isExternalCall */); + setupMockPackageManager(true /* default */, true /* system */, false /* external calls */); + UserHandle workUser = new UserHandle(12); + UserManager um = mContext.getSystemService(UserManager.class); + when(um.getUserInfo(anyInt())).thenReturn(mMockUserInfo); + when(mMockUserInfo.isManagedProfile()).thenReturn(false); + when(mMockCall.getAssociatedUser()).thenReturn(workUser); + setupFakeSystemCall(mMockSystemCall1, 1); + setupFakeSystemCall(mMockSystemCall2, 2); + + // Add "work" call to service. The mapping should've been inserted + // with the workUser as the key. + mInCallController.onCallAdded(mMockCall); + // Add system call to service. The mapping should've been + // inserted with the system user as the key. + mInCallController.onCallAdded(mMockSystemCall1); + + ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class); + // Make sure we bound to the system call as well as the work call. + verify(mMockContext, times(2)).bindServiceAsUser( + bindIntentCaptor.capture(), + any(ServiceConnection.class), + eq(serviceBindingFlags), + eq(UserHandle.CURRENT)); + assertTrue(mInCallController.getInCallServiceConnections().containsKey(workUser)); + assertTrue(mInCallController.getInCallServiceConnections().containsKey(UserHandle.SYSTEM)); + + // Remove the work call. This leverages getUserFromCall to remove the ICS mapping. + when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockSystemCall1)); + mInCallController.onCallRemoved(mMockCall); + waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); + // Verify that the mapping was properly removed. + assertNull(mInCallController.getInCallServiceConnections().get(workUser)); + // Verify mapping for system user is still present. + assertNotNull(mInCallController.getInCallServiceConnections().get(UserHandle.SYSTEM)); + + // Add another system call + mInCallController.onCallAdded(mMockSystemCall2); + when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockSystemCall2)); + // Remove first system call and verify that mapping is present + mInCallController.onCallRemoved(mMockSystemCall1); + waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); + // Verify mapping for system user is still present. + assertNotNull(mInCallController.getInCallServiceConnections().get(UserHandle.SYSTEM)); + // Remove last system call and verify that connection isn't present in ICS mapping. + when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList()); + mInCallController.onCallRemoved(mMockSystemCall2); + waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); + assertNull(mInCallController.getInCallServiceConnections().get(UserHandle.SYSTEM)); + } + + private void setupFakeSystemCall(@Mock Call call, int id) { + when(call.getAssociatedUser()).thenReturn(UserHandle.SYSTEM); + when(call.getTargetPhoneAccount()).thenReturn(PA_HANDLE); + when(call.getAnalytics()).thenReturn(new Analytics.CallInfo()); + when(call.getId()).thenReturn("TC@" + id); + } + private void setupMocksForWorkProfileTest() { when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockCallsManager.isInEmergencyCall()).thenReturn(false); diff --git a/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java b/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java index 88b5bb52a..39381e6ca 100644 --- a/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java +++ b/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java @@ -16,6 +16,7 @@ package com.android.server.telecom.tests; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IInCallAdapter; import com.android.internal.telecom.IInCallService; @@ -39,7 +40,7 @@ import java.util.concurrent.TimeUnit; * Controls a test {@link IInCallService} as would be provided by an InCall UI on a system. */ public class InCallServiceFixture implements TestFixture<IInCallService> { - + public static boolean sIgnoreOverrideAdapterFlag = false; public String mLatestCallId; public IInCallAdapter mInCallAdapter; public CallAudioState mCallAudioState; @@ -53,10 +54,17 @@ public class InCallServiceFixture implements TestFixture<IInCallService> { public CountDownLatch mUpdateCallLock = new CountDownLatch(1); public CountDownLatch mAddCallLock = new CountDownLatch(1); + @VisibleForTesting + public static void setIgnoreOverrideAdapterFlag(boolean flag) { + sIgnoreOverrideAdapterFlag = flag; + } + public class FakeInCallService extends IInCallService.Stub { @Override public void setInCallAdapter(IInCallAdapter inCallAdapter) throws RemoteException { - if (mInCallAdapter != null && inCallAdapter != null) { + // sIgnoreOverrideAdapterFlag is being used to verify a scenario where the InCallAdapter + // gets set twice (secondary user places MO/MT call). + if (mInCallAdapter != null && inCallAdapter != null && !sIgnoreOverrideAdapterFlag) { throw new RuntimeException("Adapter is already set"); } if (mInCallAdapter == null && inCallAdapter == null) { diff --git a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java index 1f1b939e0..004aa8eb2 100644 --- a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java +++ b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java @@ -23,7 +23,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -36,6 +35,7 @@ import android.media.ToneGenerator; import android.test.suitebuilder.annotation.SmallTest; import com.android.server.telecom.AsyncRingtonePlayer; +import com.android.server.telecom.Call; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioRoutePeripheralAdapter; import com.android.server.telecom.CallAudioRouteStateMachine; @@ -112,6 +112,8 @@ public class InCallTonePlayerTest extends TelecomTestCase { @Mock private CallAudioManager mCallAudioManager; + @Mock + private Call mCall; private InCallTonePlayer mInCallTonePlayer; @@ -122,7 +124,7 @@ public class InCallTonePlayerTest extends TelecomTestCase { when(mToneGeneratorFactory.get(anyInt(), anyInt())).thenReturn(mToneGenerator); when(mMediaPlayerFactory.get(anyInt(), any())).thenReturn(mMediaPlayerAdapter); - doNothing().when(mCallAudioManager).setIsTonePlaying(anyBoolean()); + doNothing().when(mCallAudioManager).setIsTonePlaying(any(Call.class), anyBoolean()); mCallAudioRoutePeripheralAdapter = new CallAudioRoutePeripheralAdapter( mCallAudioRouteStateMachine, mBluetoothRouteManager, mWiredHeadsetManager, @@ -130,7 +132,7 @@ public class InCallTonePlayerTest extends TelecomTestCase { mFactory = new InCallTonePlayer.Factory(mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory, mMediaPlayerFactory, mAudioManagerAdapter); mFactory.setCallAudioManager(mCallAudioManager); - mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_ENDED); + mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_CALL_ENDED); } @Override @@ -147,11 +149,12 @@ public class InCallTonePlayerTest extends TelecomTestCase { assertTrue(mInCallTonePlayer.startTone()); // Verify we did play a tone. verify(mMediaPlayerFactory, timeout(TEST_TIMEOUT)).get(anyInt(), any()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); mInCallTonePlayer.stopTone(); // Timeouts due to threads! - verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(false)); + verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(any(Call.class), + eq(false)); } @SmallTest @@ -161,11 +164,12 @@ public class InCallTonePlayerTest extends TelecomTestCase { assertTrue(mInCallTonePlayer.startTone()); // Verify we did play a tone. verify(mMediaPlayerFactory, timeout(TEST_TIMEOUT)).get(anyInt(), any()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); mInCallTonePlayer.stopTone(); // Timeouts due to threads! - verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(false)); + verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(any(Call.class), + eq(false)); // Correctness check: ensure we can't start the tone again. assertFalse(mInCallTonePlayer.startTone()); @@ -174,15 +178,16 @@ public class InCallTonePlayerTest extends TelecomTestCase { @SmallTest @Test public void testInterruptToneGenerator() { - mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK); + mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK); when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true); assertTrue(mInCallTonePlayer.startTone()); verify(mToneGenerator, timeout(TEST_TIMEOUT)).startTone(anyInt()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); mInCallTonePlayer.stopTone(); // Timeouts due to threads! - verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(false)); + verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(any(Call.class), + eq(false)); // Ideally it would be nice to verify this, however release is a native method so appears to // cause flakiness when testing on Cuttlefish. // verify(mToneGenerator, timeout(TEST_TIMEOUT)).release(); @@ -199,7 +204,8 @@ public class InCallTonePlayerTest extends TelecomTestCase { // Verify we did play a tone. verify(mMediaPlayerFactory, timeout(TEST_TIMEOUT)).get(anyInt(), any()); - verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(true)); + verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(any(Call.class), + eq(true)); } @SmallTest @@ -213,11 +219,11 @@ public class InCallTonePlayerTest extends TelecomTestCase { when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false); when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(false); - mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK); + mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK); assertTrue(mInCallTonePlayer.startTone()); verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT)) .get(eq(AudioManager.STREAM_BLUETOOTH_SCO), anyInt()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); } @SmallTest @@ -231,11 +237,11 @@ public class InCallTonePlayerTest extends TelecomTestCase { when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false); when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(false); - mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING); + mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_CALL_WAITING); assertTrue(mInCallTonePlayer.startTone()); verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT)) .get(eq(AudioManager.STREAM_BLUETOOTH_SCO), anyInt()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); } @SmallTest @@ -249,11 +255,11 @@ public class InCallTonePlayerTest extends TelecomTestCase { when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false); when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(true); - mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK); + mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK); assertTrue(mInCallTonePlayer.startTone()); verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT)) .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); } @SmallTest @@ -267,10 +273,10 @@ public class InCallTonePlayerTest extends TelecomTestCase { when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false); when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(true); - mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING); + mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_CALL_WAITING); assertTrue(mInCallTonePlayer.startTone()); verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT)) .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt()); - verify(mCallAudioManager).setIsTonePlaying(eq(true)); + verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true)); } } diff --git a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java index 2b05430c5..ac2f1f116 100644 --- a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java +++ b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java @@ -16,6 +16,8 @@ package com.android.server.telecom.tests; +import static com.android.server.telecom.ui.MissedCallNotifierImpl.CALL_LOG_COLUMN_ID; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -46,10 +48,14 @@ import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.telecom.CallerInfo; + +import com.android.server.telecom.CallLogManager; import com.android.server.telecom.CallerInfoLookupHelper; +import com.android.server.telecom.CallsManager; import com.android.server.telecom.Constants; import com.android.server.telecom.DefaultDialerCache; import com.android.server.telecom.DeviceIdleControllerAdapter; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.MissedCallNotifier; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.TelecomBroadcastIntentProcessor; @@ -241,7 +247,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle()); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */ null); ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mContext).sendBroadcastAsUser(intentArgumentCaptor.capture(), any(), anyString(), any()); @@ -250,6 +256,31 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { assertEquals(1, sentIntent.getIntExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, -1)); } + @SmallTest + @Test + public void testCallLogUriSentToNotifier(){ + MissedCallNotifier missedCallNotifier = setupMissedCallNotificationThroughDefaultDialer(); + PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY); + Cursor mockMissedCallsCursor = new MockMissedCallCursorBuilder() + .addEntry(TEL_CALL_HANDLE.getSchemeSpecificPart(), + CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP) + .build(); + MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME, + CALL_TIMESTAMP, phoneAccount.getAccountHandle()); + when(mFeatureFlags.addCallUriForMissedCalls()).thenReturn(true); + + missedCallNotifier.showMissedCallNotification(fakeCall, + CallLog.Calls.CONTENT_URI.buildUpon().appendPath(Long.toString( + mockMissedCallsCursor.getInt(CALL_LOG_COLUMN_ID))).build()); + ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mContext).sendBroadcastAsUser(intentArgumentCaptor.capture(), any(), + anyString(), any()); + + Intent sentIntent = intentArgumentCaptor.getValue(); + Uri actualCallUri = sentIntent.getParcelableExtra(TelecomManager.EXTRA_CALL_LOG_URI); + assertTrue(actualCallUri.isPathPrefixMatch(CallLog.Calls.CONTENT_URI)); + } + private MissedCallNotifier setupMissedCallNotificationThroughDefaultDialer() { mComponentContextFixture.addIntentReceiver( TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION, COMPONENT_NAME); @@ -275,9 +306,9 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle()); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */null); missedCallNotifier.clearMissedCalls(userHandle); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */null); ArgumentCaptor<Integer> requestIdCaptor = ArgumentCaptor.forClass( Integer.class); @@ -308,10 +339,10 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory, - mDeviceIdleControllerAdapter); + mDeviceIdleControllerAdapter, mFeatureFlags); - missedCallNotifier.showMissedCallNotification(fakeCall); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */ null); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */ null); // The following captor is to capture the two notifications that got passed into // notifyAsUser. This distinguishes between the builders used for the full notification @@ -402,7 +433,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle()); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */ null); ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass( Notification.class); @@ -464,13 +495,13 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory, - mDeviceIdleControllerAdapter); + mDeviceIdleControllerAdapter, mFeatureFlags); PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY); MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(SIP_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle()); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */ null); // Create two intents that correspond to call-back and respond back with SMS, and assert // that in the case of a SIP call, no SMS intent is generated. @@ -525,7 +556,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory, - mDeviceIdleControllerAdapter); + mDeviceIdleControllerAdapter, mFeatureFlags); // AsyncQueryHandler used in reloadFromDatabase interacts poorly with the below // timeout-verify, so run this in a new handler to mitigate that. @@ -595,7 +626,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory, - mDeviceIdleControllerAdapter); + mDeviceIdleControllerAdapter, mFeatureFlags); // AsyncQueryHandler used in reloadFromDatabase interacts poorly with the below // timeout-verify, so run this in a new handler to mitigate that. @@ -637,13 +668,13 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory, - mDeviceIdleControllerAdapter); + mDeviceIdleControllerAdapter, mFeatureFlags); PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY); MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(SIP_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle()); - missedCallNotifier.showMissedCallNotification(fakeCall); + missedCallNotifier.showMissedCallNotification(fakeCall, /* uri= */ null); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); ArgumentCaptor<Bundle> bundleCaptor = @@ -701,7 +732,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase { NotificationBuilderFactory fakeBuilderFactory, UserHandle currentUser) { MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory, - mDeviceIdleControllerAdapter); + mDeviceIdleControllerAdapter, mFeatureFlags); missedCallNotifier.setCurrentUserHandle(currentUser); return missedCallNotifier; } diff --git a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java index 4af3de343..5bba742e4 100644 --- a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java +++ b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java @@ -109,6 +109,7 @@ public class MissedInformationTest extends TelecomSystemTest { mAdapter = new CallIntentProcessor.AdapterImpl(mCallsManager.getDefaultDialerCache()); mNotificationManager = spy((NotificationManager) mContext.getSystemService( Context.NOTIFICATION_SERVICE)); + when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true); when(mContentResolver.getPackageName()).thenReturn(PACKAGE_NAME); when(mContentResolver.acquireProvider(any(String.class))).thenReturn(mContentProvider); when(mContentProvider.call(any(String.class), any(String.class), @@ -152,6 +153,8 @@ public class MissedInformationTest extends TelecomSystemTest { setUpEmergencyCall(); when(mEmergencyCall.getAssociatedUser()). thenReturn(mPhoneAccountA0.getAccountHandle().getUserHandle()); + when(mEmergencyCall.getTargetPhoneAccount()) + .thenReturn(mPhoneAccountA0.getAccountHandle()); mCallsManager.addCall(mEmergencyCall); assertTrue(mCallsManager.isInEmergencyCall()); @@ -417,7 +420,7 @@ public class MissedInformationTest extends TelecomSystemTest { null, mCallsManager.getPhoneNumberUtilsAdapter(), null, null, null, mPhoneAccountA0.getAccountHandle(), Call.CALL_DIRECTION_INCOMING, false, false, - mClockProxy, null)); + mClockProxy, null, mFeatureFlags)); doReturn(1L).when(mIncomingCall).getStartRingTime(); doAnswer((x) -> { mCountDownLatch.countDown(); diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java index 33acd9811..1ffcb7664 100644 --- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java +++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java @@ -53,6 +53,7 @@ import android.telephony.DisconnectCause; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.Call; import com.android.server.telecom.CallsManager; import com.android.server.telecom.DefaultDialerCache; @@ -75,6 +76,8 @@ import org.mockito.Mock; @RunWith(JUnit4.class) public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { + private static final Uri TEST_URI = Uri.parse("tel:16505551212"); + private static class ReceiverIntentPair { public BroadcastReceiver receiver; public Intent intent; @@ -93,6 +96,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar; @Mock private RoleManagerAdapter mRoleManagerAdapter; @Mock private DefaultDialerCache mDefaultDialerCache; + @Mock private FeatureFlags mFeatureFlags; @Mock private MmiUtils mMmiUtils; private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter = new PhoneNumberUtilsAdapterImpl(); @@ -113,6 +117,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { any(PhoneAccountHandle.class))).thenReturn(mPhoneAccount); when(mPhoneAccount.isSelfManaged()).thenReturn(true); when(mSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(false); + when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(false); } @Override @@ -510,6 +515,84 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { testUnmodifiedRegularCall(); } + /** + * Where the flag `isNewOutgoingCallBroadcastUnblocking` is off, verify that we sent an ordered + * broadcast and did not try to start the call immediately (legacy behavior). + */ + @SmallTest + @Test + public void testSendBroadcastBlocking() { + when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(false); + Intent intent = new Intent(Intent.ACTION_CALL, TEST_URI); + NewOutgoingCallIntentBroadcaster nocib = new NewOutgoingCallIntentBroadcaster( + mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, + true /* isDefaultPhoneApp */, mDefaultDialerCache, mMmiUtils, mFeatureFlags); + + NewOutgoingCallIntentBroadcaster.CallDisposition disposition = nocib.evaluateCall(); + nocib.processCall(mCall, disposition); + + // We should not have not short-circuited to place the outgoing call directly. + verify(mCall, never()).setNewOutgoingCallIntentBroadcastIsDone(); + verify(mCallsManager, never()).placeOutgoingCall(any(Call.class), any(Uri.class), + any(GatewayInfo.class), anyBoolean(), anyInt()); + + // Ensure we did send the broadcast ordered + verifyBroadcastSent(TEST_URI.getSchemeSpecificPart(), + createNumberExtras(TEST_URI.getSchemeSpecificPart())); + + // Ensure we did not try to directly send the broadcast unordered. + verify(mContext, never()).sendBroadcastAsUser( + any(Intent.class), + eq(UserHandle.CURRENT), + eq(android.Manifest.permission.PROCESS_OUTGOING_CALLS)); + } + + /** + * Where the flag `isNewOutgoingCallBroadcastUnblocking` is off, verify that we sent an ordered + * broadcast and did not try to start the call immediately. Also ensure that the broadcast + * flags are correct. + */ + @SmallTest + @Test + public void testSendBroadcastNonBlocking() { + when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(true); + Intent intent = new Intent(Intent.ACTION_CALL, TEST_URI); + NewOutgoingCallIntentBroadcaster nocib = new NewOutgoingCallIntentBroadcaster( + mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, + true /* isDefaultPhoneApp */, mDefaultDialerCache, mMmiUtils, mFeatureFlags); + + NewOutgoingCallIntentBroadcaster.CallDisposition disposition = nocib.evaluateCall(); + nocib.processCall(mCall, disposition); + + // We should have started the outgoing call flow immediately. + verify(mCall).setNewOutgoingCallIntentBroadcastIsDone(); + verify(mCallsManager).placeOutgoingCall(any(Call.class), any(Uri.class), + nullable(GatewayInfo.class), anyBoolean(), anyInt()); + + // Ensure we didn't send an ordered broadcast. + verify(mContext, never()).sendOrderedBroadcastAsUser( + any(Intent.class), + any(UserHandle.class), + anyString(), + anyInt(), + any(Bundle.class), + any(BroadcastReceiver.class), + any(Handler.class), + eq(Activity.RESULT_OK), + anyString(), + any(Bundle.class)); + + // But that we did send a regular broadcast. + ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mContext).sendBroadcastAsUser( + intentArgumentCaptor.capture(), + eq(UserHandle.CURRENT), + eq(android.Manifest.permission.PROCESS_OUTGOING_CALLS), + eq(AppOpsManager.OP_PROCESS_OUTGOING_CALLS)); + Intent capturedIntent = intentArgumentCaptor.getValue(); + assertEquals(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, capturedIntent.getFlags()); + } + private ReceiverIntentPair regularCallTestHelper(Intent intent, Bundle expectedAdditionalExtras) { Uri handle = intent.getData(); @@ -542,7 +625,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { boolean isDefaultPhoneApp) { NewOutgoingCallIntentBroadcaster b = new NewOutgoingCallIntentBroadcaster( mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, - isDefaultPhoneApp, mDefaultDialerCache, mMmiUtils); + isDefaultPhoneApp, mDefaultDialerCache, mMmiUtils, mFeatureFlags); NewOutgoingCallIntentBroadcaster.CallDisposition cd = b.evaluateCall(); if (cd.disconnectCause == DisconnectCause.NOT_DISCONNECTED) { b.processCall(mCall, cd); diff --git a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java index fed80847f..57c61915b 100644 --- a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java +++ b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java @@ -13,6 +13,7 @@ import android.content.ComponentName; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; +import android.os.UserHandle; import android.telecom.Connection; import android.telecom.ParcelableCall; import android.telecom.PhoneAccountHandle; @@ -57,6 +58,7 @@ public class ParcelableCallUtilsTest extends TelecomTestCase { when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); when(mCallsManager.getCallerInfoLookupHelper()).thenReturn(mCallerInfoLookupHelper); when(mCallsManager.getPhoneAccountRegistrar()).thenReturn(mPhoneAccountRegistrar); + when(mCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT); when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(any())).thenReturn(null); when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any())) .thenReturn(false); @@ -75,7 +77,8 @@ public class ParcelableCallUtilsTest extends TelecomTestCase { false /* shouldAttachToExistingConnection */, false /* isConference */, mClockProxy /* ClockProxy */, - mToastProxy); + mToastProxy, + mFeatureFlags); } @Override diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java index e573bb81f..9fcb87a38 100644 --- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java +++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java @@ -353,6 +353,40 @@ public class PhoneAccountRegistrarTest extends TelecomTestCase { PhoneAccount.SCHEME_TEL)); } + /** + * Verify when a {@link android.telecom.ConnectionService} is disabled or cannot be resolved, + * all phone accounts are unregistered when calling + * {@link PhoneAccountRegistrar#getAccountsForPackage_BypassResolveComp(String, UserHandle)}. + */ + @Test + public void testCannotResolveServiceUnregistersAccounts() throws Exception { + ComponentName componentName = makeQuickConnectionServiceComponentName(); + PhoneAccount account = makeQuickAccountBuilder("0", 0, USER_HANDLE_10) + .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER + | PhoneAccount.CAPABILITY_CALL_PROVIDER).build(); + // add the ConnectionService and register a single phone account for it + mComponentContextFixture.addConnectionService(componentName, + Mockito.mock(IConnectionService.class)); + registerAndEnableAccount(account); + // verify the start state + assertEquals(1, + mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(), + USER_HANDLE_10).size()); + // remove the ConnectionService so that the account cannot be resolved anymore + mComponentContextFixture.removeConnectionService(componentName, + Mockito.mock(IConnectionService.class)); + // verify the account is unregistered when fetching the phone accounts for the package + assertEquals(1, + mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(), + USER_HANDLE_10).size()); + assertEquals(0,mRegistrar.cleanupUnresolvableConnectionServiceAccounts( + mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(), + USER_HANDLE_10)).size()); + assertEquals(0, + mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(), + USER_HANDLE_10).size()); + } + @MediumTest @Test public void testSimCallManager() throws Exception { diff --git a/tests/src/com/android/server/telecom/tests/RingbackPlayerTest.java b/tests/src/com/android/server/telecom/tests/RingbackPlayerTest.java new file mode 100644 index 000000000..e85194440 --- /dev/null +++ b/tests/src/com/android/server/telecom/tests/RingbackPlayerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.telecom.tests; + +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; + +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.server.telecom.Call; +import com.android.server.telecom.CallState; +import com.android.server.telecom.InCallTonePlayer; +import com.android.server.telecom.RingbackPlayer; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; + +import java.util.concurrent.CountDownLatch; + +@RunWith(JUnit4.class) +public class RingbackPlayerTest extends TelecomTestCase { + @Mock InCallTonePlayer.Factory mFactory; + @Mock Call mCall; + @Mock InCallTonePlayer mTonePlayer; + + private RingbackPlayer mRingbackPlayer; + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + when(mFactory.createPlayer(any(Call.class), anyInt())).thenReturn(mTonePlayer); + mRingbackPlayer = new RingbackPlayer(mFactory); + } + + @SmallTest + @Test + public void testPlayerSync() { + // make sure InCallTonePlayer try to start playing the tone after RingbackPlayer receives + // stop tone request. + CountDownLatch latch = new CountDownLatch(1); + doReturn(CallState.DIALING).when(mCall).getState(); + doAnswer(x -> { + new Thread(() -> { + try { + latch.await(); + } catch (InterruptedException e) { + // Ignore + } + }).start(); + return true; + }).when(mTonePlayer).startTone(); + + mRingbackPlayer.startRingbackForCall(mCall); + mRingbackPlayer.stopRingbackForCall(mCall); + assertFalse(mRingbackPlayer.isRingbackPlaying()); + latch.countDown(); + } +} diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java index 34360cadc..771e73634 100644 --- a/tests/src/com/android/server/telecom/tests/RingerTest.java +++ b/tests/src/com/android/server/telecom/tests/RingerTest.java @@ -16,8 +16,9 @@ package com.android.server.telecom.tests; +import static android.os.VibrationEffect.EFFECT_CLICK; import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; - +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -30,6 +31,7 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -51,6 +53,9 @@ import android.os.UserManager; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorInfo; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.test.suitebuilder.annotation.SmallTest; @@ -63,33 +68,47 @@ import com.android.server.telecom.InCallTonePlayer; import com.android.server.telecom.Ringer; import com.android.server.telecom.RingtoneFactory; import com.android.server.telecom.SystemSettingsUtil; +import com.android.server.telecom.flags.FeatureFlags; import org.junit.After; 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.Mock; import org.mockito.Spy; +import java.time.Duration; import java.util.concurrent.CompletableFuture; @RunWith(JUnit4.class) public class RingerTest extends TelecomTestCase { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + private static final Uri FAKE_RINGTONE_URI = Uri.parse("content://media/fake/audio/1729"); // Returned when the a URI-based VibrationEffect is attempted, to avoid depending on actual // device configuration for ringtone URIs. The actual Uri can be verified via the // VibrationEffectProxy mock invocation. private static final VibrationEffect URI_VIBRATION_EFFECT = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK); + private static final VibrationEffect EXPECTED_SIMPLE_VIBRATION_PATTERN = + VibrationEffect.createWaveform( + new long[] {0, 1000, 1000}, new int[] {0, 255, 0}, 1); + private static final VibrationEffect EXPECTED_PULSE_VIBRATION_PATTERN = + VibrationEffect.createWaveform( + Ringer.PULSE_PATTERN, Ringer.PULSE_AMPLITUDE, 5); @Mock InCallTonePlayer.Factory mockPlayerFactory; @Mock SystemSettingsUtil mockSystemSettingsUtil; @Mock RingtoneFactory mockRingtoneFactory; @Mock Vibrator mockVibrator; + @Mock VibratorInfo mockVibratorInfo; @Mock InCallController mockInCallController; @Mock NotificationManager mockNotificationManager; @Mock Ringer.AccessibilityManagerAdapter mockAccessibilityManagerAdapter; + @Mock private FeatureFlags mFeatureFlags; @Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy; @@ -111,21 +130,25 @@ public class RingerTest extends TelecomTestCase { @Before public void setUp() throws Exception { super.setUp(); - mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); + mContext = spy(mComponentContextFixture.getTestDouble().getApplicationContext()); + when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true); doReturn(URI_VIBRATION_EFFECT).when(spyVibrationEffectProxy).get(any(), any()); - when(mockPlayerFactory.createPlayer(anyInt())).thenReturn(mockTonePlayer); + when(mockPlayerFactory.createPlayer(any(Call.class), anyInt())).thenReturn(mockTonePlayer); mockAudioManager = mContext.getSystemService(AudioManager.class); when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + when(mockVibrator.getInfo()).thenReturn(mockVibratorInfo); when(mockSystemSettingsUtil.isHapticPlaybackSupported(any(Context.class))) .thenAnswer((invocation) -> mIsHapticPlaybackSupported); mockNotificationManager =mContext.getSystemService(NotificationManager.class); when(mockTonePlayer.startTone()).thenReturn(true); - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true); + when(mockNotificationManager.matchesCallFilter(any(Uri.class))).thenReturn(true); when(mockRingtoneFactory.hasHapticChannels(any(Ringtone.class))).thenReturn(false); when(mockCall1.getState()).thenReturn(CallState.RINGING); when(mockCall2.getState()).thenReturn(CallState.RINGING); when(mockCall1.getAssociatedUser()).thenReturn(PA_HANDLE.getUserHandle()); when(mockCall2.getAssociatedUser()).thenReturn(PA_HANDLE.getUserHandle()); + when(mockCall1.getTargetPhoneAccount()).thenReturn(PA_HANDLE); + when(mockCall2.getTargetPhoneAccount()).thenReturn(PA_HANDLE); // Set BT active state in tests to ensure that we do not end up blocking tests for 1 sec // waiting for BT to connect in unit tests by default. asyncRingtonePlayer.updateBtActiveState(true); @@ -140,7 +163,8 @@ public class RingerTest extends TelecomTestCase { private void createRingerUnderTest() { mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil, asyncRingtonePlayer, mockRingtoneFactory, mockVibrator, spyVibrationEffectProxy, - mockInCallController, mockNotificationManager, mockAccessibilityManagerAdapter); + mockInCallController, mockNotificationManager, mockAccessibilityManagerAdapter, + mFeatureFlags); // This future is used to wait for AsyncRingtonePlayer to finish its part. mRingerUnderTest.setBlockOnRingingFuture(mRingCompletionFuture); } @@ -153,6 +177,151 @@ public class RingerTest extends TelecomTestCase { @SmallTest @Test + public void testSimpleVibrationPrecedesValidSupportedDefaultRingVibrationOverride() + throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(true); + mockVibrationResourceValues( + """ + <vibration-effect> + <predefined-effect name="click"/> + </vibration-effect> + """, + /* useSimpleVibration= */ true); + when(mockVibratorInfo.areVibrationFeaturesSupported(any())).thenReturn(true); + + createRingerUnderTest(); + + assertEquals(EXPECTED_SIMPLE_VIBRATION_PATTERN, mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test + public void testDefaultRingVibrationOverrideNotUsedWhenFeatureIsDisabled() + throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(false); + mockVibrationResourceValues( + """ + <vibration-effect> + <waveform-effect> + <waveform-entry durationMs="100" amplitude="0"/> + <repeating> + <waveform-entry durationMs="500" amplitude="default"/> + <waveform-entry durationMs="700" amplitude="0"/> + </repeating> + </waveform-effect> + </vibration-effect> + """, + /* useSimpleVibration= */ false); + when(mockVibratorInfo.areVibrationFeaturesSupported(any())).thenReturn(true); + + createRingerUnderTest(); + + assertEquals(EXPECTED_PULSE_VIBRATION_PATTERN, mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test + public void testValidSupportedRepeatingDefaultRingVibrationOverride() throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(true); + mockVibrationResourceValues( + """ + <vibration-effect> + <waveform-effect> + <waveform-entry durationMs="100" amplitude="0"/> + <repeating> + <waveform-entry durationMs="500" amplitude="default"/> + <waveform-entry durationMs="700" amplitude="0"/> + </repeating> + </waveform-effect> + </vibration-effect> + """, + /* useSimpleVibration= */ false); + when(mockVibratorInfo.areVibrationFeaturesSupported(any())).thenReturn(true); + + createRingerUnderTest(); + + assertEquals( + VibrationEffect.createWaveform(new long[]{100, 500, 700}, /* repeat= */ 1), + mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test + public void testValidSupportedNonRepeatingDefaultRingVibrationOverride() throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(true); + mockVibrationResourceValues( + """ + <vibration-effect> + <predefined-effect name="click"/> + </vibration-effect> + """, + /* useSimpleVibration= */ false); + when(mockVibratorInfo.areVibrationFeaturesSupported(any())).thenReturn(true); + + createRingerUnderTest(); + + assertEquals( + VibrationEffect + .startComposition() + .repeatEffectIndefinitely( + VibrationEffect + .startComposition() + .addEffect(VibrationEffect.createPredefined(EFFECT_CLICK)) + .addOffDuration(Duration.ofSeconds(1)) + .compose() + ) + .compose(), + mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test + public void testValidButUnsupportedDefaultRingVibrationOverride() throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(true); + mockVibrationResourceValues( + """ + <vibration-effect> + <predefined-effect name="click"/> + </vibration-effect> + """, + /* useSimpleVibration= */ false); + when(mockVibratorInfo.areVibrationFeaturesSupported( + eq(VibrationEffect.createPredefined(EFFECT_CLICK)))).thenReturn(false); + + createRingerUnderTest(); + + assertEquals(EXPECTED_SIMPLE_VIBRATION_PATTERN, mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test + public void testInvalidDefaultRingVibrationOverride() throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(true); + mockVibrationResourceValues( + /* defaultVibrationContent= */ "bad serialization", + /* useSimpleVibration= */ false); + when(mockVibratorInfo.areVibrationFeaturesSupported(any())).thenReturn(true); + + createRingerUnderTest(); + + assertEquals(EXPECTED_SIMPLE_VIBRATION_PATTERN, mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test + public void testEmptyDefaultRingVibrationOverride() throws Exception { + when(mFeatureFlags.useDeviceProvidedSerializedRingerVibration()).thenReturn(true); + mockVibrationResourceValues( + /* defaultVibrationContent= */ "", /* useSimpleVibration= */ false); + when(mockVibratorInfo.areVibrationFeaturesSupported(any())).thenReturn(true); + + createRingerUnderTest(); + + assertEquals(EXPECTED_SIMPLE_VIBRATION_PATTERN, mRingerUnderTest.mDefaultVibrationEffect); + } + + @SmallTest + @Test public void testNoActionInTheaterMode() throws Exception { // Start call waiting to make sure that it doesn't stop when we start ringing mRingerUnderTest.startCallWaiting(mockCall1); @@ -231,7 +400,7 @@ public class RingerTest extends TelecomTestCase { @SmallTest @Test public void testCallWaitingButNoRingForSpecificContacts() throws Exception { - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false); + when(mockNotificationManager.matchesCallFilter(any(Uri.class))).thenReturn(false); // Start call waiting to make sure that it does stop when we start ringing mRingerUnderTest.startCallWaiting(mockCall1); verify(mockTonePlayer).startTone(); @@ -492,7 +661,7 @@ public class RingerTest extends TelecomTestCase { when(mContext.getSystemService(NotificationManager.class)).thenReturn( mockNotificationManager); // suppress the call - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false); + when(mockNotificationManager.matchesCallFilter(any(Uri.class))).thenReturn(false); // run the method under test assertFalse(mRingerUnderTest.shouldRingForContact(mockCall1)); @@ -501,7 +670,7 @@ public class RingerTest extends TelecomTestCase { // verify we never set the call object and matchesCallFilter is called verify(mockCall1, never()).setCallIsSuppressedByDoNotDisturb(true); verify(mockNotificationManager, times(1)) - .matchesCallFilter(any(Bundle.class)); + .matchesCallFilter(any(Uri.class)); } /** @@ -514,7 +683,6 @@ public class RingerTest extends TelecomTestCase { when(mockCall1.wasDndCheckComputedForCall()).thenReturn(false); when(mockCall1.getHandle()).thenReturn(Uri.parse("")); // alert the user of the call - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true); // run the method under test assertTrue(mRingerUnderTest.shouldRingForContact(mockCall1)); @@ -523,7 +691,7 @@ public class RingerTest extends TelecomTestCase { // verify we never set the call object and matchesCallFilter is called verify(mockCall1, never()).setCallIsSuppressedByDoNotDisturb(false); verify(mockNotificationManager, times(1)) - .matchesCallFilter(any(Bundle.class)); + .matchesCallFilter(any(Uri.class)); } /** @@ -539,7 +707,7 @@ public class RingerTest extends TelecomTestCase { // THEN assertFalse(mRingerUnderTest.shouldRingForContact(mockCall1)); verify(mockCall1, never()).setCallIsSuppressedByDoNotDisturb(false); - verify(mockNotificationManager, never()).matchesCallFilter(any(Bundle.class)); + verify(mockNotificationManager, never()).matchesCallFilter(any(Uri.class)); } @Test @@ -549,7 +717,7 @@ public class RingerTest extends TelecomTestCase { mRingerUnderTest.startCallWaiting(mockCall1); when(mockCall2.wasDndCheckComputedForCall()).thenReturn(false); when(mockCall2.getHandle()).thenReturn(Uri.parse("")); - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false); + when(mockNotificationManager.matchesCallFilter(any(Uri.class))).thenReturn(false); assertFalse(mRingerUnderTest.shouldRingForContact(mockCall2)); assertFalse(startRingingAndWaitForAsync(mockCall2, false)); @@ -564,7 +732,6 @@ public class RingerTest extends TelecomTestCase { mRingerUnderTest.startCallWaiting(mockCall1); when(mockCall2.wasDndCheckComputedForCall()).thenReturn(false); when(mockCall2.getHandle()).thenReturn(Uri.parse("")); - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true); assertTrue(mRingerUnderTest.shouldRingForContact(mockCall2)); assertTrue(startRingingAndWaitForAsync(mockCall2, false)); @@ -591,7 +758,6 @@ public class RingerTest extends TelecomTestCase { mRingerUnderTest.startCallWaiting(mockCall1); when(mockCall2.wasDndCheckComputedForCall()).thenReturn(false); when(mockCall2.getHandle()).thenReturn(Uri.parse("")); - when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true); assertTrue(mRingerUnderTest.shouldRingForContact(mockCall2)); assertTrue(mRingerUnderTest.startRinging(mockCall2, false)); @@ -670,4 +836,13 @@ public class RingerTest extends TelecomTestCase { when(mockRingtoneFactory.getHapticOnlyRingtone()).thenReturn(mockRingtone); return mockRingtone; } + + private void mockVibrationResourceValues( + String defaultVibrationContent, boolean useSimpleVibration) { + mComponentContextFixture.putRawResource( + com.android.internal.R.raw.default_ringtone_vibration_effect, + defaultVibrationContent); + mComponentContextFixture.putBooleanResource( + R.bool.use_simple_vibration_pattern, useSimpleVibration); + } } diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java index 8bc1f2a4d..e9466ee23 100644 --- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java +++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java @@ -58,11 +58,13 @@ import com.android.server.telecom.CallIntentProcessor; import com.android.server.telecom.CallState; import com.android.server.telecom.CallsManager; import com.android.server.telecom.DefaultDialerCache; +import com.android.server.telecom.InCallController; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.TelecomServiceImpl; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.components.UserCallIntentProcessor; import com.android.server.telecom.components.UserCallIntentProcessorFactory; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.voip.IncomingCallTransaction; import com.android.server.telecom.voip.OutgoingCallTransaction; import com.android.server.telecom.voip.TransactionManager; @@ -76,6 +78,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; +import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; @@ -86,6 +89,7 @@ import static android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -122,7 +126,7 @@ public class TelecomServiceImplTest extends TelecomTestCase { public static class CallIntentProcessAdapterFake implements CallIntentProcessor.Adapter { @Override public void processOutgoingCallIntent(Context context, CallsManager callsManager, - Intent intent, String callingPackage) { + Intent intent, String callingPackage, FeatureFlags flags) { } @@ -192,6 +196,9 @@ public class TelecomServiceImplTest extends TelecomTestCase { @Mock private ICallEventCallback mICallEventCallback; @Mock private TransactionManager mTransactionManager; @Mock private AnomalyReporterAdapter mAnomalyReporterAdapter; + @Mock private FeatureFlags mFeatureFlags; + + @Mock private InCallController mInCallController; private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; @@ -219,6 +226,7 @@ public class TelecomServiceImplTest extends TelecomTestCase { doReturn(mContext).when(mContext).getApplicationContext(); doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt()); + when(mFakeCallsManager.getInCallController()).thenReturn(mInCallController); doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class), anyString()); when(mContext.checkCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS)) @@ -242,6 +250,7 @@ public class TelecomServiceImplTest extends TelecomTestCase { mDefaultDialerCache, mSubscriptionManagerAdapter, mSettingsSecureAdapter, + mFeatureFlags, mLock); telecomServiceImpl.setTransactionManager(mTransactionManager); telecomServiceImpl.setAnomalyReporterAdapter(mAnomalyReporterAdapter); @@ -260,6 +269,7 @@ public class TelecomServiceImplTest extends TelecomTestCase { mPackageManager = mContext.getPackageManager(); when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid()); + when(mFeatureFlags.earlyBindingToIncallService()).thenReturn(true); } @Override @@ -1040,6 +1050,7 @@ public class TelecomServiceImplTest extends TelecomTestCase { verify(mFakePhoneAccountRegistrar).getPhoneAccount( TEL_PA_HANDLE_16, TEL_PA_HANDLE_16.getUserHandle()); + verify(mInCallController, never()).bindToServices(any()); addCallTestHelper(TelecomManager.ACTION_INCOMING_CALL, CallIntentProcessor.KEY_IS_INCOMING_CALL, extras, TEL_PA_HANDLE_16, false); @@ -1047,6 +1058,81 @@ public class TelecomServiceImplTest extends TelecomTestCase { @SmallTest @Test + public void testAddNewIncomingFlagDisabledNoEarlyBinding() throws Exception { + when(mFeatureFlags.earlyBindingToIncallService()).thenReturn(false); + PhoneAccount phoneAccount = makeSkipCallFilteringPhoneAccount(TEL_PA_HANDLE_16).build(); + phoneAccount.setIsEnabled(true); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( + eq(TEL_PA_HANDLE_16), any(UserHandle.class)); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked( + eq(TEL_PA_HANDLE_16)); + doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true); + Bundle extras = createSampleExtras(); + + mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE); + + verify(mInCallController, never()).bindToServices(null); + } + + @SmallTest + @Test + public void testAddNewIncomingCallEarlyBindingForNoCallFilterCalls() throws Exception { + PhoneAccount phoneAccount = makeSkipCallFilteringPhoneAccount(TEL_PA_HANDLE_16).build(); + phoneAccount.setIsEnabled(true); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( + eq(TEL_PA_HANDLE_16), any(UserHandle.class)); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked( + eq(TEL_PA_HANDLE_16)); + doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true); + Bundle extras = createSampleExtras(); + + mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE); + + verify(mInCallController).bindToServices(null); + } + + @SmallTest + @Test + public void testAddNewIncomingCallEarlyBindingNotEnableForNonWatchDevices() throws Exception { + PhoneAccount phoneAccount = makeSkipCallFilteringPhoneAccount(TEL_PA_HANDLE_16).build(); + phoneAccount.setIsEnabled(true); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( + eq(TEL_PA_HANDLE_16), any(UserHandle.class)); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked( + eq(TEL_PA_HANDLE_16)); + doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false); + Bundle extras = createSampleExtras(); + + mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE); + + verify(mInCallController, never()).bindToServices(null); + } + + @SmallTest + @Test + public void testAddNewIncomingCallEarlyBindingNotEnableForPhoneAccountHasCallFilters() + throws Exception { + PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_16).build(); + phoneAccount.setIsEnabled(true); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( + eq(TEL_PA_HANDLE_16), any(UserHandle.class)); + doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked( + eq(TEL_PA_HANDLE_16)); + doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true); + Bundle extras = createSampleExtras(); + + mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE); + + verify(mInCallController, never()).bindToServices(null); + } + + + @SmallTest + @Test public void testAddNewIncomingCallFailure() throws Exception { try { mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, null, CALLING_PACKAGE); @@ -1703,6 +1789,28 @@ public class TelecomServiceImplTest extends TelecomTestCase { verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class)); } + /** + * FeatureFlags is autogenerated code, so there could be a situation where something changes + * outside of Telecom control that breaks reflection. This test attempts to ensure that changes + * to auto-generated FeatureFlags code that breaks reflection are caught early. + */ + @SmallTest + @Test + public void testFlagConfigReflectionWorks() { + try { + Method[] methods = FeatureFlags.class.getMethods(); + for (Method m : methods) { + // test getting the name and invoking the flag code + String name = m.getName(); + Object val = m.invoke(mFeatureFlags); + assertNotNull(name); + assertNotNull(val); + } + } catch (Exception e) { + fail("Reflection failed for FeatureFlags with error: " + e); + } + } + @SmallTest @Test public void testIsVoicemailNumber() throws Exception { @@ -2144,6 +2252,12 @@ public class TelecomServiceImplTest extends TelecomTestCase { return new PhoneAccount.Builder(paHandle, "testLabel"); } + private PhoneAccount.Builder makeSkipCallFilteringPhoneAccount(PhoneAccountHandle paHandle) { + Bundle extras = new Bundle(); + extras.putBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING, true); + return new PhoneAccount.Builder(paHandle, "testLabel").setExtras(extras); + } + private Bundle createSampleExtras() { Bundle extras = new Bundle(); extras.putString("test_key", "test_value"); diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java index fb3512537..aa2cf5662 100644 --- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java @@ -38,6 +38,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; @@ -69,6 +70,7 @@ import android.telephony.TelephonyRegistryManager; import com.android.internal.telecom.IInCallAdapter; import com.android.server.telecom.AsyncRingtonePlayer; +import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioModeStateMachine; import com.android.server.telecom.CallAudioRouteStateMachine; @@ -98,6 +100,7 @@ import com.android.server.telecom.WiredHeadsetManager; import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.callfiltering.BlockedNumbersAdapter; import com.android.server.telecom.components.UserCallIntentProcessor; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.ui.IncomingCallNotifier; import com.google.common.base.Predicate; @@ -119,7 +122,7 @@ import java.util.concurrent.TimeUnit; /** * Implements mocks and functionality required to implement telecom system tests. */ -public class TelecomSystemTest extends TelecomTestCase { +public class TelecomSystemTest extends TelecomTestCase{ private static final String CALLING_PACKAGE = TelecomSystemTest.class.getPackageName(); static final int TEST_POLL_INTERVAL = 10; // milliseconds @@ -167,7 +170,7 @@ public class TelecomSystemTest extends TelecomTestCase { } @Override - public void showMissedCallNotification(CallInfo call) { + public void showMissedCallNotification(CallInfo call, @Nullable Uri uri) { missedCallsNotified.add(call); } @@ -214,6 +217,10 @@ public class TelecomSystemTest extends TelecomTestCase { @Mock Ringer.AccessibilityManagerAdapter mAccessibilityManagerAdapter; @Mock BlockedNumbersAdapter mBlockedNumbersAdapter; + @Mock + CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; + @Mock + FeatureFlags mFeatureFlags; final ComponentName mInCallServiceComponentNameX = new ComponentName( @@ -320,6 +327,20 @@ public class TelecomSystemTest extends TelecomTestCase { PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) .build(); + final PhoneAccount mPhoneAccountMultiUser = + PhoneAccount.builder( + new PhoneAccountHandle( + mConnectionServiceComponentNameA, + "id MU", UserHandle.of(12)), + "Phone account service MU") + .addSupportedUriScheme("tel") + .setCapabilities( + PhoneAccount.CAPABILITY_CALL_PROVIDER | + PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | + PhoneAccount.CAPABILITY_VIDEO_CALLING | + PhoneAccount.CAPABILITY_MULTI_USER) + .build(); + ConnectionServiceFixture mConnectionServiceFixtureA; ConnectionServiceFixture mConnectionServiceFixtureB; Timeouts.Adapter mTimeoutsAdapter; @@ -493,9 +514,11 @@ public class TelecomSystemTest extends TelecomTestCase { when(mRoleManagerAdapter.getCallCompanionApps()).thenReturn(Collections.emptyList()); when(mRoleManagerAdapter.getDefaultCallScreeningApp(any(UserHandle.class))) .thenReturn(null); + when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(false); mTelecomSystem = new TelecomSystem( mComponentContextFixture.getTestDouble(), - (context, phoneAccountRegistrar, defaultDialerCache, mDeviceIdleControllerAdapter) + (context, phoneAccountRegistrar, defaultDialerCache, mDeviceIdleControllerAdapter, + mFeatureFlag) -> mMissedCallNotifier, mCallerInfoAsyncQueryFactoryFixture.getTestDouble(), headsetMediaButtonFactory, @@ -518,7 +541,9 @@ public class TelecomSystemTest extends TelecomTestCase { StatusBarNotifier statusBarNotifier, CallAudioManager.AudioServiceFactory audioServiceFactory, int earpieceControl, - Executor asyncTaskExecutor) { + Executor asyncTaskExecutor, + CallAudioCommunicationDeviceTracker communicationDeviceTracker, + FeatureFlags featureFlags) { return new CallAudioRouteStateMachine(context, callsManager, bluetoothManager, @@ -528,15 +553,20 @@ public class TelecomSystemTest extends TelecomTestCase { // Force enable an earpiece for the end-to-end tests CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, mHandlerThread.getLooper(), - Runnable::run /* async tasks as now sync for testing! */); + Runnable::run /* async tasks as now sync for testing! */, + communicationDeviceTracker, + featureFlags); } }, new CallAudioModeStateMachine.Factory() { @Override public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper, - AudioManager am) { + AudioManager am, FeatureFlags featureFlags, + CallAudioCommunicationDeviceTracker callAudioCommunicationDeviceTracker + ) { return new CallAudioModeStateMachine(systemStateHelper, am, - mHandlerThread.getLooper()); + mHandlerThread.getLooper(), featureFlags, + callAudioCommunicationDeviceTracker); } }, mClockProxy, @@ -550,7 +580,8 @@ public class TelecomSystemTest extends TelecomTestCase { }, mDeviceIdleControllerAdapter, mAccessibilityManagerAdapter, Runnable::run, Runnable::run, - mBlockedNumbersAdapter); + mBlockedNumbersAdapter, + mFeatureFlags); mComponentContextFixture.setTelecomManager(new TelecomManager( mComponentContextFixture.getTestDouble(), @@ -584,6 +615,7 @@ public class TelecomSystemTest extends TelecomTestCase { mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0); mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE0); mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE1); + mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountMultiUser); mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount( mPhoneAccountA0.getAccountHandle(), Process.myUserHandle()); diff --git a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java index 5353bc642..e8389a06d 100644 --- a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java +++ b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java @@ -22,6 +22,9 @@ import android.telecom.Log; import androidx.test.InstrumentationRegistry; +import com.android.server.telecom.flags.FeatureFlags; + +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -33,6 +36,8 @@ import java.util.function.Predicate; public abstract class TelecomTestCase { protected static final String TESTING_TAG = "Telecom-TEST"; protected Context mContext; + @Mock + FeatureFlags mFeatureFlags; MockitoHelper mMockitoHelper = new MockitoHelper(); ComponentContextFixture mComponentContextFixture; @@ -42,11 +47,12 @@ public abstract class TelecomTestCase { Log.setIsExtendedLoggingEnabled(true); Log.setUnitTestingEnabled(true); mMockitoHelper.setUp(InstrumentationRegistry.getContext(), getClass()); - mComponentContextFixture = new ComponentContextFixture(); + MockitoAnnotations.initMocks(this); + + mComponentContextFixture = new ComponentContextFixture(mFeatureFlags); mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); Log.setSessionContext(mComponentContextFixture.getTestDouble().getApplicationContext()); Log.getSessionManager().mCleanStaleSessions = null; - MockitoAnnotations.initMocks(this); } public void tearDown() throws Exception { diff --git a/tests/src/com/android/server/telecom/tests/TransactionTests.java b/tests/src/com/android/server/telecom/tests/TransactionTests.java index 3fc87a9fa..e58c6c4d0 100644 --- a/tests/src/com/android/server/telecom/tests/TransactionTests.java +++ b/tests/src/com/android/server/telecom/tests/TransactionTests.java @@ -16,7 +16,11 @@ package com.android.server.telecom.tests; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -39,11 +43,15 @@ import android.telecom.CallAttributes; import android.telecom.DisconnectCause; import android.telecom.PhoneAccountHandle; +import androidx.test.filters.SmallTest; + import com.android.server.telecom.Call; import com.android.server.telecom.CallState; import com.android.server.telecom.CallerInfoLookupHelper; import com.android.server.telecom.CallsManager; import com.android.server.telecom.ClockProxy; +import com.android.server.telecom.ConnectionServiceWrapper; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.PhoneNumberUtilsAdapter; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.ui.ToastFactory; @@ -53,6 +61,8 @@ import com.android.server.telecom.voip.IncomingCallTransaction; import com.android.server.telecom.voip.OutgoingCallTransaction; import com.android.server.telecom.voip.MaybeHoldCallForNewCallTransaction; import com.android.server.telecom.voip.RequestNewActiveCallTransaction; +import com.android.server.telecom.voip.VerifyCallStateChangeTransaction; +import com.android.server.telecom.voip.VoipCallTransactionResult; import org.junit.After; import org.junit.Before; @@ -62,6 +72,11 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + public class TransactionTests extends TelecomTestCase { @@ -250,6 +265,65 @@ public class TransactionTests extends TelecomTestCase { isA(Boolean.class)); } + /** + * This test verifies if the ConnectionService call is NOT transitioned to the desired call + * state (within timeout period), Telecom will disconnect the call. + */ + @SmallTest + @Test + public void testCallStateChangeTimesOut() + throws ExecutionException, InterruptedException, TimeoutException { + when(mFeatureFlags.transactionalCsVerifier()).thenReturn(true); + VerifyCallStateChangeTransaction t = new VerifyCallStateChangeTransaction(mCallsManager, + mMockCall1, CallState.ON_HOLD, true); + // WHEN + setupHoldableCall(); + + // simulate the transaction being processed and the CompletableFuture timing out + t.processTransaction(null); + CompletableFuture<Integer> timeoutFuture = t.getCallStateOrTimeoutResult(); + timeoutFuture.complete(VerifyCallStateChangeTransaction.FAILURE_CODE); + + // THEN + verify(mMockCall1, times(1)).addCallStateListener(t.getCallStateListenerImpl()); + assertEquals(timeoutFuture.get().intValue(), VerifyCallStateChangeTransaction.FAILURE_CODE); + assertEquals(VoipCallTransactionResult.RESULT_FAILED, + t.getTransactionResult().get(2, TimeUnit.SECONDS).getResult()); + verify(mMockCall1, atLeastOnce()).removeCallStateListener(any()); + verify(mCallsManager, times(1)).markCallAsDisconnected(eq(mMockCall1), any()); + verify(mCallsManager, times(1)).markCallAsRemoved(eq(mMockCall1)); + } + + /** + * This test verifies that when an application transitions a call to the requested state, + * Telecom does not disconnect the call and transaction completes successfully. + */ + @SmallTest + @Test + public void testCallStateIsSuccessfullyChanged() + throws ExecutionException, InterruptedException, TimeoutException { + when(mFeatureFlags.transactionalCsVerifier()).thenReturn(true); + VerifyCallStateChangeTransaction t = new VerifyCallStateChangeTransaction(mCallsManager, + mMockCall1, CallState.ON_HOLD, true); + // WHEN + setupHoldableCall(); + + // simulate the transaction being processed and the setOnHold() being called / state change + t.processTransaction(null); + t.getCallStateListenerImpl().onCallStateChanged(CallState.ON_HOLD); + when(mMockCall1.getState()).thenReturn(CallState.ON_HOLD); + + // THEN + verify(mMockCall1, times(1)).addCallStateListener(t.getCallStateListenerImpl()); + assertEquals(t.getCallStateOrTimeoutResult().get().intValue(), + VerifyCallStateChangeTransaction.SUCCESS_CODE); + assertEquals(VoipCallTransactionResult.RESULT_SUCCEED, + t.getTransactionResult().get(2, TimeUnit.SECONDS).getResult()); + verify(mMockCall1, atLeastOnce()).removeCallStateListener(any()); + verify(mCallsManager, never()).markCallAsDisconnected(eq(mMockCall1), any()); + verify(mCallsManager, never()).markCallAsRemoved(eq(mMockCall1)); + } + private Call createSpyCall(PhoneAccountHandle targetPhoneAccount, int initialState, String id) { when(mCallsManager.getCallerInfoLookupHelper()).thenReturn(mCallerInfoLookupHelper); @@ -267,7 +341,8 @@ public class TransactionTests extends TelecomTestCase { false /* shouldAttachToExistingConnection*/, false /* isConference */, mClockProxy, - mToastFactory); + mToastFactory, + mFeatureFlags); Call callSpy = Mockito.spy(call); @@ -280,4 +355,12 @@ public class TransactionTests extends TelecomTestCase { return callSpy; } + + private void setupHoldableCall(){ + when(mMockCall1.getState()).thenReturn(CallState.ACTIVE); + when(mMockCall1.getConnectionServiceWrapper()).thenReturn( + mock(ConnectionServiceWrapper.class)); + doNothing().when(mMockCall1).addCallStateListener(any()); + doReturn(true).when(mMockCall1).removeCallStateListener(any()); + } }
\ No newline at end of file diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java index 84beedc0f..c77a614e3 100644 --- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java +++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java @@ -32,6 +32,7 @@ import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import com.android.server.telecom.CallAudioModeStateMachine; +import com.android.server.telecom.CallAudioRouteAdapter; import com.android.server.telecom.CallAudioRouteStateMachine; import java.util.List; @@ -258,13 +259,13 @@ public class VideoCallTests extends TelecomSystemTest { */ private void verifyAudioRoute(int expectedRoute) throws Exception { // Capture all onCallAudioStateChanged callbacks to InCall. - CallAudioRouteStateMachine carsm = mTelecomSystem.getCallsManager() - .getCallAudioManager().getCallAudioRouteStateMachine(); + CallAudioRouteAdapter cara = mTelecomSystem.getCallsManager() + .getCallAudioManager().getCallAudioRouteAdapter(); CallAudioModeStateMachine camsm = mTelecomSystem.getCallsManager() .getCallAudioManager().getCallAudioModeStateMachine(); waitForHandlerAction(camsm.getHandler(), TEST_TIMEOUT); final boolean[] success = {true}; - carsm.sendMessage(CallAudioRouteStateMachine.RUN_RUNNABLE, (Runnable) () -> { + cara.sendMessage(CallAudioRouteStateMachine.RUN_RUNNABLE, (Runnable) () -> { ArgumentCaptor<CallAudioState> callAudioStateArgumentCaptor = ArgumentCaptor.forClass( CallAudioState.class); try { @@ -277,7 +278,7 @@ public class VideoCallTests extends TelecomSystemTest { assertEquals(expectedRoute, changes.get(changes.size() - 1).getRoute()); success[0] = true; }); - waitForHandlerAction(carsm.getHandler(), TEST_TIMEOUT); + waitForHandlerAction(cara.getAdapterHandler(), TEST_TIMEOUT); assertTrue(success[0]); } } diff --git a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java index c66b0f715..ddea231c1 100644 --- a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java +++ b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java @@ -16,6 +16,12 @@ package com.android.server.telecom.tests; +import static android.app.ForegroundServiceDelegationOptions.DELEGATION_SERVICE_PHONE_CALL; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL; + import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -86,6 +92,31 @@ public class VoipCallMonitorTest extends TelecomTestCase { .thenReturn(true); } + /** + * This test ensures VoipCallMonitor is passing the correct foregroundServiceTypes when starting + * foreground service delegation on behalf of a client. + */ + @SmallTest + @Test + public void testVerifyForegroundServiceTypesBeingPassedToActivityManager() { + Call call = createTestCall("testCall", mHandle1User1); + ArgumentCaptor<ForegroundServiceDelegationOptions> optionsCaptor = + ArgumentCaptor.forClass(ForegroundServiceDelegationOptions.class); + + mMonitor.onCallAdded(call); + + verify(mActivityManagerInternal, timeout(TIMEOUT)).startForegroundServiceDelegate( + optionsCaptor.capture(), any(ServiceConnection.class)); + + assertEquals( FOREGROUND_SERVICE_TYPE_PHONE_CALL | + FOREGROUND_SERVICE_TYPE_MICROPHONE | + FOREGROUND_SERVICE_TYPE_CAMERA | + FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE, + optionsCaptor.getValue().mForegroundServiceTypes); + + mMonitor.onCallRemoved(call); + } + @SmallTest @Test public void testStartMonitorForOneCall() { |