Add BluetoothRouteManager (multi-hfp part 2)
am: ea8d15df3c
Change-Id: I5d322c7c773c1b410ed880e65d51d8f6ae6333ff
diff --git a/Android.mk b/Android.mk
index 4785b24..79ef194 100644
--- a/Android.mk
+++ b/Android.mk
@@ -5,9 +5,13 @@
LOCAL_JAVA_LIBRARIES := telephony-common
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-proto-files-under, proto)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/proto/
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
+
LOCAL_PACKAGE_NAME := Telecom
LOCAL_CERTIFICATE := platform
diff --git a/proto/telecom.proto b/proto/telecom.proto
new file mode 100644
index 0000000..06dd394
--- /dev/null
+++ b/proto/telecom.proto
@@ -0,0 +1,280 @@
+syntax = "proto2";
+
+package com.android.server.telecom;
+
+option java_package = "com.android.server.telecom";
+option java_outer_classname = "TelecomLogClass";
+
+// The information about the telecom events.
+message TelecomLog {
+
+ // Information about each call.
+ repeated CallLog call_logs = 1;
+
+ // Timing information for the logging sessions
+ repeated LogSessionTiming session_timings = 2;
+}
+
+message LogSessionTiming {
+ enum SessionEntryPoint {
+ ICA_ANSWER_CALL = 1;
+ ICA_REJECT_CALL = 2;
+ ICA_DISCONNECT_CALL = 3;
+ ICA_HOLD_CALL = 4;
+ ICA_UNHOLD_CALL = 5;
+ ICA_MUTE = 6;
+ ICA_SET_AUDIO_ROUTE = 7;
+ ICA_CONFERENCE = 8;
+
+ CSW_HANDLE_CREATE_CONNECTION_COMPLETE = 100;
+ CSW_SET_ACTIVE = 101;
+ CSW_SET_RINGING = 102;
+ CSW_SET_DIALING = 103;
+ CSW_SET_DISCONNECTED = 104;
+ CSW_SET_ON_HOLD = 105;
+ CSW_REMOVE_CALL = 106;
+ CSW_SET_IS_CONFERENCED = 107;
+ CSW_ADD_CONFERENCE_CALL = 108;
+ }
+
+ // The entry point into Telecom code that this session tracks.
+ optional SessionEntryPoint sessionEntryPoint = 1;
+ // The time it took for this session to finish.
+ optional int64 time_millis = 2;
+}
+
+message Event {
+ // From android.telecom.ParcelableAnalytics
+ enum EventName {
+ SET_SELECT_PHONE_ACCOUNT = 0;
+ SET_ACTIVE = 1;
+ SET_DISCONNECTED = 2;
+ START_CONNECTION = 3;
+ SET_DIALING = 4;
+ BIND_CS = 5;
+ CS_BOUND = 6;
+ REQUEST_ACCEPT = 7;
+ REQUEST_REJECT = 8;
+
+ SCREENING_SENT = 100;
+ SCREENING_COMPLETED = 101;
+ DIRECT_TO_VM_INITIATED = 102;
+ DIRECT_TO_VM_FINISHED = 103;
+ BLOCK_CHECK_INITIATED = 104;
+ BLOCK_CHECK_FINISHED = 105;
+ FILTERING_INITIATED = 106;
+ FILTERING_COMPLETED = 107;
+ FILTERING_TIMED_OUT = 108;
+
+ SKIP_RINGING = 200;
+ SILENCE = 201;
+ MUTE = 202;
+ UNMUTE = 203;
+ AUDIO_ROUTE_BT = 204;
+ AUDIO_ROUTE_EARPIECE = 205;
+ AUDIO_ROUTE_HEADSET = 206;
+ AUDIO_ROUTE_SPEAKER = 207;
+
+ CONFERENCE_WITH = 300;
+ SPLIT_CONFERENCE = 301;
+ SET_PARENT = 302;
+
+ REQUEST_HOLD = 400;
+ REQUEST_UNHOLD = 401;
+ REMOTELY_HELD = 402;
+ REMOTELY_UNHELD = 403;
+ SET_HOLD = 404;
+ SWAP = 405;
+
+ REQUEST_PULL = 500;
+ }
+
+ // The ID of the event.
+ optional EventName event_name = 1;
+
+ // The elapsed time since the last event, rounded to one significant digit.
+ // If the event is the first, this will be negative.
+ optional int64 time_since_last_event_millis = 2;
+}
+
+message VideoEvent {
+ // From android.telecom.ParcelableCallAnalytics
+ enum VideoEventName {
+ SEND_LOCAL_SESSION_MODIFY_REQUEST = 0;
+ SEND_LOCAL_SESSION_MODIFY_RESPONSE = 1;
+ RECEIVE_REMOTE_SESSION_MODIFY_REQUEST = 2;
+ RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE = 3;
+ }
+
+ // From android.telecom.VideoProfile
+ enum VideoState {
+ STATE_AUDIO_ONLY = 0;
+ STATE_TX_ENABLED = 1;
+ STATE_RX_ENABLED = 2;
+ STATE_BIDIRECTIONAL = 3;
+ STATE_PAUSED = 4;
+ }
+
+ // The ID of the event.
+ optional VideoEventName event_name = 1;
+
+ // The elapsed time since the last event, rounded to one significant digit.
+ // If the event is the first, this will be negative.
+ optional int64 time_since_last_event_millis = 2;
+
+ // The video state
+ optional int32 video_state = 3;
+}
+
+message EventTimingEntry {
+ enum EventTimingName {
+ ACCEPT_TIMING = 0;
+ REJECT_TIMING = 1;
+ DISCONNECT_TIMING = 2;
+ HOLD_TIMING = 3;
+ UNHOLD_TIMING = 4;
+ OUTGOING_TIME_TO_DIALING_TIMING = 5;
+ BIND_CS_TIMING = 6;
+ SCREENING_COMPLETED_TIMING = 7;
+ DIRECT_TO_VM_FINISHED_TIMING = 8;
+ BLOCK_CHECK_FINISHED_TIMING = 9;
+ FILTERING_COMPLETED_TIMING = 10;
+ FILTERING_TIMED_OUT_TIMING = 11;
+ }
+
+ // The name of the event timing.
+ optional EventTimingName timing_name = 1;
+
+ // The number of milliseconds that this event pair took.
+ optional int64 time_millis = 2;
+}
+
+message InCallServiceInfo {
+ // Keep this up-to-date with com.android.server.telecom.InCallController.
+ enum InCallServiceType {
+ IN_CALL_SERVICE_TYPE_INVALID = 0;
+ IN_CALL_SERVICE_TYPE_DIALER_UI = 1;
+ IN_CALL_SERVICE_TYPE_SYSTEM_UI = 2;
+ IN_CALL_SERVICE_TYPE_CAR_MODE_UI = 3;
+ IN_CALL_SERVICE_TYPE_NON_UI = 4;
+ }
+
+ // The shortened component name of the in-call service.
+ optional string in_call_service_name = 1;
+
+ // The type of the in-call service
+ optional InCallServiceType in_call_service_type = 2;
+}
+
+// Information about each call.
+message CallLog {
+
+ // Information on call-types.
+ enum CallType {
+
+ // Call type is not known.
+ CALLTYPE_UNKNOWN = 0;
+
+ // Incoming call.
+ CALLTYPE_INCOMING = 1;
+
+ // Outgoing call.
+ CALLTYPE_OUTGOING = 2;
+ }
+
+ // Termination code.
+ enum CallTerminationCode {
+
+ // Disconnected because of an unknown or unspecified reason.
+ CALL_TERMINATION_CODE_UNKNOWN = 0;
+
+ // Disconnected because there was an error, such as a problem
+ // with the network.
+ CALL_TERMINATION_CODE_ERROR = 1;
+
+ // Disconnected because of a local user-initiated action,
+ // such as hanging up.
+ CALL_TERMINATION_CODE_LOCAL = 2;
+
+ // Disconnected because of a remote user-initiated action,
+ // such as the other party hanging up.
+ CALL_TERMINATION_CODE_REMOTE = 3;
+
+ // Disconnected because it has been canceled.
+ CALL_TERMINATION_CODE_CANCELED = 4;
+
+ // Disconnected because there was no response to an incoming call.
+ CALL_TERMINATION_CODE_MISSED = 5;
+
+ // Disconnected because the user rejected an incoming call.
+ CALL_TERMINATION_CODE_REJECTED = 6;
+
+ // Disconnected because the other party was busy.
+ CALL_TERMINATION_CODE_BUSY = 7;
+
+ // Disconnected because of a restriction on placing the call,
+ // such as dialing in airplane mode.
+ CALL_TERMINATION_CODE_RESTRICTED = 8;
+
+ // Disconnected for reason not described by other disconnect codes.
+ CALL_TERMINATION_CODE_OTHER = 9;
+
+ // Disconnected because the connection manager did not support the call.
+ // The call will be tried again without a connection manager.
+ CONNECTION_MANAGER_NOT_SUPPORTED = 10;
+ }
+
+ // Start time of the connection.
+ // Rounded to the nearest 5 minute interval.
+ optional int64 start_time_5min = 1;
+
+ // Duration in millis.
+ optional int64 call_duration_millis = 2;
+
+ // Call type.
+ optional CallType type = 3;
+
+ // True if the call interrupted an in-progress call, whether it was the
+ // user dialing out during a call or an incoming call during another call.
+ optional bool is_additional_call = 4 [default = false];
+
+ // True if the call was interrupted by another call.
+ optional bool is_interrupted = 5 [default = false];
+
+ // A bitmask with bits corresponding to call technologies that were used
+ // during the call. The ones that we will record are CDMA, GSM, IMS, SIP,
+ // and third-party.
+ // See the com.android.server.telecom.Analytics.*_PHONE constants.
+ optional int32 call_technologies = 6;
+
+ // Indicates the call termination code.
+ optional CallTerminationCode call_termination_code = 7;
+
+ // A list of the package names of connection services used.
+ repeated string connection_service = 9;
+
+ // Set to true if the call was created from createCallForExistingConnection.
+ optional bool is_created_from_existing_connection = 10 [default = false];
+
+ // Set to true if its an emergency call.
+ optional bool is_emergency_call = 11 [default = false];
+
+ // A list of the events that occur during the call.
+ repeated Event call_events = 12;
+
+ // A map from the names of latency timings to the timings.
+ repeated EventTimingEntry call_timings = 13;
+
+ // Whether this call has ever been a video call
+ optional bool is_video_call = 14 [default = false];
+
+ // A list of the video events during the call.
+ repeated VideoEvent video_events = 15;
+
+ // A list of the in-call services bound during the call.
+ repeated InCallServiceInfo in_call_services = 16;
+
+ // A bitmask of the properties that were set at any point during the call.
+ // Bits are defined by android.telecom.Connection.PROPERTY_* constants.
+ optional int32 connection_properties = 17;
+}
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index e46f852..2109cef 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Vermiste stemboodskapnommer"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Geen stemboodskapnommer is op die SIM-kaart gestoor nie."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Voeg nommer by"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Verander verstekbellerprogram?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Gebruik <xliff:g id="NEW_APP">%1$s</xliff:g> eerder as <xliff:g id="CURRENT_APP">%2$s</xliff:g> as jou verstekbellerprogram?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Gebruik <xliff:g id="NEW_APP">%s</xliff:g> as jou verstekbellerprogram?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Maak <xliff:g id="NEW_APP">%s</xliff:g> jou verstek-Foon-program?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Stel verstek"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Kanselleer"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> sal oproepe kan maak en alle aspekte daarvan beheer. Net programme wat jy vertrou, moet as die verstek-Foon-program gestel word."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Geblokkeerde nommers"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Jy sal nie oproepe of boodskappe vanaf geblokkeerde nommers ontvang nie."</string>
<string name="block_number" msgid="1101252256321306179">"Voeg \'n nommer by"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 3c62c86..41f8b2d 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"የድምፅመልዕክት ቁጥርአመለጠ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"በSIM ካርዱ ላይምንም የድምፅመልዕክት ቁጥር አልከተቀመጠም።"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"ቁጥር አክል"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ነባሪ መደወያ መተግበሪያ ይለወጥ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g>ን በ<xliff:g id="CURRENT_APP">%2$s</xliff:g> ምትክ እንደ የእርስዎ ነባሪ መደወያ መተግበሪያ ይጠቀም?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g>ን እንደ የእርስዎ ነባሪ መደወያ መተግበሪያ ይጠቀም?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> የስልክዎ ነባሪ መተግበሪያ ይደረግ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ነባሪ አዘጋጅ"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ይቅር"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ጥሪዎች ማድረግ እና ሁሉንም የጥሪ ገጽታዎች መቆጣጠር ይችላል። ነባሪ መተግበሪያ መደረግ ያለባቸው እርስዎ የሚያምኗቸው መተግበሪያዎች ብቻ መሆን አለባቸው።"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"የታገዱ ቁጥሮች"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ከታገዱ ቁጥሮች ጥሪዎች ወይም ጽሑፎች አይቀበሉም።"</string>
<string name="block_number" msgid="1101252256321306179">"ቁጥር ያክሉ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 40b895d..8e3abbe 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"رقم البريد الصوتي مفقود"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"لم يتم تخزين رقم بريد صوتي على شريحة SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"إضافة رقم"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"هل تريد تغيير التطبيق الافتراضي لبرنامج الاتصال؟"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"هل تريد استخدام <xliff:g id="NEW_APP">%1$s</xliff:g> بدلاً من <xliff:g id="CURRENT_APP">%2$s</xliff:g> تطبيقًا افتراضيًا لبرنامج الاتصال؟"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"هل تريد استخدام <xliff:g id="NEW_APP">%s</xliff:g> تطبيقًا افتراضيًا لبرنامج الاتصال؟"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"هل تريد تعيين <xliff:g id="NEW_APP">%s</xliff:g> باعتباره تطبيق الهاتف الافتراضي؟"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"تعيين كافتراضي"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"إلغاء"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"سيتمكن <xliff:g id="NEW_APP">%s</xliff:g> من إجراء المكالمات والتحكم في كل جوانبها. يمكن فقط تعيين التطبيقات التي تثق بها باعتبارها تطبيق الهاتف الافتراضي."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"الأرقام المحظورة"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"لن تتلقى المكالمات أو المراسلات النصية من الأرقام المحظورة."</string>
<string name="block_number" msgid="1101252256321306179">"إضافة رقم"</string>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index 21936d8..850e121 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Səsli poçt nömrəsi çatışmır"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartda heç bir səsli poçt nömrəsi yoxdur."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Nömrə əlavə edin"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Defolt nömrə yığan tətbiqi dəyişdirilsin?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Defolt nömrə yığan tətbiqi kimi <xliff:g id="CURRENT_APP">%2$s</xliff:g> əvəzinə <xliff:g id="NEW_APP">%1$s</xliff:g> işlədilsin?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Defolt nömrə yığan tətbiqi kimi <xliff:g id="NEW_APP">%s</xliff:g> işlədilsin?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> tətbiüi defolt Phone tətbiqi təyin edilsin?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Defolt ayarlayın"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Ləğv edin"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> bütün zəngləri edə və nəzarətdə saxlaya biləcək. Yalnız güvəndiyiniz tətbiqləri Telefon tətbiqi kimi ayarlaya bilərsiniz."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Bloklanmış nömrələr"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Blok edilmiş nömrədən zənglər və ya mesajlar almayacaqsınız."</string>
<string name="block_number" msgid="1101252256321306179">"Nömrə əlavə edin"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 605f6ca..bbe04b8 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Липсващ номер на гласова поща"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"На SIM картата няма съхранен номер за гласова поща."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Добавяне на номер"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Да се промени ли основното приложение за дайлер?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g> да се използва ли вместо <xliff:g id="CURRENT_APP">%2$s</xliff:g> като основното ви приложение за дайлер?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Да се използва ли <xliff:g id="NEW_APP">%s</xliff:g> като основното ви приложение за дайлер?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> да бъде ли стандартното ви приложение за телефон?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Задаване като стандартно"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Отказ"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ще може да извършва обаждания и да контролира всички аспекти на обажданията. Като стандартно приложение за телефон задавайте само приложения, на които имате доверие."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Блокирани номера"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Няма да получавате обаждания или SMS от блокираните номера."</string>
<string name="block_number" msgid="1101252256321306179">"Добавяне на номер"</string>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index 1ce7c85..088ca2a 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ভয়েসমেল নম্বর অনুপস্থিত"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"সিম কার্ডটিতে কোনো ভয়েসমেল নম্বর সংরক্ষিত নেই৷"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"একটি নম্বর যোগ করুন"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ডিফল্ট ডায়ালার অ্যাপ পরিবর্তন করবেন?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"আপনার ডিফল্ট ডায়লার অ্যাপ হিসেবে <xliff:g id="CURRENT_APP">%2$s</xliff:g> পরিবর্তে <xliff:g id="NEW_APP">%1$s</xliff:g> ব্যবহার করবেন?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"আপনার ডিফল্ট ডায়লার অ্যাপ হিসেবে <xliff:g id="NEW_APP">%s</xliff:g> ব্যবহার করবেন?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> কে আপনার ডিফল্ট ফোন অ্যাপ বানাতে চান?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ডিফল্ট হিসাবে সেট করুন"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"বাতিল করুন"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> কল করতে এবং কলের সমগ্র বৈশিষ্ট্য নিয়ন্ত্রণ করতে সক্ষম হবে৷ শুধুমাত্র আপনি যে অ্যাপ্সকে বিশ্বাস করেন সেগুলিকেই ডিফল্ট ফোন অ্যাপ হিসাবে সেট করা উচিৎ৷"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"অবরুদ্ধ নম্বরগুলি"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"অবরুদ্ধ নম্বরগুলি থেকে আপনি কল বা এসএমএস পাবেন না।"</string>
<string name="block_number" msgid="1101252256321306179">"একটি নম্বর যোগ করুন"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index fc92f36..9504895 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Falta el número de la bústia de veu"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"No hi ha cap número de bústia de veu emmagatzemat a la targeta SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Afegeix número"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Vols canviar l\'aplicació de marcador predeterminada?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Vols fer servir <xliff:g id="NEW_APP">%1$s</xliff:g> en lloc de <xliff:g id="CURRENT_APP">%2$s</xliff:g> com a aplicació de marcador predeterminada?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Vols fer servir <xliff:g id="NEW_APP">%s</xliff:g> com a aplicació de marcador predeterminada?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Vols que <xliff:g id="NEW_APP">%s</xliff:g> sigui l\'aplicació per a mòbils predetermin.?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Defineix com a predeterminat"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancel·la"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> podrà fer les teves trucades i controlar-ne tots els aspectes. Només les aplicacions de confiança s\'han de definir com a l\'aplicació per a mòbils predeterminada."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Números bloquejats"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"No rebràs trucades ni missatges de text dels números bloquejats."</string>
<string name="block_number" msgid="1101252256321306179">"Afegeix un número"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 8f4e4fc..ac77aac 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Chybí číslo hlasové schránky"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Na SIM kartě není uloženo žádné číslo hlasové schránky."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Přidat číslo"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Změnit výchozí aplikaci vytáčení?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Chcete aplikaci <xliff:g id="NEW_APP">%1$s</xliff:g> použít jako výchozí aplikaci vytáčení místo aplikace <xliff:g id="CURRENT_APP">%2$s</xliff:g>?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Chcete aplikaci <xliff:g id="NEW_APP">%s</xliff:g> použít jako výchozí aplikaci vytáčení?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Nastavit <xliff:g id="NEW_APP">%s</xliff:g> jako výchozí aplikaci na telefonování?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Nastavit jako výchozí"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Zrušit"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"Aplikace <xliff:g id="NEW_APP">%s</xliff:g> bude moci uskutečňovat hovory a spravovat všechny jejich aspekty. Jako výchozí aplikaci na telefonování byste měli nastavit jen aplikaci, které věříte."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokovaná čísla"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Ze zablokovaných čísel už nebudete přijímat hovory ani zprávy SMS."</string>
<string name="block_number" msgid="1101252256321306179">"Přidat číslo"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index f90cecf..48fba35 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Telefonsvarernummer mangler"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Der er ikke gemt noget telefonsvarernummer på SIM-kortet."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Tilføj nummer"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Vil du skifte standardappen til opkald?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Brug <xliff:g id="NEW_APP">%1$s</xliff:g> i stedet for <xliff:g id="CURRENT_APP">%2$s</xliff:g> som din standardapp til opkald?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Brug <xliff:g id="NEW_APP">%s</xliff:g> som din standardapp til opkald?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Vil du gøre <xliff:g id="NEW_APP">%s</xliff:g> til din standardapp til opkald?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Indstil standard"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Annuller"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> kan foretage og administrere alle aspekter af opkald. Du bør kun indstille en app til din standardapp til opkald, hvis du har tillid til den."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokerede telefonnumre"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Du modtager ikke opkald eller sms-beskeder fra blokerede numre."</string>
<string name="block_number" msgid="1101252256321306179">"Tilføj et nummer"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 71949ea..7993f35 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Fehlende Mailbox-Nummer"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Auf der SIM-Karte ist keine Mailbox-Nummer gespeichert."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Nummer hinzufügen"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Standard-App für Telefonie ändern?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g> statt <xliff:g id="CURRENT_APP">%2$s</xliff:g> als Standard-App für Telefonie verwenden?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> als Standard-App für Telefonie verwenden?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> als Standard-Telefon-App festlegen?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Als Standard festlegen"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Abbrechen"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> wird alle Anruffunktionen steuern. Nur vertrauenswürdige Apps sollten als Standard-Telefon-App festgelegt werden."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blockierte Nummern"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Du erhältst keine Anrufe oder SMS von blockierten Nummern."</string>
<string name="block_number" msgid="1101252256321306179">"Nummer hinzufügen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index c39387a..06ee5ab 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Λείπει ο αριθμός αυτόματου τηλεφωνητή"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Δεν έχει αποθηκευτεί αριθμός για τον αυτόματο τηλεφωνητή στην κάρτα SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Προσθήκη αριθμού"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Αλλαγή της προεπιλεγμένης εφαρμογής Dialer;"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Χρήση της εφαρμογής <xliff:g id="NEW_APP">%1$s</xliff:g> αντί για την εφαρμογή <xliff:g id="CURRENT_APP">%2$s</xliff:g> ως προεπιλεγμένης εφαρμογής Dialer;"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Χρήση της εφαρμογής <xliff:g id="NEW_APP">%s</xliff:g> ως προεπιλεγμένης εφαρμογής Dialer;"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Ορισμός <xliff:g id="NEW_APP">%s</xliff:g> ως προεπιλεγμένης εφαρμογής τηλεφώνου;"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Ορισμός ως προεπιλογή"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Ακύρωση"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"Το <xliff:g id="NEW_APP">%s</xliff:g> θα έχει τη δυνατότητα πραγματοποίησης κλήσεων, καθώς και ελέγχου κάθε πτυχής τους. Μόνον κάποια αξιόπιστη εφαρμογή θα πρέπει να ορίζεται ως προεπιλεγμένη."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Αποκλεισμένοι αριθμοί"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Δεν θα λαμβάνετε κλήσεις ή μηνύματα κειμένου από αποκλεισμένους αριθμούς."</string>
<string name="block_number" msgid="1101252256321306179">"Προσθήκη αριθμού"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 661ceee..0d01605 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Missing voicemail number"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"No voicemail number is stored on the SIM card."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Add number"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Change default Dialer app?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Use <xliff:g id="NEW_APP">%1$s</xliff:g> instead of <xliff:g id="CURRENT_APP">%2$s</xliff:g> as your default dialler app?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Use <xliff:g id="NEW_APP">%s</xliff:g> as your default dialler app?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Make <xliff:g id="NEW_APP">%s</xliff:g> your default Phone app?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Set Default"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancel"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to place and control all aspects of calls. Only apps that you trust should be set as the default Phone app."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blocked numbers"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"You won\'t receive calls or texts from blocked numbers."</string>
<string name="block_number" msgid="1101252256321306179">"Add a number"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 661ceee..0d01605 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Missing voicemail number"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"No voicemail number is stored on the SIM card."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Add number"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Change default Dialer app?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Use <xliff:g id="NEW_APP">%1$s</xliff:g> instead of <xliff:g id="CURRENT_APP">%2$s</xliff:g> as your default dialler app?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Use <xliff:g id="NEW_APP">%s</xliff:g> as your default dialler app?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Make <xliff:g id="NEW_APP">%s</xliff:g> your default Phone app?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Set Default"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancel"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to place and control all aspects of calls. Only apps that you trust should be set as the default Phone app."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blocked numbers"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"You won\'t receive calls or texts from blocked numbers."</string>
<string name="block_number" msgid="1101252256321306179">"Add a number"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 661ceee..0d01605 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Missing voicemail number"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"No voicemail number is stored on the SIM card."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Add number"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Change default Dialer app?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Use <xliff:g id="NEW_APP">%1$s</xliff:g> instead of <xliff:g id="CURRENT_APP">%2$s</xliff:g> as your default dialler app?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Use <xliff:g id="NEW_APP">%s</xliff:g> as your default dialler app?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Make <xliff:g id="NEW_APP">%s</xliff:g> your default Phone app?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Set Default"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancel"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to place and control all aspects of calls. Only apps that you trust should be set as the default Phone app."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blocked numbers"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"You won\'t receive calls or texts from blocked numbers."</string>
<string name="block_number" msgid="1101252256321306179">"Add a number"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index a791c8a..6768c48 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Falta el número de correo de voz"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"No hay un número de correo de voz almacenado en la tarjeta SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Agregar número"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"¿Quieres cambiar la aplicación Marcador predeterminada?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"¿Quieres usar <xliff:g id="NEW_APP">%1$s</xliff:g> en lugar de <xliff:g id="CURRENT_APP">%2$s</xliff:g> como la aplicación de marcado predeterminada?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"¿Quieres usar <xliff:g id="NEW_APP">%s</xliff:g> como la aplicación de marcado predeterminada?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"¿Establecer <xliff:g id="NEW_APP">%s</xliff:g> como la app de teléfono predeterminada?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Establecer como predeterminada"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancelar"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> podrá realizar llamadas y controlar todos los aspectos relacionados con ellas. Establece solamente una app de confianza como la app de teléfono predeterminada."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Números bloqueados"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"No recibirás llamadas ni mensajes de texto de los números bloqueados."</string>
<string name="block_number" msgid="1101252256321306179">"Agregar un número"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index b793ca7..f9be28b 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Falta el número del buzón de voz."</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"No se ha almacenado ningún número de buzón de voz en la tarjeta SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Añadir número"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"¿Cambiar el marcador predeterminado?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"¿Quieres utilizar <xliff:g id="NEW_APP">%1$s</xliff:g> en lugar de <xliff:g id="CURRENT_APP">%2$s</xliff:g> como marcador predeterminado?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"¿Quieres utilizar <xliff:g id="NEW_APP">%s</xliff:g> como marcador predeterminado?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"¿Quieres que <xliff:g id="NEW_APP">%s</xliff:g> sea tu aplicación de teléfono predeterminada?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Configurar como predeterminada"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancelar"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> podrá llamar y controlar todo lo relacionado con las llamadas. Te aconsejamos que solo configures una aplicación como predeterminada si es de confianza."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Números bloqueados"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"No recibirás llamadas ni SMS de los números bloqueados."</string>
<string name="block_number" msgid="1101252256321306179">"Añadir un número"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index ff37ee4..506ba31 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Puudub kõnepostinumber"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM-kaardile pole salvestatud ühtegi kõnepostinumbrit."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Lisa number"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Kas muuta helistamise vaikerakendust?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Kas kasutada rakendust <xliff:g id="NEW_APP">%1$s</xliff:g> rakenduse <xliff:g id="CURRENT_APP">%2$s</xliff:g> asemel helistamise vaikerakendusena?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Kas kasutada rakendust <xliff:g id="NEW_APP">%s</xliff:g> helistamise vaikerakendusena?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Kas muuta rakendus <xliff:g id="NEW_APP">%s</xliff:g> telefoni vaikerakenduseks?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Määra vaikeseadeks"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Tühista"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"Rakendus <xliff:g id="NEW_APP">%s</xliff:g> saab helistada ja juhtida kõiki kõnede aspekte. Määrake telefoni vaikerakenduseks vaid usaldusväärsed rakendused."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokeeritud numbrid"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Te ei saa blokeeritud numbritelt kõnesid ega tekstsõnumeid."</string>
<string name="block_number" msgid="1101252256321306179">"Lisa number"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 3a3bdd9..7f2ef59 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Erantzungailuaren zenbakia falta da"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Ez da erantzungailuaren zenbakirik gorde SIM txartelean."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Gehitu zenbakia"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Telefono-aplikazio lehenetsia aldatu nahi duzu?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> aplikazioaren ordez <xliff:g id="NEW_APP">%1$s</xliff:g> erabili nahi duzu telefono-aplikazio lehenetsi gisa?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> telefono-aplikazio lehenetsi gisa erabili nahi duzu?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> telefonoaren aplikazio lehenetsia izatea nahi duzu?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Ezarri lehenetsi gisa"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Utzi"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"Deien aspektu guztiak erabili eta kontrolatu ahal izango ditu <xliff:g id="NEW_APP">%s</xliff:g> aplikazioak. Fidagarriak diren aplikazioak bakarrik erabili beharko lirateke telefonoaren aplikazio lehenetsi gisa."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokeatutako zenbakiak"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Ez duzu jasoko deirik edo testu-mezurik blokeatutako zenbakietatik."</string>
<string name="block_number" msgid="1101252256321306179">"Gehitu zenbakia"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index aec0966..78acda1 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"عدم وجود شماره پست صوتی"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"شماره پست صوتی در سیم کارت ذخیره نشده است."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"افزودن شماره"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"برنامه شمارهگیر پیشفرض تغییر کند؟"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"از <xliff:g id="NEW_APP">%1$s</xliff:g> به جای <xliff:g id="CURRENT_APP">%2$s</xliff:g> به عنوان برنامه شمارهگیر پیشفرض استفاده شود؟"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"از <xliff:g id="NEW_APP">%s</xliff:g> به عنوان برنامه شمارهگیر پیشفرض استفاده شود؟"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> را به برنامه تلفن پیشفرضتان تبدیل میکنید؟"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"تنظیم پیشفرض"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"لغو"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> میتواند تماسها را برقرار کند و همه مسائل مربوط به آنها را کنترل کند. فقط برنامههایی را که به آنها اطمینان دارید بهعنوان برنامه پیشفرض تلفن تنظیم کنید."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"شمارههای مسدودشده"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"از شمارههای مسدودشده نمیتوانید تماس یا پیامک دریافت کنید."</string>
<string name="block_number" msgid="1101252256321306179">"افزودن شماره"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 5481e47..b810ac5 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Puhelinvastaajan numero puuttuu"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM-kortille ei ole tallennettu puhelinvastaajan numeroa."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Lisää numero"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Vaihdetaanko oletuspuhelusovellus?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Asetetaanko oletuspuhelusovellukseksi <xliff:g id="NEW_APP">%1$s</xliff:g> sovelluksen <xliff:g id="CURRENT_APP">%2$s</xliff:g> sijaan?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Asetetaanko <xliff:g id="NEW_APP">%s</xliff:g> oletuspuhelusovellukseksi?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Valitaanko <xliff:g id="NEW_APP">%s</xliff:g> oletuspuhelinsovellukseksi?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Aseta oletukseksi"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Peruuta"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> voi hallita kaikkia puhelutoimintoja. Aseta oletuspuhelinsovellukseksi vain luotettava sovellus."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Estetyt numerot"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Et voi vastaanottaa puheluita tai tekstiviestejä estetyistä numeroista."</string>
<string name="block_number" msgid="1101252256321306179">"Lisää numero"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index f1f6f14..d41cb2d 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Numéro de messagerie vocale manquant"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Aucun numéro de messagerie vocale n\'est enregistré sur la carte SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Ajouter un numéro"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Changer l\'application de composition par défaut?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Utiliser <xliff:g id="NEW_APP">%1$s</xliff:g> au lieu de <xliff:g id="CURRENT_APP">%2$s</xliff:g> comme application de composition par défaut?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Utiliser <xliff:g id="NEW_APP">%s</xliff:g> comme application de composition par défaut?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Définir <xliff:g id="NEW_APP">%s</xliff:g> comme votre application de téléphonie par défaut?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Définir comme application de téléphonie par défaut"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Annuler"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> sera en mesure de passer des appels et de contrôler tous les aspects des appels. Seules les applications auxquelles vous avez confiance doivent être définies comme l\'application de téléphonie par défaut."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Numéros bloqués"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Vous ne recevrez pas d\'appels ni de messages texte provenant des numéros bloqués."</string>
<string name="block_number" msgid="1101252256321306179">"Ajouter un numéro"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f641545..57df3d0 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Numéro de messagerie vocale manquant"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Aucun numéro de messagerie vocale n\'est enregistré sur la carte SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Ajouter un numéro"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Modifier l\'application de clavier par défaut ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Utiliser <xliff:g id="NEW_APP">%1$s</xliff:g> et non plus <xliff:g id="CURRENT_APP">%2$s</xliff:g> comme application de clavier par défaut ?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Utiliser <xliff:g id="NEW_APP">%s</xliff:g> comme application de clavier par défaut ?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Définir <xliff:g id="NEW_APP">%s</xliff:g> comme application de téléphone par défaut ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Définir l\'application par défaut"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Annuler"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> sera en mesure de passer des appels et d\'en contrôler tous les détails. Ne définissez qu\'une application de confiance comme application de téléphone par défaut."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Numéros bloqués"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Vous ne recevrez plus les appels ni les SMS émis depuis les numéros bloqués."</string>
<string name="block_number" msgid="1101252256321306179">"Ajouter un numéro"</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index ae89a83..c6786c2 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Falta o número de correo de voz"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Non hai ningún número de correo de voz almacenado na tarxeta SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Engadir número"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Queres cambiar a aplicación predeterminada do marcador?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Queres usar <xliff:g id="NEW_APP">%1$s</xliff:g> en lugar de <xliff:g id="CURRENT_APP">%2$s</xliff:g> como a túa aplicación de marcador predeterminada?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Queres usar <xliff:g id="NEW_APP">%s</xliff:g> como a túa aplicación de marcador predeterminada?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Establecer <xliff:g id="NEW_APP">%s</xliff:g> como aplicación de teléfono predeterminada?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Establecer como predeterminada"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancelar"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> poderá facer chamadas e controlar todo o referente a estas. Só deberías establecer como aplicación de teléfono predeterminada aplicacións nas que confíes."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Números bloqueados"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Non recibirás chamadas nin mensaxes de texto desde números bloqueados."</string>
<string name="block_number" msgid="1101252256321306179">"Engadir un número"</string>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index 3442516..afaebe4 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"વૉઇસમેઇલ નંબર ખૂટે છે"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM કાર્ડ પર કોઈ વૉઇસમેઇલ નંબર સંગ્રહિત નથી."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"નંબર ઉમેરો"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ડિફોલ્ટ ડાયલર ઍપ્લિકેશન બદલીએ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"તમારી ડિફોલ્ટ ડાયલર ઍપ્લિકેશન તરીકે <xliff:g id="CURRENT_APP">%2$s</xliff:g> ને બદલે <xliff:g id="NEW_APP">%1$s</xliff:g> નો ઉપયોગ કરીએ?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"તમારી ડિફોલ્ટ ડાયલર ઍપ્લિકેશન તરીકે <xliff:g id="NEW_APP">%s</xliff:g> નો ઉપયોગ કરીએ?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"શું <xliff:g id="NEW_APP">%s</xliff:g> ને તમારી ડિફૉલ્ટ ફોન ઍપ્લિકેશન બનાવીએ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ડિફૉલ્ટ સેટ કરો"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"રદ કરો"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g>, કૉલ્સ કરવામાં અને કૉલ્સના તમામ પાસાઓને નિયંત્રિત કરવામાં સમર્થ હશે. તમે વિશ્વાસ કરો છો તે જ ઍપ્લિકેશનોને ડિફૉલ્ટ ફોન ઍપ્લિકેશન તરીકે સેટ કરો."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"અવરોધિત નંબરો"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"તમે અવરોધિત નંબરોથી કૉલ્સ અથવા ટેક્સ્ટ પ્રાપ્ત કરશો નહીં."</string>
<string name="block_number" msgid="1101252256321306179">"એક નંબર ઉમેરો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index c011b4a..874712d 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"गुम वॉयस मेल नंबर"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"सिम कार्ड पर कोई वॉयस मेल नंबर संग्रहीत नहीं है."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"नंबर जोड़ें"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"डिफ़ॉल्ट डायलर ऐप को बदलें?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"अपने डिफ़ॉल्ट डायलर ऐप के रूप में <xliff:g id="CURRENT_APP">%2$s</xliff:g> के बजाय <xliff:g id="NEW_APP">%1$s</xliff:g> का उपयोग करें?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"अपने डिफ़ॉल्ट डायलर ऐप के रूप में <xliff:g id="NEW_APP">%s</xliff:g> का उपयोग करें?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> को अपना डिफ़ॉल्ट ऐप्लिकेशन बनाएं?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"डिफ़ॉल्ट सेट करें"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"अभी नहीं"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> कॉल करने और कॉल से संबंधित सभी पहलुओं को नियंत्रित कर पाएगा. केवल उन्हीं ऐप्लिकेशन को डिफ़ॉल्ट फ़ोन ऐप्लिकेशन के रूप में सेट करना चाहिए जिन पर आप विश्वास करते हैं."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"अवरोधित नंबर"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"आपको अवरुद्ध किए गए नंबर से कॉल या लेख संदेश प्राप्त नहीं होंगे."</string>
<string name="block_number" msgid="1101252256321306179">"एक नंबर जोड़ें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 6e7fb3a..86e06ed 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Nedostaje broj govorne pošte"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Na SIM kartici nije spremljen broj govorne pošte."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj broj"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Želite li promijeniti zadanu aplikaciju brojčanika?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Želite li upotrebljavati <xliff:g id="NEW_APP">%1$s</xliff:g> umjesto aplikacije <xliff:g id="CURRENT_APP">%2$s</xliff:g> kao zadanu aplikaciju brojčanika?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Želite li upotrebljavati <xliff:g id="NEW_APP">%s</xliff:g> kao zadanu aplikaciju brojčanika?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Želite li postaviti <xliff:g id="NEW_APP">%s</xliff:g> kao zadanu aplikaciju telefona?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Postavi zadano"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Odustani"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> će moći uspostaviti poziv i upravljati svim njegovim aspektima. Kao zadanu aplikaciju telefona postavite samo aplikaciju koju smatrate pouzdanom."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokirani brojevi"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Nećete primati ni pozive ni poruke s blokiranih brojeva."</string>
<string name="block_number" msgid="1101252256321306179">"Dodaj broj"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 72476bc..6266e54 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Hiányzik a hangposta száma"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Nincs hangpostaszám a SIM kártyán."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Szám hozzáadása"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Módosítja az alapértelmezett tárcsázó alkalmazást?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Legyen a(z) <xliff:g id="NEW_APP">%1$s</xliff:g> az alapértelmezett tárcsázó alkalmazás a(z) <xliff:g id="CURRENT_APP">%2$s</xliff:g> helyett?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Legyen a(z) <xliff:g id="NEW_APP">%s</xliff:g> az alapértelmezett tárcsázó alkalmazás?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Beállítja a(z) <xliff:g id="NEW_APP">%s</xliff:g> alkalmazást alapértelmezettként?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Beállítás alapértelmezettként"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Mégse"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> jogosult lesz hívások indítására és a hívásokkal kapcsolatos minden beállítás vezérlésére. Csak megbízható alkalmazást állítson be alapértelmezett telefonalkalmazásként."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Letiltott számok"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"A jövőben nem kap hívásokat vagy SMS-eket a letiltott számokról."</string>
<string name="block_number" msgid="1101252256321306179">"Szám hozzáadása"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 1061754..7c6d12b 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Բացակայում է ձայնային փոստի համարը"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM քարտում ձայնային փոստի ոչ մի համար գրանցված չէ:"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Ավելացնել համար"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Փոխե՞լ կանխադրված Համարհավաքի հավելվածը:"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Օգտագործե՞լ <xliff:g id="NEW_APP">%1$s</xliff:g> հավելվածը <xliff:g id="CURRENT_APP">%2$s</xliff:g>-ի փոխարեն որպես համարհավաքի կանխադրված հավելված:"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Դարձնե՞լ <xliff:g id="NEW_APP">%s</xliff:g> հավելվածը համարհավաքի կանխադրված հավելված:"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Նշե՞լ <xliff:g id="NEW_APP">%s</xliff:g>-ը որպես Հեռախոսի կանխադրված հավելված:"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Սահմանել որպես կանխադրված"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Չեղարկել"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> հավելվածը կկատարի զանգերի հետ կապված բոլոր գործառույթները: Որպես Հեռախոսի կանխադրված հավելված նշեք միայն վստահելի հավելվածներ:"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Արգելափակված համարներ"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Արգելափակված համարներից զանգեր կամ SMS–ներ չեք ստանա:"</string>
<string name="block_number" msgid="1101252256321306179">"Ավելացնել համար"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index edb0731..780c94b 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Nomor kotak pesan hilang"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Tidak ada nomor kotak pesan tersimpan pada kartu SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Tambahkan nomor"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Ubah aplikasi Pemanggil default?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Gunakan <xliff:g id="NEW_APP">%1$s</xliff:g>, bukan <xliff:g id="CURRENT_APP">%2$s</xliff:g> sebagai aplikasi pemanggil default?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Gunakan <xliff:g id="NEW_APP">%s</xliff:g> sebagai aplikasi pemanggil default?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Jadikan <xliff:g id="NEW_APP">%s</xliff:g> sebagai aplikasi Telepon default?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Setel Default"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Batal"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> dapat melakukan panggilan dan mengontrol semua aspek panggilan. Hanya aplikasi yang Anda percaya boleh disetel sebagai aplikasi Telepon default."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Nomor yang diblokir"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Anda tidak akan menerima telepon atau SMS dari nomor yang diblokir."</string>
<string name="block_number" msgid="1101252256321306179">"Tambah nomor"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 928a74e..bc43950 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Talhólfsnúmer vantar"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Ekkert talhólfsnúmer er vistað á SIM-kortinu."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Bæta númeri við"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Viltu skipta um sjálfgefið hringiforrit?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Nota <xliff:g id="NEW_APP">%1$s</xliff:g> í stað <xliff:g id="CURRENT_APP">%2$s</xliff:g> sem sjálfgefið hringiforrit?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Nota <xliff:g id="NEW_APP">%s</xliff:g> sem sjálfgefið hringiforrit?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Gera <xliff:g id="NEW_APP">%s</xliff:g> að sjálfgefnu símaforriti?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Velja sem sjálfgefið"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Hætta við"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> getur framkvæmt og stjórnað öllu sem tengist símtölum. Einungis forrit sem þú treystir ættu að vera stillt sem sjálfgefið símaforrit."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Númer á bannlista"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Þú færð ekki símtöl eða skilaboð frá númerum á bannlista."</string>
<string name="block_number" msgid="1101252256321306179">"Bæta við númeri"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index bddb598..716f765 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Numero segreteria mancante"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Nessun numero di segreteria presente nella SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Aggiungi numero"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Modificare l\'app tastiera predefinita?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Utilizzare <xliff:g id="NEW_APP">%1$s</xliff:g> invece di <xliff:g id="CURRENT_APP">%2$s</xliff:g> come app tastiera predefinita?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Utilizzare <xliff:g id="NEW_APP">%s</xliff:g> come app tastiera predefinita?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Rendere <xliff:g id="NEW_APP">%s</xliff:g> l\'app predefinita del tuo telefono?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Imposta come predefinita"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Annulla"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> potrà effettuare e controllare tutti gli aspetti delle chiamate. L\'app predefinita del telefono dovrebbe essere un\'app di cui ti fidi."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Numeri bloccati"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Non riceverai chiamate o SMS da numeri bloccati."</string>
<string name="block_number" msgid="1101252256321306179">"Aggiungi un numero"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 24fa715..a730121 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"חסר מספר של דואר קולי"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"בכרטיס ה-SIM לא מאוחסן מספר של דואר קולי."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"הוסף מספר"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"האם לשנות את אפליקציית החייגן שבברירת מחדל?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"האם להשתמש ב-<xliff:g id="NEW_APP">%1$s</xliff:g> במקום ב-<xliff:g id="CURRENT_APP">%2$s</xliff:g> כאפליקציית החייגן שבברירת מחדל?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"האם להשתמש ב-<xliff:g id="NEW_APP">%s</xliff:g> כאפליקציית החייגן שבברירת מחדל?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"האם להפוך את <xliff:g id="NEW_APP">%s</xliff:g> לברירת המחדל לאפליקציית \'טלפון\'?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"הגדר כברירת מחדל"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ביטול"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> תוכל להתקשר ולשלוט בכל ההיבטים של השיחות. מומלץ לבחור רק אפליקציות שאתה סומך עליהן כברירת המחדל לאפליקציית \'טלפון\'."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"מספרים חסומים"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"לא תקבל שיחות או הודעות טקסט מהמספרים החסומים."</string>
<string name="block_number" msgid="1101252256321306179">"הוסף מספר"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 1977b02..256d926 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ボイスメール番号がありません"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIMカードにボイスメールの番号がありません。"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"番号を追加"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"既定の電話アプリを変更しますか?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g>を<xliff:g id="CURRENT_APP">%2$s</xliff:g>の代わりに既定の電話アプリとして使用しますか?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g>を既定の電話アプリとして使用しますか?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> をデフォルトの電話アプリにしますか?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"デフォルトに設定"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"キャンセル"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> はすべての通話の発信や制御を行えるようになります。デフォルトの電話アプリに設定するのは信頼できるアプリだけにしてください。"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"ブロックした番号"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ブロックした電話番号からの通話やテキスト メッセージを受け取ることはありません。"</string>
<string name="block_number" msgid="1101252256321306179">"番号を追加"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 520913b..1e48ae1 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ხმოვანი ფოსტის ნომერი არ არის"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM ბარათზე ხმოვანი ფოსტის ნომერი შენახული არ არის."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"ნომრის დამატება"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"გსურთ ამკრეფის ნაგულისხმევი აპის შეცვლა?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"გსურთ ამკრეფის ნაგულისხმევ აპად <xliff:g id="CURRENT_APP">%2$s</xliff:g>-ის ნაცვლად <xliff:g id="NEW_APP">%1$s</xliff:g>-ის გამოყენება?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"გსურთ, გამოიყენოთ <xliff:g id="NEW_APP">%s</xliff:g>, როგორც ამკრეფის ნაგულისხმევი აპი?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"გახდეს <xliff:g id="NEW_APP">%s</xliff:g> თქვენი ნაგულისხმევი ტელეფონის აპი?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ნაგულისხმევად დაყენება"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"გაუქმება"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> შეძლებს ზარების განხორციელებას და მათი ყველა ასპექტის მართვას. ნაგულისხმევ ტელეფონის აპად უნდა დააყენოთ ის აპები, რომლებსაც ენდობით."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"დაბლოკილი ნომრები"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"დაბლოკილი ნომრებიდან ზარებსა და ტექსტურ შეტყობინებებს ვერ მიიღებთ."</string>
<string name="block_number" msgid="1101252256321306179">"ნომრის დამატება"</string>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index 524203f..5a49e4d 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Дауыс хабарының нөмірі жоқ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM картасында ешқандай дауыс хабарының нөмірі сақталмаған."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Нөмір қосу"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Әдепкі нөмір тергіш қолданбаны өзгерткіңіз келе ме?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> орнына <xliff:g id="NEW_APP">%1$s</xliff:g> қолданбасын әдепкі тергіш қолданба ретінде пайдалану қажет пе?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> қолданбасын әдепкі нөмір тергіш қолданба ретінде пайдалану қажет пе?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> қолданбасын әдепкі Телефон қолданбасы ретінде сақтайсыз ба?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Әдепкі ретінде орнату"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Тоқтату"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> қоңыраулардың барлық аспектілерін бақылайтын болады. Тек қана өзіңіз сенетін қолданбаларды ғана әдепкі ретінде орнатқан дұрыс."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Бөгелген нөмірлер"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Тыйым салынған нөмірлерден қоңыраулар немесе мәтіндік хабарлар алмайсыз."</string>
<string name="block_number" msgid="1101252256321306179">"Нөмір қосу"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 93dac37..f3fa21b 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"បាត់ចំនួនសារជាសំឡេង"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"គ្មានចំនួនសារជាសំឡេងត្រូវបានរក្សាទុកនៅលើស៊ីមកាតទេ។"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"បន្ថែមលេខ"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ប្តូរកម្មវិធីហៅទូរស័ព្ទលំនាំដើម?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"ប្រើ <xliff:g id="NEW_APP">%1$s</xliff:g> ជំនួសឲ្យ <xliff:g id="CURRENT_APP">%2$s</xliff:g> ជាកម្មវិធីហៅទូរស័ព្ទលំនាំដើមរបស់អ្នក?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"ប្រើ <xliff:g id="NEW_APP">%s</xliff:g> ជាកម្មវិធីហៅទូរស័ព្ទលំនាំដើមរបស់អ្នក?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"ធ្វើ <xliff:g id="NEW_APP">%s</xliff:g> ជាកម្មវិធីទូរសព្ទលំនាំដើមរបស់អ្នកដែរ ឬទេ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"កំណត់លំនាំដើម"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"បោះបង់"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> នឹងអាចដាក់ចុះ និងត្រួតពិនិត្យទិដ្ឋភាពការហៅទាំងអស់។ មានតែកម្មវិធីដែលអ្នកទុកចិត្តប៉ុណ្ណោះអាចត្រូវបានកំណត់ជាកម្មវិធីទូរសព្ទលំនាំដើម។"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"លេខដែលបានរារាំង"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"អ្នកនឹងមិនទទួលបានការហៅទូរស័ព្ទ ឬសារពីលេខដែលបានរារាំងឡើយ។"</string>
<string name="block_number" msgid="1101252256321306179">"បញ្ចូលលេខ"</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 0117849..86834d9 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="telecommAppLabel" product="default" msgid="382363169988504520">"ಕರೆ ನಿರ್ವಹಣೆ"</string>
<string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"ಫೋನ್"</string>
- <string name="unknown" msgid="6878797917991465859">"ಅಜ್ಞಾತ"</string>
+ <string name="unknown" msgid="6878797917991465859">"ಅಪರಿಚಿತ"</string>
<string name="notification_missedCallTitle" msgid="7554385905572364535">"ಮಿಸ್ಡ್ ಕಾಲ್"</string>
<string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"ಮಿಸ್ಡ್ ಕೆಲಸದ ಕರೆ"</string>
<string name="notification_missedCallsTitle" msgid="1361677948941502522">"ತಪ್ಪಿದ ಕರೆಗಳು"</string>
@@ -33,7 +33,7 @@
<string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"ನಾನು ನಂತರ ನಿಮಗೆ ಕರೆ ಮಾಡುತ್ತೇನೆ."</string>
<string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"ಈಗ ಮಾತನಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಂತರ ಮಾಡುವಿರಾ?"</string>
<string name="respond_via_sms_setting_title" msgid="3754000371039709383">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆಗಳು"</string>
- <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ ಸಂಪಾದಿಸಿ"</string>
+ <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
<string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ"</string>
<string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> ಗೆ ಸಂದೇಶ ಕಳುಹಿಸಲಾಗಿದೆ."</string>
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ಧ್ವನಿಮೇಲ್ ಸಂಖ್ಯೆಯು ಕಾಣೆಯಾಗಿದೆ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"ಸಿಮ್ ಕಾರ್ಡ್ನಲ್ಲಿ ಯಾವುದೇ ಧ್ವನಿಮೇಲ್ ಸಂಖ್ಯೆಯನ್ನು ಸಂಗ್ರಹಿಸಿಲ್ಲ."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ಡೀಫಾಲ್ಟ್ ಡಯಲರ್ ಅಪ್ಲಿಕೇಶನ್ ಬದಲಾಯಿಸುವುದೇ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> ಬದಲಿಗೆ <xliff:g id="NEW_APP">%1$s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಡಯಲರ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿ ಬಳಸುವುದೇ?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಡಯಲರ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿ ಬಳಸುವುದೇ?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಡಿಫಾಲ್ಟ್ ಫೋನ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿ ಮಾಡುವುದೇ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ಡಿಫಾಲ್ಟ್ ಹೊಂದಿಸಿ"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ಗೆ ನಿಮ್ಮ ಕರೆಗಳ ಎಲ್ಲಾ ಅಂಶಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ಮತ್ತು ಕರೆಗಳನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ. ನೀವು ವಿಶ್ವಾಸವಿರಿಸಿರುವಂತಹ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಮಾತ್ರ ನಿಮ್ಮ ಡಿಫಾಲ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿ ಹೊಂದಿಸಬೇಕು."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"ನಿರ್ಬಂಧಿಸಲಾದ ಸಂಖ್ಯೆಗಳು"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ನಿರ್ಬಂಧಿಸಲಾದ ಸಂಖ್ಯೆಗಳಿಂದ ಕರೆಗಳು ಅಥವಾ ಪಠ್ಯ ಸಂದೇಶಗಳನ್ನು ನೀವು ಸ್ವೀಕರಿಸುವುದಿಲ್ಲ."</string>
<string name="block_number" msgid="1101252256321306179">"ಸಂಖ್ಯೆ ಸೇರಿಸಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 8b347b5..9cf688a 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"음성사서함 번호 없음"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM 카드에 저장된 음성사서함 번호가 없습니다."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"번호 추가"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"기본 다이얼러 앱을 변경하시겠습니까?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> 대신 <xliff:g id="NEW_APP">%1$s</xliff:g>을(를) 기본 다이얼러 앱으로 사용하시겠습니까?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g>을(를) 기본 다이얼러 앱으로 사용하시겠습니까?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g>을(를) 기본 전화 앱으로 설정하나요?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"기본으로 설정"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"취소"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g>은(는) 모든 전화를 걸고 제어할 수 있습니다. 신뢰할 수 있는 앱만 기본 전화 앱으로 설정하세요."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"차단된 번호"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"차단한 번호에서 걸려오는 전화나 문자를 더 이상 받지 않습니다."</string>
<string name="block_number" msgid="1101252256321306179">"번호 추가"</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index f0ddb39..31d81df 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Үн почтасынын номери жок болуп жатат"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM-картада сакталган үн почтасынын номери жок."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Номер кошуу"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Демейки номер тергич колдонмо өзгөрүлсүнбү?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Демейки номер тергич колдонмо катары мурунку <xliff:g id="CURRENT_APP">%2$s</xliff:g> колдонмонун ордуна <xliff:g id="NEW_APP">%1$s</xliff:g> бул колдонмо колдонулсунбу?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Демейки номер тергич колдонмо катары <xliff:g id="NEW_APP">%s</xliff:g> колдонулсунбу?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> колдонмосун демейки телефон колдонмосу кыласызбы?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Демейки шартта колдонуу"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Жокко чыгаруу"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> колдонмосу аркылуу чалып, алардын параметрлерин жөндөй аласыз. Демейки чалуулар үчүн ишеничтүү колдонмолорду гана пайдалануу керек."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Бөгөттөлгөн номерлер"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Бөгөттөлгөн номерлерден эч ким чалып же билдирүү жөнөтө албайт."</string>
<string name="block_number" msgid="1101252256321306179">"Номер кошуу"</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index ac8ed8c..adc0d1a 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ບໍ່ມີເບີຂໍ້ຄວາມສຽງ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"ບໍ່ມີເບີຂໍ້ຄວາມສຽງຖືກບັນທຶກໃນ SIM card."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"ເພີ່ມໝາຍເລກ"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ປ່ຽນແປງແອັບແຜ່ນກົດມາດຕະຖານ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"ໃຊ້ <xliff:g id="NEW_APP">%1$s</xliff:g> ແທນ <xliff:g id="CURRENT_APP">%2$s</xliff:g> ເປັນແອັບແຜ່ນກົດມາດຕະຖານຂອງທ່ານ?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"ໃຊ້ <xliff:g id="NEW_APP">%s</xliff:g> ເປັນແອັບແຜ່ນກົດມາດຕະຖານຂອງທ່ານ?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"ຕັ້ງໃຫ້ <xliff:g id="NEW_APP">%s</xliff:g> ເປັນແອັບໂທລະສັບເລີ່ມຕົ້ນຂອງທ່ານບໍ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ຕັ້ງເປັນຄ່າເລີ່ມຕົ້ນ"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ຍົກເລີກ"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ຈະສາມາດໂທ ແລະ ຄວບຄຸມທຸກແງ່ມຸມຂອງການໂທຕ່າງໆໄດ້. ທ່ານຄວນຕັ້ງໃຫ້ແອັບໂທລະສັບທີ່ທ່ານໄວ້ໃຈໄດ້ເທົ່ານັ້ນເປັນແອັບເລີ່ມຕົ້ນ."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"ເບີໂທລະສັບທີ່ບລັອກໄວ້"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ທ່ານຈະບໍ່ໄດ້ຮັບສາຍ ຫຼື ຂໍ້ຄວາມຈາກເບີທີ່ບລັອກໄວ້."</string>
<string name="block_number" msgid="1101252256321306179">"ເພີ່ມເບີໂທລະສັບ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index c1146fd..00bc892 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Trūksta balso pašto numerio"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kortelėje nėra išsaugoto balso pašto numerio."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Pridėti numerį"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Pakeisti numatytąją numerio rinkiklio programą?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Naudoti „<xliff:g id="NEW_APP">%1$s</xliff:g>“ vietoje „<xliff:g id="CURRENT_APP">%2$s</xliff:g>“ kaip numatytąją numerio rinkiklio programą?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Naudoti „<xliff:g id="NEW_APP">%s</xliff:g>“ kaip numatytąją numerio rinkiklio programą?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Nustatyti „<xliff:g id="NEW_APP">%s</xliff:g>“ kaip numatytąją telefono programą?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Nustatyti numatytuosius nustatymus"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Atšaukti"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"„<xliff:g id="NEW_APP">%s</xliff:g>“ galės atlikti ir valdyti įvairius skambučius. Tik patikimą programą turėtumėte nustatyti kaip numatytąją telefono programą."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Užblokuoti numeriai"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Negausite skambučių ar teksto pranešimų iš užblokuotų numerių."</string>
<string name="block_number" msgid="1101252256321306179">"Pridėti numerį"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 0bee0f2..2238f9d 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Trūkst balss pasta numura"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartē neviens balss pasta numurs nav saglabāts."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Pievienot numuru"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Vai mainīt numura sastādītāja noklusējuma lietotni?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Vai lietotnes <xliff:g id="CURRENT_APP">%2$s</xliff:g> vietā izmantot <xliff:g id="NEW_APP">%1$s</xliff:g> kā numura sastādītāja noklusējuma lietotni?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Vai izmantot <xliff:g id="NEW_APP">%s</xliff:g> kā numura sastādītāja noklusējuma lietotni?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Vai iestatīt <xliff:g id="NEW_APP">%s</xliff:g> kā tālruņa noklusējuma lietotni?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Iestatīt kā noklusējumu"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Atcelt"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"Lietotne <xliff:g id="NEW_APP">%s</xliff:g> varēs veikt zvanus un kontrolēt visas zvanu funkcijas. Tālruņa noklusējuma lietotnes iestatīšanai izmantojiet tikai uzticamas lietotnes."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Bloķētie numuri"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Jūs nesaņemsiet zvanus vai īsziņas no bloķētajiem numuriem."</string>
<string name="block_number" msgid="1101252256321306179">"Pievienot numuru"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index 33a7b73..bc47335 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Недостасува број на говорна пошта"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Нема мемориран број на говорна пошта на СИМ картичката."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Додај број"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Смени ја стандардната апликација Бирач?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Користи <xliff:g id="NEW_APP">%1$s</xliff:g> наместо <xliff:g id="CURRENT_APP">%2$s</xliff:g> како стандардна апликација за бирање?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Користи <xliff:g id="NEW_APP">%s</xliff:g> како стандардна апликација за бирање?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Да се направи <xliff:g id="NEW_APP">%s</xliff:g> ваша стандардна апликација Телефон?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Поставете стандардна"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Откажете"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ќе може да ги поставува и контролира сите аспекти на повикувањето. Само апликации на кои им веруваш треба да се поставуваат како стандардната апликација Телефон."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Блокирани броеви"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Нема да добивате повици или SMS од блокирани броеви."</string>
<string name="block_number" msgid="1101252256321306179">"Додај број"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index b2a87bd..d16e447 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"വോയ്സ്മെയിൽ നമ്പർ കാണുന്നില്ല"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"സിം കാർഡിൽ വോയ്സ്മെയിൽ നമ്പറൊന്നും സംഭരിച്ചിട്ടില്ല."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"നമ്പർ ചേർക്കുക"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"സ്ഥിര ഡയലർ ആപ്പ് മാറ്റണോ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> എന്നതിനുപകരം <xliff:g id="NEW_APP">%1$s</xliff:g> എന്നതിനെ നിങ്ങളുടെ സ്ഥിര ഡയലർ ആപ്പ് ആയി ഉപയോഗിക്കണോ?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> എന്നതിനെ നിങ്ങളുടെ സ്ഥിര ഡയലർ ആപ്പ് ആയി ഉപയോഗിക്കണോ?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> എന്നതിനെ നിങ്ങളുടെ ഡിഫോൾട്ട് ഫോൺ ആപ്പാക്കണോ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ഡിഫോൾട്ട് ഫോൺ ആപ്പ് സജ്ജമാക്കുക"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"റദ്ദാക്കുക"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ആപ്പിന് എല്ലാ തരത്തിലുമുള്ള കോളുകൾ ചെയ്യാനും നിയന്ത്രിക്കാനുമാവും. നിങ്ങൾക്ക് വിശ്വാസമുള്ള ആപ്സിനെ മാത്രമേ ഡിഫോൾട്ട് ഫോൺ ആപ്പായി സജ്ജമാക്കാവൂ."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"ബ്ലോക്കുചെയ്ത നമ്പറുകൾ"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ബ്ലോക്കുചെയ്ത നമ്പറുകളിൽ നിന്ന് നിങ്ങൾക്ക് കോളുകളോ സന്ദേശങ്ങളോ ലഭിക്കില്ല."</string>
<string name="block_number" msgid="1101252256321306179">"ഒരു നമ്പർ ചേർക്കുക"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index cfe39d0..8e0b39b 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Дуут шуудангийн дугаар байхгүй"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM карт дээр дуут шуудангийн дугаар хадгалагдаагүй байна."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Дугаар нэмэх"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Үндсэн залгагч апп-ыг өөрчлөх үү?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g>-ыг <xliff:g id="CURRENT_APP">%2$s</xliff:g>-ын оронд таны үндсэн залгагч апп болгон тохируулах уу?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g>-ыг таны үндсэн залгагч апп болгон тохируулах уу?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g>-г өөрийн өгөгдмөл Утасны апп болгох уу?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Өгөгдмөл болгох"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Цуцлах"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> бүх төрлийн дуудлага хийх, хянах боломжтой болно. Зөвхөн өөрийн итгэдэг апп-г өгөгдмөл Утасны апп-р тохируулах нь зүйтэй."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Блоклосон дугаар"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Та хориглосон дугаараас дуудлага, мессеж хүлээн авахгүй."</string>
<string name="block_number" msgid="1101252256321306179">"Дугаар нэмэх"</string>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 3dfcd34..a4f55fb 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"व्हॉइसमेल नंबर गहाळ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"सिम कार्डवर कोणताही व्हॉइसमेल नंबर संचयित केला नाही."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"नंबर जोडा"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"डीफॉल्ट डायलर अॅप बदलायचा?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"आपला डीफॉल्ट डायलर अॅप म्हणून <xliff:g id="CURRENT_APP">%2$s</xliff:g> ऐवजी <xliff:g id="NEW_APP">%1$s</xliff:g> वापरायचा?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"आपला डीफॉल्ट डायलर अॅप म्हणून <xliff:g id="NEW_APP">%s</xliff:g> वापरायचा?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ला आपला डीफॉल्ट अॅप बनवायचा?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"डीफॉल्ट म्हणून सेट करा"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"रद्द करा"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> कॉल करण्यात आणि त्याचे सर्व पैलू नियंत्रित करण्यात सक्षम असेल. ज्या अॅप्सवर आपला विश्वास आहे फक्त त्यांंनाच आपला डीफॉल्ट फोन अॅप म्हणून सेट करावे."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"अवरोधित केलेले नंबर"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"आपल्याला अवरोधित नंबरवरून कॉल किंवा मजकूर प्राप्त होणार नाहीत."</string>
<string name="block_number" msgid="1101252256321306179">"एक नंबर जोडा"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index c77f2bb..208dcb1 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Nombor mel suara tiada"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Tidak ada nombor mel suara disimpan pada kad SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Tambah nombor"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Tukar apl Pendail lalai?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Gunakan <xliff:g id="NEW_APP">%1$s</xliff:g> dan bukannya <xliff:g id="CURRENT_APP">%2$s</xliff:g> sebagai apl pendail lalai anda?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Gunakan <xliff:g id="NEW_APP">%s</xliff:g> sebagai apl pendail lalai anda?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Jadikan <xliff:g id="NEW_APP">%s</xliff:g> apl Telefon lalai anda?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Tetapkan Lalai"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Batal"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> akan dapat membuat dan mengawal semua aspek panggilan. Hanya apl yang anda percayai sahaja yang seharusnya ditetapkan sebagai apl Telefon lalai."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Nombor yang disekat"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Anda tidak akan menerima panggilan atau teks daripada nombor yang disekat."</string>
<string name="block_number" msgid="1101252256321306179">"Tambahkan nombor"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 1eccf5e..da191da 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"အသံစာပို့စနစ် နံပါတ် ပျောက်နေပါသည်"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"ဆင်းမ်ကဒ်ပေါ်တွင် အသံစာပို့စနစ် နံပါတ် သိမ်းဆည်ထားခြင်း မရှိပါ"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"နံပါတ်ထပ်ထည့်ရန်"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"စက်ရုံထုတ်ဖုန်းခေါ်အပ်ဖ်ကိုပြောင်းလိုပါသလား"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> အစား <xliff:g id="NEW_APP">%1$s</xliff:g> ကိုသင့်ရဲ့ စက်ရုံထုတ်ဖုန်းခေါ်အပ်ဖ်အဖြစ် သုံးလိုပါသလား"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> ကိုသင့်ရဲ့စက်ရုံထုတ်ဖုန်းခေါ်အပ်ဖ်အဖြစ် သုံးလိုပါသလား"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ကို သင့်ဖုန်း၏မူရင်းအက်ပ်အဖြစ် ထားမလား။"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"မူရင်း သတ်မှတ်ရန်"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"မလုပ်တော့"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> သည် ခေါ်ဆိုမှုများကို ဘက်စုံပြုလုပ်ထိန်းချုပ်သွားနိုင်မည်ဖြစ်သည်။ သင်ယုံကြည်သော အက်ပ်များကိုသာ မူရင်း Phone အက်ပ်အဖြစ် သတ်မှတ်သင့်ပါသည်။"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"ပိတ်ဆို့ထားသည့် နံပါတ်များ"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"သင်သည် ဘလော့ခ်လုပ်ထားသော နံပါတ်များမှ ဖုန်းခေါ်ခြင်း (သို့) စာသားပို့ခြင်းတို့ကို လက်ခံရရှိမည် မဟုတ်ပါ။"</string>
<string name="block_number" msgid="1101252256321306179">"နံပါတ်တစ်ခု ထည့်ပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 1af23ae..230e9c3 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Mangler nummer til talepostkasse"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Det er ikke lagret noe nummer for talepostkasse på SIM-kortet."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Legg til nummer"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Vil du endre standard telefonapp?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Vil du bruke <xliff:g id="NEW_APP">%1$s</xliff:g> i stedet for <xliff:g id="CURRENT_APP">%2$s</xliff:g> som standard telefonapp?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Vil du bruke <xliff:g id="NEW_APP">%s</xliff:g> som standard telefonapp?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Vil du bruke <xliff:g id="NEW_APP">%s</xliff:g> som standard telefonapp?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Angi som standard"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Avbryt"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> kan håndtere alt som har med telefonanrop å gjøre. Bruk bare apper du stoler på som standard telefonapp."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokkerte numre"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Du mottar ingen anrop eller tekstmeldinger fra blokkerte numre."</string>
<string name="block_number" msgid="1101252256321306179">"Legg til et nummer"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 3becfb9..7ed47f4 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"भ्वाइसमेल नम्बर हराइरहेको छ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM कार्डमा कुनै पनि भ्वाइसमेल नम्बर भण्डारण भएको छैन।"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"नम्बर थप्नुहोस्"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"पूर्वनिर्धारित डायलर अनुप्रयोग फेर्ने हो?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g>को सट्टामा <xliff:g id="NEW_APP">%1$s</xliff:g>लाई पूर्वनिर्धारित डायलर अनुप्रयोगको रूपमा प्रयोग गर्ने हो?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g>लाई तपाईँको पूर्वनिर्धारित डायलर अनुप्रयोगको रूपमा प्रयोग गर्ने हो?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"तपाईंको पूर्वनिर्धारित फोन अनुप्रयोग <xliff:g id="NEW_APP">%s</xliff:g> बनाउने हो?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"पूर्वनिर्धारित रूपमा सेट गर्नुहोस्"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"रद्द गर्नुहोस्"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> कलका सबै पक्षहरूलाई स्थापित गर्न र नियन्त्रण गर्न सक्षम हुने छ। तपाईंलाई विश्वास लाग्ने अनुप्रयोगहरूलाई मात्र फोनमा पूर्वनिर्धारित अनुप्रयोगका रूपमा सेट गर्नुपर्छ।"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"रोकिएका नम्बरहरू"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"तपाईँले रोक लगाइएका नम्बरहरूबाट फोन वा पाठ सन्देशहरू प्राप्त गर्नुहुने छैन।"</string>
<string name="block_number" msgid="1101252256321306179">"नम्बर थप्नुहोस्"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index b50b111..7f8821a 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Voicemailnummer ontbreekt"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Er is geen voicemailnummer op de SIM-kaart opgeslagen."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Nummer toevoegen"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Standaard kiezerapp wijzigen?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g> in plaats van <xliff:g id="CURRENT_APP">%2$s</xliff:g> gebruiken als standaard kiezerapp?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> gebruiken als standaard kiezerapp?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Wil je <xliff:g id="NEW_APP">%s</xliff:g> instellen als je standaard telefoon-app?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Standaard instellen"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Annuleren"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> kan oproepen plaatsen en alle aspecten hiervan beheren. Stel alleen apps in als je standaard telefoon-app als je ze vertrouwt."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Geblokkeerde nummers"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Je ontvangt geen oproepen of sms\'jes van geblokkeerde nummers."</string>
<string name="block_number" msgid="1101252256321306179">"Een nummer toevoegen"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 738f992..73800d9 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ਲੁਪਤ ਵੌਇਸਮੇਲ ਨੰਬਰ"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM ਕਾਰਡ ਤੇ ਕੋਈ ਵੌਇਸਮੇਲ ਨੰਬਰ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ।"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"ਨੰਬਰ ਜੋੜੋ"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ਕੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡਾਇਲਰ ਐਪ ਨੂੰ ਬਦਲਣਾ ਹੈ?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"ਕੀ <xliff:g id="CURRENT_APP">%2$s</xliff:g> ਦੀ ਬਜਾਏ <xliff:g id="NEW_APP">%1$s</xliff:g> ਨੂੰ ਆਪਣੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡਾਇਲਰ ਐਪ ਵਜੋਂ ਵਰਤਣਾ ਹੈ?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"ਕੀ <xliff:g id="NEW_APP">%s</xliff:g> ਨੂੰ ਆਪਣੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡਾਇਲਰ ਐਪ ਵਜੋਂ ਵਰਤਣਾ ਹੈ?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"ਕੀ <xliff:g id="NEW_APP">%s</xliff:g> ਨੂੰ ਆਪਣੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਫ਼ੋਨ ਐਪ ਬਣਾਉਣਾ ਹੈ?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈੱਟ ਕਰੋ"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ਰੱਦ ਕਰੋ"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ਕਾਲਾਂ ਕਰ ਸਕੇਗੀ ਅਤੇ ਕਾਲਾਂ ਦੇ ਸਾਰੇ ਪੱਖਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰ ਸਕੇਗੀ। ਸਿਰਫ਼ ਉਹਨਾਂ ਐਪਾਂ ਨੂੰ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਫ਼ੋਨ ਐਪ ਵਜੋਂ ਸੈੱਟ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ ਜਿੰਨ੍ਹਾਂ \'ਤੇ ਤੁਸੀਂ ਭਰੋਸਾ ਕਰਦੇ ਹੋ।"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"ਬਲੌਕ ਕੀਤੇ ਗਏ ਨੰਬਰ"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ਤੁਹਾਨੂੰ ਬਲੌਕ ਕੀਤੇ ਨੰਬਰਾਂ ਤੋਂ ਕਾਲਾਂ ਜਾਂ ਲਿਖਤ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋਣਗੇ।"</string>
<string name="block_number" msgid="1101252256321306179">"ਇੱਕ ਨੰਬਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index c6567ec..e460463 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Brakuje numeru poczty głosowej"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Na karcie SIM nie ma zapisanego numeru poczty głosowej."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj numer"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Zmienić domyślną aplikację telefonu?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Zmienić <xliff:g id="CURRENT_APP">%2$s</xliff:g> na <xliff:g id="NEW_APP">%1$s</xliff:g> jako domyślną aplikację telefonu?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Ustawić <xliff:g id="NEW_APP">%s</xliff:g> jako domyślną aplikację telefonu?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Ustawić <xliff:g id="NEW_APP">%s</xliff:g> jako domyślną aplikację telefoniczną?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Ustaw jako aplikację domyślną"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Anuluj"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> uzyska możliwość nawiązywania połączeń i kontrolowania wszystkich ich aspektów. Tylko zaufane aplikacje powinny być ustawiane jako domyślna aplikacja telefoniczna."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Zablokowane numery"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Nie będziesz otrzymywać połączeń ani SMS-ów z zablokowanych numerów."</string>
<string name="block_number" msgid="1101252256321306179">"Dodaj numer"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 8f45672..b2e576e 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Número do correio de voz em falta"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Não existe um número de correio de voz armazenado no cartão SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Adicionar número"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Alterar aplicação de Telefone predefinida?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Utilizar <xliff:g id="NEW_APP">%1$s</xliff:g> em vez de <xliff:g id="CURRENT_APP">%2$s</xliff:g> como a aplicação de telefone predefinida?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Utilizar <xliff:g id="NEW_APP">%s</xliff:g> como a aplicação de telefone predefinida?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Predefinir <xliff:g id="NEW_APP">%s</xliff:g> como a sua aplicação Telefone?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Predefinir"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancelar"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"A aplicação <xliff:g id="NEW_APP">%s</xliff:g> poderá efetuar chamadas e controlar todos os aspetos das mesmas. Apenas as aplicações em que confia devem ser escolhidas como a aplicação de telefone predefinida."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Números bloqueados"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Não irá receber chamadas ou mensagens de texto de números bloqueados."</string>
<string name="block_number" msgid="1101252256321306179">"Adicionar um número"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index e2dc815..6d4271c 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Número correio de voz ausente"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Não há um número correio de voz armazenado no cartão SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Adicionar número"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Alterar o app discador padrão?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Usar <xliff:g id="NEW_APP">%1$s</xliff:g> em vez de <xliff:g id="CURRENT_APP">%2$s</xliff:g> como seu app discador padrão?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Usar <xliff:g id="NEW_APP">%s</xliff:g> como seu app discador padrão?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Usar o <xliff:g id="NEW_APP">%s</xliff:g> como seu aplicativo de smartphone padrão?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Definir padrão"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancelar"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"O <xliff:g id="NEW_APP">%s</xliff:g> poderá ligar e controlar todos os aspectos das chamadas. Defina como aplicativo de smartphone padrão somente aqueles em que você confia."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Números bloqueados"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Você não receberá chamadas nem mensagens de texto dos números bloqueados."</string>
<string name="block_number" msgid="1101252256321306179">"Adicionar um número"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index ccad8e3..4c204fb 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Lipsește numărul mesageriei vocale"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Niciun număr de mesagerie vocală nu este stocat pe cardul SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Adăugați numărul"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Schimbați aplicația Telefon prestabilită?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Folosiți <xliff:g id="NEW_APP">%1$s</xliff:g> și nu <xliff:g id="CURRENT_APP">%2$s</xliff:g> ca aplicație de telefonie prestabilită?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Folosiți <xliff:g id="NEW_APP">%s</xliff:g> ca aplicație de telefonie prestabilită?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Setați <xliff:g id="NEW_APP">%s</xliff:g> ca aplicație prestabilită a telefonului?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Setați ca prestabilită"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Anulați"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> va putea iniția apeluri și va putea controla toate aspectele acestora. E recomandat să setați ca aplicație prestabilită a telefonului numai aplicații în care aveți încredere."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Numere blocate"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Nu veți primi apeluri sau mesaje text de la numerele blocate."</string>
<string name="block_number" msgid="1101252256321306179">"Adăugați un număr"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 1f6f5af..d6623cd 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -45,15 +45,16 @@
<string name="no_vm_number" msgid="4164780423805688336">"Не указан номер голосовой почты"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"На SIM-карте нет ни одного номера голосовой почты."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Добавить номер"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Новое приложение для звонков"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"\"<xliff:g id="NEW_APP">%1$s</xliff:g>\" станет приложением для звонков по умолчанию вместо \"<xliff:g id="CURRENT_APP">%2$s</xliff:g>\". Продолжить?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"\"<xliff:g id="NEW_APP">%s</xliff:g>\" станет приложением для звонков по умолчанию. Продолжить?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Сделать <xliff:g id="NEW_APP">%s</xliff:g> приложением по умолчанию для звонков?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Использовать по умолчанию"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Отмена"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> будет отвечать за выполнение всех вызовов и настройку их параметров. Только надежные приложения следует использовать для звонков по умолчанию."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Заблокированные номера"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Звонки и сообщения с заблокированных номеров поступать не будут."</string>
<string name="block_number" msgid="1101252256321306179">"Добавить номер"</string>
<string name="unblock_dialog_body" msgid="1614238499771862793">"Разблокировать номер <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
<string name="unblock_button" msgid="3078048901972674170">"Разблокировать"</string>
- <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Блокировать звонки и сообщения с"</string>
+ <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Блокировать звонки и сообщения от"</string>
<string name="add_blocked_number_hint" msgid="6847675097085433553">"Номер телефона"</string>
<string name="block_button" msgid="8822290682524373357">"Заблокировать"</string>
<string name="non_primary_user" msgid="5180129233352533459">"Просматривать и изменять список заблокированных номеров может только владелец устройства."</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 78badfa..6a445bb 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"හඬ තැපැල් අංකය නැත"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM කාඩ් පතෙහි හඬ තැපැල් අංකයක් ආචිත වී නැත."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"අංකයක් එක් කරන්න"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"සුපුරුදු දුරකථන යෙදුම වෙනස් කරන්න ද?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> වෙනුවට <xliff:g id="NEW_APP">%1$s</xliff:g> ඔබගේ සුපුරුදු දුරකථන යෙදුම ලෙස භාවිතා කරන්නද?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> ඔබගේ සුපුරුදු දුරකථන යෙදුම ලෙස භාවිතා කරන්නද?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ඔබේ පෙරනිමි දුරකථන යෙදුම කරන්නද?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"පෙරනිමිය සකසන්න"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"අවලංගු කරන්න"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ඇමතුම් ලබා ගැනීමට සහ එවායේ සියලු අංග පාලනය කිරීමට හැකි වනු ඇත. ඔබ විශ්වාස කරන යෙදුම් පමණක් පෙරනිමි දුරකථන යෙදුම ලෙස සැකසිය යුතුය."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"අවහිර කළ අංක"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"ඔබට අවහිර කළ අංකයවලින් ඇමතුම් හෝ පෙළ නොලැබෙනු ඇත."</string>
<string name="block_number" msgid="1101252256321306179">"අංකයක් එක් කරන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 5da7467..9dbb232 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Chýba číslo hlasovej schránky"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Na SIM karte nie je uložené žiadne číslo hlasovej schránky."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Pridať číslo"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Chcete zmeniť predvolenú aplikáciu vytáčania?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Chcete použiť aplikáciu <xliff:g id="NEW_APP">%1$s</xliff:g> namiesto aplikácie <xliff:g id="CURRENT_APP">%2$s</xliff:g> ako predvolenú aplikáciu vytáčania?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Chcete použiť aplikáciu <xliff:g id="NEW_APP">%s</xliff:g> ako predvolenú aplikáciu vytáčania?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Nastaviť <xliff:g id="NEW_APP">%s</xliff:g> ako predvolanú aplikáciu na telefonovanie?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Nastaviť ako predvolené"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Zrušiť"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> bude môcť uskutočňovať hovory a ovládať všetky aspekty hovorov. Ako predvolenú aplikáciu na telefonovanie by ste si mali nastaviť len aplikáciu, ktorej dôverujete."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokované čísla"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Z blokovaných čísel nebudete prijímať hovory ani textové správy."</string>
<string name="block_number" msgid="1101252256321306179">"Pridať číslo"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 00a811b..b328c69 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Manjkajoča številka glasovne pošte"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Na kartici SIM ni shranjena številka glasovne pošte."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj številko"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Želite spremeniti privzeto aplikacijo za klicanje?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Želite <xliff:g id="NEW_APP">%1$s</xliff:g> uporabljati kot privzeto aplikacijo za klicanje namesto <xliff:g id="CURRENT_APP">%2$s</xliff:g>?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Želite <xliff:g id="NEW_APP">%s</xliff:g> uporabljati kot privzeto aplikacijo za klicanje?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Želite, da je <xliff:g id="NEW_APP">%s</xliff:g> privzeta aplikacija za klicanje?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Nastavi za privzeto"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Prekliči"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"V aplikaciji <xliff:g id="NEW_APP">%s</xliff:g> bo mogoče opravljati klice in nadzirati vse vidike klicev. Kot privzeto aplikacijo za klicanje nastavite samo aplikacije, ki jim zaupate."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blokirane številke"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Z blokiranih številk ne boste prejemali klicev ali sporočil SMS."</string>
<string name="block_number" msgid="1101252256321306179">"Dodaj številko"</string>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index b13c2ab..00660d0 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Mungon numri i postës zanore"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Nuk ka numër të ruajtur në kartën SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Shto numër"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Të ndryshohet apl. parazgjedhur i formuesit të numrave?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Të përdoret <xliff:g id="NEW_APP">%1$s</xliff:g> në vend të <xliff:g id="CURRENT_APP">%2$s</xliff:g> si aplikacioni i parazgjedhur i formuesit të numrave?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Të përdoret <xliff:g id="NEW_APP">%s</xliff:g> si aplikacioni i parazgjedhur i formuesit të numrave?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Të bëhet <xliff:g id="NEW_APP">%s</xliff:g> aplikacioni yt i parazgjedhur në telefon?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Vendos të parazgjedhurën"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Anulo"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> do të mund të bëjë dhe kontrollojë të gjitha aspektet e telefonatave. Vetëm aplikacionet të cilave u beson duhet të caktohen si aplikacioni Telefon i parazgjedhur."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Numrat e bllokuar"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Nuk do të marrësh telefonata ose mesazhe me tekst nga numrat e bllokuar."</string>
<string name="block_number" msgid="1101252256321306179">"Shto një numër"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 1fd28f2..23c2441 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Недостаје број за говорну пошту"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Није ускладиштен ниједан број говорне поште на SIM картици."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Додај број"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Променити подразумевану апликацију Телефон?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Желите ли да користите апликацију <xliff:g id="NEW_APP">%1$s</xliff:g> уместо апликације <xliff:g id="CURRENT_APP">%2$s</xliff:g> као подразумевану апликацију за позивање телефонских бројева?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Желите ли да користите апликацију <xliff:g id="NEW_APP">%s</xliff:g> као подразумевану апликацију за позивање телефонских бројева?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Желите ли да <xliff:g id="NEW_APP">%s</xliff:g> постане подразумевана апликација Телефон?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Постави као подразумевано"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Откажи"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ће моћи да упућује позиве и контролише све њихове аспекте. Апликацију подесите као подразумевану за телефонирање само ако је сматрате поузданом."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Блокирани бројеви"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Нећете примати позиве ни SMS-ове са блокираних бројева."</string>
<string name="block_number" msgid="1101252256321306179">"Додај број"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index ac22da8..1ecd70d 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Nummer till röstbrevlåda saknas"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Det finns inget nummer till röstbrevlådan sparat på SIM-kortet."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Lägg till nummer"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Vill du byta standardapp för uppringning?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Vill du använda <xliff:g id="NEW_APP">%1$s</xliff:g> i stället för <xliff:g id="CURRENT_APP">%2$s</xliff:g> som standardapp för uppringning?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Vill du använda <xliff:g id="NEW_APP">%s</xliff:g> som standardapp för uppringning?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Gör <xliff:g id="NEW_APP">%s</xliff:g> till standardtelefonapp?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Ange standard"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Avbryt"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> kan ringa och styra allt omkring samtal. Endast appar du litar på bör ställas in som standardtelefonapp."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Blockerade nummer"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Du kommer inte ta emot samtal eller sms från blockerade nummer."</string>
<string name="block_number" msgid="1101252256321306179">"Lägg till ett telefonnummer"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 58d8e24..ce01517 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Nambari ya sauti inayokosekana"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Hakuna nambari ya ujumbe wa sauti iliyohifadhiwa katika SIM kadi."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Ongeza nambari"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Ungependa kubadilisha programu chaguo-msingi ya simu?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Ungependa kutumia <xliff:g id="NEW_APP">%1$s</xliff:g> badala ya <xliff:g id="CURRENT_APP">%2$s</xliff:g> kama programu ya chaguo-msingi ya kupigia simu?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Ungependa kutumia <xliff:g id="NEW_APP">%s</xliff:g> kama programu ya chaguo-msingi ya kupigia simu?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Unataka kufanya <xliff:g id="NEW_APP">%s</xliff:g> iwe programu chaguo-msingi ya simu?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Fanya iwe Chaguo-Msingi"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Ghairi"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> itaweza kupiga simu na kudhibiti kila kipengele cha simu. Unastahili kuweka programu unazoziamini tu kama programu chaguo-msingi ya kupiga simu."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Nambari zilizozuiwa"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Hutapokea simu au SMS kutoka kwa nambari zilizozuiwa."</string>
<string name="block_number" msgid="1101252256321306179">"Ongeza nambari"</string>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index b68a98f..e39a199 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"குரலஞ்சல் எண் இல்லை"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"சிம் கார்டில் குரலஞ்சலுக்கான எண் எதுவும் சேமிக்கப்படவில்லை."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"எண்ணைச் சேர்"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"இயல்புநிலை டயலர் பயன்பாட்டை மாற்றவா?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="NEW_APP">%1$s</xliff:g>ஐ <xliff:g id="CURRENT_APP">%2$s</xliff:g>க்குப் பதிலாக, இயல்புநிலை டயலர் பயன்பாடாகப் பயன்படுத்தவா?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g>ஐ இயல்புநிலை டயலர் பயன்பாடாகப் பயன்படுத்தவா?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g>ஐ இயல்புநிலை ஃபோன் பயன்பாடாக அமைக்கவா?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"இயல்புநிலையாக அமை"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ரத்துசெய்"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"அழைப்புகளின் எல்லா அம்சங்களையும் <xliff:g id="NEW_APP">%s</xliff:g> ஆல் செயல்படுத்தவும் கட்டுப்படுத்தவும் முடியும். நீங்கள் நம்பகமானது என கருதும் பயன்பாடுகளை மட்டுமே இயல்புநிலை ஃபோன் பயன்பாடாக அமைக்க வேண்டும்."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"தடுக்கப்பட்ட எண்கள்"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"தடுக்கப்பட்ட எண்களிலிருந்து அழைப்புகள் அல்லது உரைச் செய்திகளைப் பெறமாட்டீர்கள்."</string>
<string name="block_number" msgid="1101252256321306179">"எண்ணைச் சேர்"</string>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index e6d8156..09bc4cf 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"వాయిస్ మెయిల్ నంబర్ లేదు"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"సిమ్ కార్డులో వాయిస్ మెయిల్ నంబర్ ఏదీ నిల్వ చేయబడలేదు."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"నంబర్ను జోడించు"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"డిఫాల్ట్ డయలర్ అనువర్తనాన్ని మార్చాలా?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"మీ డిఫాల్ట్ డయలర్ అనువర్తనంగా <xliff:g id="CURRENT_APP">%2$s</xliff:g> బదులు <xliff:g id="NEW_APP">%1$s</xliff:g>ని ఉపయోగించాలా?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"మీ డిఫాల్ట్ డయలర్ అనువర్తనంగా <xliff:g id="NEW_APP">%s</xliff:g>ని ఉపయోగించాలా?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g>ని మీ డిఫాల్ట్ ఫోన్ అనువర్తనంగా చేయాలా?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"డిఫాల్ట్గా సెట్ చేయండి"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"రద్దు చేయి"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> అన్ని రకాల కాల్లను చేయగలదు మరియు సంబంధిత అన్ని అంశాలను నియంత్రించగలదు. మీరు విశ్వసించే అనువర్తనాలను మాత్రమే డిఫాల్ట్ ఫోన్ అనువర్తనంగా సెట్ చేయాలి."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"బ్లాక్ చేయబడిన నంబర్లు"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"మీరు బ్లాక్ చేయబడిన నంబర్ల నుండి కాల్లు లేదా వచన సందేశాలను స్వీకరించరు."</string>
<string name="block_number" msgid="1101252256321306179">"నంబర్ను జోడించు"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 5a7cf4f..2acead3 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"ไม่มีหมายเลขข้อความเสียง"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"ไม่มีหมายเลขข้อความเสียงจัดเก็บอยู่ในซิมการ์ด"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"เพิ่มหมายเลข"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"เปลี่ยนแอปแป้นโทรศัพท์เริ่มต้นไหม"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"ใช้ <xliff:g id="NEW_APP">%1$s</xliff:g> เป็นแอปแป้นโทรศัพท์เริ่มต้นแทน <xliff:g id="CURRENT_APP">%2$s</xliff:g> ไหม"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"ใช้ <xliff:g id="NEW_APP">%s</xliff:g> เป็นแอปแป้นโทรศัพท์เริ่มต้นไหม"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"ต้องการตั้งค่าให้ <xliff:g id="NEW_APP">%s</xliff:g> เป็นแอปโทรศัพท์เริ่มต้นหรือไม่"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ตั้งเป็นค่าเริ่มต้น"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ยกเลิก"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> จะจัดการการโทรและควบคุมการติดต่อทุกด้าน โปรดติดตั้งเฉพาะแอปที่คุณไว้วางใจให้เป็นแอปโทรศัพท์เริ่มต้น"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"หมายเลขที่ถูกบล็อก"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"คุณจะไม่สามารถรับสายหรือข้อความจากหมายเลขที่บล็อกได้"</string>
<string name="block_number" msgid="1101252256321306179">"เพิ่มหมายเลข"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index b658c36..b711f07 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Nawawala ang numero ng voicemail"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Walang nakaimbak na numero ng voicemail sa SIM card."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Magdagdag ng numero"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Baguhin ang iyong default na Dialer app?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Gamitin ang <xliff:g id="NEW_APP">%1$s</xliff:g> sa halip na <xliff:g id="CURRENT_APP">%2$s</xliff:g> bilang default na dialer app mo?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Gamitin ang <xliff:g id="NEW_APP">%s</xliff:g> bilang default na dialer app mo?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Gawing iyong default na app na Telepono ang <xliff:g id="NEW_APP">%s</xliff:g>?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Magtakda ng Default"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Kanselahin"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"Ang <xliff:g id="NEW_APP">%s</xliff:g> ay magagawang tumawag at kontrolin ang lahat ng aspeto ng tawag. Mga app na pinagkakatiwalaan mo lang ang dapat itakda bilang default na app na Telepono."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Mga naka-block na numero"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Hindi ka makakatanggap ng mga tawag o mga text mula sa mga naka-block na numero."</string>
<string name="block_number" msgid="1101252256321306179">"Magdagdag ng numero"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 229cf0f..5c20656 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Eksik sesli mesaj numarası"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartta depolanan sesli mesaj numarası yok."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Numara ekle"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Varsayılan Numara Çeviri uygulaması değiştirilsin mi?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Varsayılan numara çevirici uygulamanız olarak <xliff:g id="CURRENT_APP">%2$s</xliff:g> yerine <xliff:g id="NEW_APP">%1$s</xliff:g> kullanılsın mı?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Varsayılan numara çevirici uygulamanız olarak <xliff:g id="NEW_APP">%s</xliff:g> kullanılsın mı?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> varsayılan Telefon uygulamanız yapılsın mı?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Varsayılan Uygulamayı Ayarla"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"İptal"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> uygulaması üzerinden çağrı yapabilecek ve çağrıları her yönüyle kontrol edebileceksiniz. Yalnızca güvendiğiniz uygulamalar varsayılan Telefon uygulaması olarak ayarlanmalıdır."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Engellenen numaralar"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Engellenen numaralardan gelen çağrıları veya kısa mesajları almazsınız."</string>
<string name="block_number" msgid="1101252256321306179">"Numara ekle"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 384413e..036ea40 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Відстуній номер голосової пошти"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"На SIM-карті немає збереж. номерів голос. пошти."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Додати номер"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Змінити додаток для дзвінків за умовчанням?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Зробити <xliff:g id="NEW_APP">%1$s</xliff:g> додатком для дзвінків за умовчанням замість додатка <xliff:g id="CURRENT_APP">%2$s</xliff:g>?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Зробити <xliff:g id="NEW_APP">%s</xliff:g> додатком для дзвінків за умовчанням?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Зробити <xliff:g id="NEW_APP">%s</xliff:g> додатком для викликів за умовчанням?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Установити за умовчанням"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Скасувати"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"За допомогою додатка <xliff:g id="NEW_APP">%s</xliff:g> ви зможете здійснювати та контролювати виклики. Лише довірені додатки можна встановлювати як додатки для викликів за умовчанням."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Заблоковані номери"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Ви не отримуватимете виклики й повідомлення із заблокованих номерів."</string>
<string name="block_number" msgid="1101252256321306179">"Додати номер"</string>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index f880d83..b917066 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"صوتی میل نمبر درج نہیں ہے"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM کارڈ پر کوئی بھی صوتی میل نمبر اسٹور نہیں ہے۔"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"نمبر شامل کریں"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"ڈیفالٹ ڈائلر ایپ تبدیل کریں"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"<xliff:g id="CURRENT_APP">%2$s</xliff:g> کی بجائے <xliff:g id="NEW_APP">%1$s</xliff:g> کو بطور اپنی ڈیفالٹ ڈائلر ایپ استعمال کریں؟"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> کو بطور اپنی ڈیفالٹ ڈائلر ایپ استعمال کریں؟"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> کو اپنی ڈیفالٹ فون ایپ بنائیں؟"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ڈیفالٹ سیٹ کریں"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"منسوخ کریں"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> کال کرنے اور اس کے باقی تمام پہلوؤں کو کنٹرول کر پائے گی۔ صرف ان ایپس کو بطور ڈیفالٹ فون ایپ سیٹ کرنا چاہئیے جن پر آپ کو اعتماد ہے۔"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"مسدود کردہ نمبرز"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"آپ مسدود کردہ نمبروں سے کالیں یا متنی پیغامات وصول نہیں کریں گے۔"</string>
<string name="block_number" msgid="1101252256321306179">"ایک نمبر شامل کریں"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index ecfbf3b..8e8ab26 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Ovozli pochta raqami ko‘rsatilmagan"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartada birorta ham ovozli pochta raqami yo‘q."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Raqam qo‘shish"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Birlamchi raqam terish ilovasi o‘zgartirilsinmi?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Raqam terish uchun birlamchi ilova sifatida <xliff:g id="CURRENT_APP">%2$s</xliff:g> o‘rniga <xliff:g id="NEW_APP">%1$s</xliff:g> ilovasi tanlansinmi?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"<xliff:g id="NEW_APP">%s</xliff:g> raqam terish uchun birlamchi ilova sifatida tanlansinmi?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Qo‘ng‘iroq. uchun <xliff:g id="NEW_APP">%s</xliff:g> asosiy ilova sifatida o‘rnatilsinmi?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Asosiy ilova sifatida o‘rnatish"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Bekor qilish"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> ilovasi qo‘ng‘iroq qilishga yodam beradi va qo‘ng‘iroqlarga tegishli boshqa barcha parametrlarni boshqaradi. Qo‘ng‘iroqlar uchun faqat ishonarli ilovani asosiy ilova qilib o‘rnatish lozim."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Bloklangan raqamlar"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Bloklangan raqamlardan keladigan qo‘ng‘iroq yoki SMS xabarlar qabul qilinmaydi."</string>
<string name="block_number" msgid="1101252256321306179">"Raqam qo‘shish"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index ec10471..2308246 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Thiếu số thư thoại"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Không có số thư thoại nào được lưu trữ trên thẻ SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Thêm số điện thoại"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Thay đổi ứng dụng Trình quay số mặc định?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Sử dụng <xliff:g id="NEW_APP">%1$s</xliff:g> làm ứng dụng trình quay số mặc định của bạn thay vì <xliff:g id="CURRENT_APP">%2$s</xliff:g>?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Sử dụng <xliff:g id="NEW_APP">%s</xliff:g> làm ứng dụng trình quay số mặc định của bạn?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Đặt <xliff:g id="NEW_APP">%s</xliff:g> làm ứng dụng Điện thoại mặc định của bạn?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Đặt làm mặc định"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Hủy"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> sẽ có thể đặt và kiểm soát mọi khía cạnh của cuộc gọi. Chỉ nên đặt những ứng dụng mà bạn tin cậy làm ứng dụng Điện thoại mặc định."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Số bị chặn"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Bạn sẽ không nhận được cuộc gọi hoặc tin nhắn từ các số bị chặn."</string>
<string name="block_number" msgid="1101252256321306179">"Thêm số điện thoại"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index b67f1f3..8374edb 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -25,7 +25,7 @@
<string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> 个未接电话"</string>
<string name="notification_missedCallTicker" msgid="504686252427747209">"来自<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>的未接电话"</string>
<string name="notification_missedCall_call_back" msgid="2684890353590890187">"回拨"</string>
- <string name="notification_missedCall_message" msgid="3049928912736917988">"短信"</string>
+ <string name="notification_missedCall_message" msgid="3049928912736917988">"发短信"</string>
<string name="accessibility_call_muted" msgid="2776111226185342220">"通话已静音。"</string>
<string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"扬声器已启用。"</string>
<string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"现在无法接听。有什么事吗?"</string>
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"缺少语音信箱号码"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM卡上未存储语音信箱号码。"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"添加号码"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"要更改默认拨号器应用吗?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"要使用<xliff:g id="NEW_APP">%1$s</xliff:g>(而非<xliff:g id="CURRENT_APP">%2$s</xliff:g>)作为您的默认拨号器应用吗?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"要使用<xliff:g id="NEW_APP">%s</xliff:g>作为您的默认拨号器应用吗?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"要将 <xliff:g id="NEW_APP">%s</xliff:g> 设为默认电话应用吗?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"设为默认电话应用"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"取消"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> 将可用于拨打电话和全面管理通话。请务必仅将您信任的应用设为默认电话应用。"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"已屏蔽的号码"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"您不会收到来自已屏蔽的号码的来电或短信。"</string>
<string name="block_number" msgid="1101252256321306179">"添加电话号码"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 0fe3e60..0dff76b 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"未填留言信箱號碼"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM 卡中沒有儲存任何留言信箱號碼。"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"新增電話號碼"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"變更預設撥號器應用程式?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"使用 <xliff:g id="NEW_APP">%1$s</xliff:g> 取代 <xliff:g id="CURRENT_APP">%2$s</xliff:g> 作為預設撥號器應用程式?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"使用 <xliff:g id="NEW_APP">%s</xliff:g> 為預設撥號器應用程式?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"要將<xliff:g id="NEW_APP">%s</xliff:g>設為預設電話應用程式嗎?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"設為預設"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"取消"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"「<xliff:g id="NEW_APP">%s</xliff:g>」將可撥打電話並控制所有相關功能。只有您信任的應用程式,才應設為預設手機應用程式。"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"已封鎖的號碼"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"您不會收到已封鎖號碼的來電或短訊。"</string>
<string name="block_number" msgid="1101252256321306179">"新增號碼"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 9d4b99d..7bb98a9 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"遺失語音信箱號碼"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"SIM 卡中未儲存語音信箱號碼。"</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"新增號碼"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"要變更預設撥號應用程式嗎?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"要將 <xliff:g id="NEW_APP">%1$s</xliff:g> (而非 <xliff:g id="CURRENT_APP">%2$s</xliff:g>) 設為預設撥號應用程式嗎?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"要將 <xliff:g id="NEW_APP">%s</xliff:g> 設為預設撥號應用程式嗎?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"確定要將 <xliff:g id="NEW_APP">%s</xliff:g> 設為預設電話應用程式嗎?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"設為預設電話應用程式"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"取消"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"這樣一來,<xliff:g id="NEW_APP">%s</xliff:g> 將能撥打電話及控管所有通話設定。請務必只將您信任的應用程式設為預設電話應用程式。"</string>
<string name="blocked_numbers" msgid="2751843139572970579">"已封鎖的號碼"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"您不會收到已封鎖號碼的來電或簡訊。"</string>
<string name="block_number" msgid="1101252256321306179">"新增號碼"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 00c7e14..b65700c 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -45,9 +45,10 @@
<string name="no_vm_number" msgid="4164780423805688336">"Inombolo engekho yomyalezo wezwi"</string>
<string name="no_vm_number_msg" msgid="1300729501030053828">"Ayikho inombolo yomlayezo wezwi egcinwe ekhadini le-SIM."</string>
<string name="add_vm_number_str" msgid="4676479471644687453">"Engeza inombolo"</string>
- <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Guqula uhlelo lwakho lokusebenza oluzenzakalelayo lokudayela?"</string>
- <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Sebenzisa i-<xliff:g id="NEW_APP">%1$s</xliff:g> esikhundleni se-<xliff:g id="CURRENT_APP">%2$s</xliff:g> njengohlelo lwakho lokusebenza oluzenzakalelayo lokokudayela?"</string>
- <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Sebenzisa i-<xliff:g id="NEW_APP">%s</xliff:g> njengohlelo lwakho lokusebenza oluzenzakalelayo lokokudayela?"</string>
+ <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Yenza i-<xliff:g id="NEW_APP">%s</xliff:g> uhlelo lwakho lwefoni oluzenzakalelayo?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Setha okuzenzakalelayo"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Khansela"</string>
+ <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> Uzokwazi ukubeka nokulawula zonke izinto zamakholi. Izinhlelo zokusebenza kuphela ozithembayo ezingasethwa njengohlelo lokusebenza oluzenzakalelayo lefoni."</string>
<string name="blocked_numbers" msgid="2751843139572970579">"Izinombolo ezivinjiwe"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Ngeke uthole amakholi noma imibhalo kusuka kuzinombolo ezivinjelwe."</string>
<string name="block_number" msgid="1101252256321306179">"Engeza inombolo"</string>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 75b8352..b0bcd3c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -15,11 +15,11 @@
-->
<resources>
- <color name="theme_color">#0288d1</color>
+ <color name="theme_color">#2a56c6</color>
<color name="dialer_settings_actionbar_text_color">#ffffff</color>
<color name="dialer_settings_actionbar_background_color">@color/theme_color</color>
- <color name="dialer_settings_color_dark">#0277bd</color>
+ <color name="dialer_settings_color_dark">#1c3aa9</color>
<color name="blocked_numbers_divider_color">#e5e5e5</color>
<color name="blocked_numbers_butter_bar_color">#f5f5f5</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e46aa54..11b2d50 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -109,12 +109,13 @@
<!-- Title of dialog used to comfirm whether the user intends to change the default dialer
application [CHAR LIMIT=55]-->
- <string name="change_default_dialer_dialog_title">Change default Dialer app?</string>
- <!-- Text in dialog used to confirm whether or not the user intends to change the default dialer, if a different default dialer has been previously set. -->
- <string name="change_default_dialer_with_previous_app_set_text">Use <xliff:g id="new_app">%1$s</xliff:g> instead of <xliff:g id="current_app">%2$s</xliff:g> as your default dialer app?</string>
- <!-- Text in dialog used to confirm whether or not the user intends to change the default dialer, if a different default dialer has not been previously set. -->
- <string name="change_default_dialer_no_previous_app_set_text">Use <xliff:g id="new_app">%s</xliff:g> as your default dialer app?</string>
-
+ <string name="change_default_dialer_dialog_title">Make <xliff:g id="new_app">%s</xliff:g> your default Phone app?</string>
+ <!-- Confirmation text that a user taps on to change the Default Phone App-->
+ <string name="change_default_dialer_dialog_affirmative">Set Default</string>
+ <!-- Cancel text that a user taps on to not change the Default Phone App-->
+ <string name="change_default_dialer_dialog_negative">Cancel</string>
+ <!-- Warning message indicating what may happen if a user allows a 3rd party app to become the default dialer.-->
+ <string name="change_default_dialer_warning_message"><xliff:g id="new_app">%s</xliff:g> will be able to place and control all aspects of calls. Only apps you trust should be set as the default Phone app.</string>
<!-- Blocked numbers -->
<string name="blocked_numbers">Blocked numbers</string>
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index afbb69d..0a15b26 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -16,44 +16,174 @@
package com.android.server.telecom;
-import android.telecom.ParcelableCallAnalytics;
+import android.telecom.Connection;
import android.telecom.DisconnectCause;
+import android.telecom.Logging.EventManager;
+import android.telecom.ParcelableCallAnalytics;
+import android.telecom.TelecomAnalytics;
+import android.util.Base64;
import android.telecom.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+
+import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent;
+import static android.telecom.TelecomAnalytics.SessionTiming;
/**
* A class that collects and stores data on how calls are being made, in order to
* aggregate these into useful statistics.
*/
public class Analytics {
- public static class CallInfo {
- void setCallStartTime(long startTime) {
+ public static final String ANALYTICS_DUMPSYS_ARG = "analytics";
+ private static final String CLEAR_ANALYTICS_ARG = "clear";
+
+ public static final Map<String, Integer> sLogEventToAnalyticsEvent =
+ new HashMap<String, Integer>() {{
+ put(LogUtils.Events.SET_SELECT_PHONE_ACCOUNT, AnalyticsEvent.SET_SELECT_PHONE_ACCOUNT);
+ put(LogUtils.Events.REQUEST_HOLD, AnalyticsEvent.REQUEST_HOLD);
+ put(LogUtils.Events.REQUEST_UNHOLD, AnalyticsEvent.REQUEST_UNHOLD);
+ put(LogUtils.Events.SWAP, AnalyticsEvent.SWAP);
+ put(LogUtils.Events.SKIP_RINGING, AnalyticsEvent.SKIP_RINGING);
+ put(LogUtils.Events.CONFERENCE_WITH, AnalyticsEvent.CONFERENCE_WITH);
+ put(LogUtils.Events.SPLIT_FROM_CONFERENCE, AnalyticsEvent.SPLIT_CONFERENCE);
+ put(LogUtils.Events.SET_PARENT, AnalyticsEvent.SET_PARENT);
+ put(LogUtils.Events.MUTE, AnalyticsEvent.MUTE);
+ put(LogUtils.Events.UNMUTE, AnalyticsEvent.UNMUTE);
+ put(LogUtils.Events.AUDIO_ROUTE_BT, AnalyticsEvent.AUDIO_ROUTE_BT);
+ put(LogUtils.Events.AUDIO_ROUTE_EARPIECE, AnalyticsEvent.AUDIO_ROUTE_EARPIECE);
+ put(LogUtils.Events.AUDIO_ROUTE_HEADSET, AnalyticsEvent.AUDIO_ROUTE_HEADSET);
+ put(LogUtils.Events.AUDIO_ROUTE_SPEAKER, AnalyticsEvent.AUDIO_ROUTE_SPEAKER);
+ put(LogUtils.Events.SILENCE, AnalyticsEvent.SILENCE);
+ put(LogUtils.Events.SCREENING_COMPLETED, AnalyticsEvent.SCREENING_COMPLETED);
+ put(LogUtils.Events.BLOCK_CHECK_FINISHED, AnalyticsEvent.BLOCK_CHECK_FINISHED);
+ put(LogUtils.Events.DIRECT_TO_VM_FINISHED, AnalyticsEvent.DIRECT_TO_VM_FINISHED);
+ put(LogUtils.Events.REMOTELY_HELD, AnalyticsEvent.REMOTELY_HELD);
+ put(LogUtils.Events.REMOTELY_UNHELD, AnalyticsEvent.REMOTELY_UNHELD);
+ put(LogUtils.Events.REQUEST_PULL, AnalyticsEvent.REQUEST_PULL);
+ put(LogUtils.Events.REQUEST_ACCEPT, AnalyticsEvent.REQUEST_ACCEPT);
+ put(LogUtils.Events.REQUEST_REJECT, AnalyticsEvent.REQUEST_REJECT);
+ put(LogUtils.Events.SET_ACTIVE, AnalyticsEvent.SET_ACTIVE);
+ put(LogUtils.Events.SET_DISCONNECTED, AnalyticsEvent.SET_DISCONNECTED);
+ put(LogUtils.Events.SET_HOLD, AnalyticsEvent.SET_HOLD);
+ put(LogUtils.Events.SET_DIALING, AnalyticsEvent.SET_DIALING);
+ put(LogUtils.Events.START_CONNECTION, AnalyticsEvent.START_CONNECTION);
+ put(LogUtils.Events.BIND_CS, AnalyticsEvent.BIND_CS);
+ put(LogUtils.Events.CS_BOUND, AnalyticsEvent.CS_BOUND);
+ put(LogUtils.Events.SCREENING_SENT, AnalyticsEvent.SCREENING_SENT);
+ put(LogUtils.Events.DIRECT_TO_VM_INITIATED, AnalyticsEvent.DIRECT_TO_VM_INITIATED);
+ put(LogUtils.Events.BLOCK_CHECK_INITIATED, AnalyticsEvent.BLOCK_CHECK_INITIATED);
+ put(LogUtils.Events.FILTERING_INITIATED, AnalyticsEvent.FILTERING_INITIATED);
+ put(LogUtils.Events.FILTERING_COMPLETED, AnalyticsEvent.FILTERING_COMPLETED);
+ put(LogUtils.Events.FILTERING_TIMED_OUT, AnalyticsEvent.FILTERING_TIMED_OUT);
+ }};
+
+ public static final Map<String, Integer> sLogSessionToSessionId =
+ new HashMap<String, Integer> () {{
+ put(LogUtils.Sessions.ICA_ANSWER_CALL, SessionTiming.ICA_ANSWER_CALL);
+ put(LogUtils.Sessions.ICA_REJECT_CALL, SessionTiming.ICA_REJECT_CALL);
+ put(LogUtils.Sessions.ICA_DISCONNECT_CALL, SessionTiming.ICA_DISCONNECT_CALL);
+ put(LogUtils.Sessions.ICA_HOLD_CALL, SessionTiming.ICA_HOLD_CALL);
+ put(LogUtils.Sessions.ICA_UNHOLD_CALL, SessionTiming.ICA_UNHOLD_CALL);
+ put(LogUtils.Sessions.ICA_MUTE, SessionTiming.ICA_MUTE);
+ put(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, SessionTiming.ICA_SET_AUDIO_ROUTE);
+ put(LogUtils.Sessions.ICA_CONFERENCE, SessionTiming.ICA_CONFERENCE);
+ put(LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
+ SessionTiming.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
+ put(LogUtils.Sessions.CSW_SET_ACTIVE, SessionTiming.CSW_SET_ACTIVE);
+ put(LogUtils.Sessions.CSW_SET_RINGING, SessionTiming.CSW_SET_RINGING);
+ put(LogUtils.Sessions.CSW_SET_DIALING, SessionTiming.CSW_SET_DIALING);
+ put(LogUtils.Sessions.CSW_SET_DISCONNECTED, SessionTiming.CSW_SET_DISCONNECTED);
+ put(LogUtils.Sessions.CSW_SET_ON_HOLD, SessionTiming.CSW_SET_ON_HOLD);
+ put(LogUtils.Sessions.CSW_REMOVE_CALL, SessionTiming.CSW_REMOVE_CALL);
+ put(LogUtils.Sessions.CSW_SET_IS_CONFERENCED, SessionTiming.CSW_SET_IS_CONFERENCED);
+ put(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL, SessionTiming.CSW_ADD_CONFERENCE_CALL);
+
+ }};
+
+ public static final Map<String, Integer> sLogEventTimingToAnalyticsEventTiming =
+ new HashMap<String, Integer>() {{
+ put(LogUtils.Events.Timings.ACCEPT_TIMING,
+ ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING);
+ put(LogUtils.Events.Timings.REJECT_TIMING,
+ ParcelableCallAnalytics.EventTiming.REJECT_TIMING);
+ put(LogUtils.Events.Timings.DISCONNECT_TIMING,
+ ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING);
+ put(LogUtils.Events.Timings.HOLD_TIMING,
+ ParcelableCallAnalytics.EventTiming.HOLD_TIMING);
+ put(LogUtils.Events.Timings.UNHOLD_TIMING,
+ ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING);
+ put(LogUtils.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING,
+ ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING);
+ put(LogUtils.Events.Timings.BIND_CS_TIMING,
+ ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING);
+ put(LogUtils.Events.Timings.SCREENING_COMPLETED_TIMING,
+ ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING);
+ put(LogUtils.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING,
+ ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING);
+ put(LogUtils.Events.Timings.BLOCK_CHECK_FINISHED_TIMING,
+ ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING);
+ put(LogUtils.Events.Timings.FILTERING_COMPLETED_TIMING,
+ ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING);
+ put(LogUtils.Events.Timings.FILTERING_TIMED_OUT_TIMING,
+ ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING);
+ }};
+
+ public static final Map<Integer, String> sSessionIdToLogSession = new HashMap<>();
+ static {
+ for (Map.Entry<String, Integer> e : sLogSessionToSessionId.entrySet()) {
+ sSessionIdToLogSession.put(e.getValue(), e.getKey());
+ }
+ }
+
+ public static class CallInfo {
+ public void setCallStartTime(long startTime) {
}
- void setCallEndTime(long endTime) {
+ public void setCallEndTime(long endTime) {
}
- void setCallIsAdditional(boolean isAdditional) {
+ public void setCallIsAdditional(boolean isAdditional) {
}
- void setCallIsInterrupted(boolean isInterrupted) {
+ public void setCallIsInterrupted(boolean isInterrupted) {
}
- void setCallDisconnectCause(DisconnectCause disconnectCause) {
+ public void setCallDisconnectCause(DisconnectCause disconnectCause) {
}
- void addCallTechnology(int callTechnology) {
+ public void addCallTechnology(int callTechnology) {
}
- void setCreatedFromExistingConnection(boolean createdFromExistingConnection) {
+ public void setCreatedFromExistingConnection(boolean createdFromExistingConnection) {
}
- void setCallConnectionService(String connectionServiceName) {
+ public void setCallConnectionService(String connectionServiceName) {
+ }
+
+ public void setCallEvents(EventManager.EventRecord records) {
+ }
+
+ public void setCallIsVideo(boolean isVideo) {
+ }
+
+ public void addVideoEvent(int eventId, int videoState) {
+ }
+
+ public void addInCallService(String serviceName, int type) {
+ }
+
+ public void addCallProperties(int properties) {
}
}
@@ -82,6 +212,15 @@
public String connectionService;
public boolean isEmergency = false;
+ public EventManager.EventRecord callEvents;
+
+ public boolean isVideo = false;
+ public List<TelecomLogClass.VideoEvent> videoEvents;
+ public List<TelecomLogClass.InCallServiceInfo> inCallServiceInfos;
+ public int callProperties = 0;
+
+ private long mTimeOfLastVideoEvent = -1;
+
CallInfoImpl(String callId, int callDirection) {
this.callId = callId;
startTime = 0;
@@ -89,6 +228,8 @@
this.callDirection = callDirection;
callTechnologies = 0;
connectionService = "";
+ videoEvents = new LinkedList<>();
+ inCallServiceInfos = new LinkedList<>();
}
CallInfoImpl(CallInfoImpl other) {
@@ -102,6 +243,10 @@
this.createdFromExistingConnection = other.createdFromExistingConnection;
this.connectionService = other.connectionService;
this.isEmergency = other.isEmergency;
+ this.callEvents = other.callEvents;
+ this.isVideo = other.isVideo;
+ this.videoEvents = other.videoEvents;
+ this.callProperties = other.callProperties;
if (other.callTerminationReason != null) {
this.callTerminationReason = new DisconnectCause(
@@ -166,6 +311,45 @@
}
@Override
+ public void setCallEvents(EventManager.EventRecord records) {
+ this.callEvents = records;
+ }
+
+ @Override
+ public void setCallIsVideo(boolean isVideo) {
+ this.isVideo = isVideo;
+ }
+
+ @Override
+ public void addVideoEvent(int eventId, int videoState) {
+ long timeSinceLastEvent;
+ long currentTime = System.currentTimeMillis();
+ if (mTimeOfLastVideoEvent < 0) {
+ timeSinceLastEvent = -1;
+ } else {
+ timeSinceLastEvent = roundToOneSigFig(currentTime - mTimeOfLastVideoEvent);
+ }
+ mTimeOfLastVideoEvent = currentTime;
+
+ videoEvents.add(new TelecomLogClass.VideoEvent()
+ .setEventName(eventId)
+ .setTimeSinceLastEventMillis(timeSinceLastEvent)
+ .setVideoState(videoState));
+ }
+
+ @Override
+ public void addInCallService(String serviceName, int type) {
+ inCallServiceInfos.add(new TelecomLogClass.InCallServiceInfo()
+ .setInCallServiceName(serviceName)
+ .setInCallServiceType(type));
+ }
+
+ @Override
+ public void addCallProperties(int properties) {
+ this.callProperties |= properties;
+ }
+
+ @Override
public String toString() {
return "{\n"
+ " startTime: " + startTime + '\n'
@@ -176,28 +360,93 @@
+ " callTechnologies: " + getCallTechnologiesAsString() + '\n'
+ " callTerminationReason: " + getCallDisconnectReasonString() + '\n'
+ " connectionService: " + connectionService + '\n'
+ + " isVideoCall: " + isVideo + '\n'
+ + " inCallServices: " + getInCallServicesString() + '\n'
+ + " callProperties: " + Connection.propertiesToStringShort(callProperties)
+ + '\n'
+ "}\n";
}
public ParcelableCallAnalytics toParcelableAnalytics() {
+ TelecomLogClass.CallLog analyticsProto = toProto();
+ List<ParcelableCallAnalytics.AnalyticsEvent> events =
+ Arrays.stream(analyticsProto.callEvents)
+ .map(callEventProto -> new ParcelableCallAnalytics.AnalyticsEvent(
+ callEventProto.getEventName(),
+ callEventProto.getTimeSinceLastEventMillis())
+ ).collect(Collectors.toList());
+
+ List<ParcelableCallAnalytics.EventTiming> timings =
+ Arrays.stream(analyticsProto.callTimings)
+ .map(callTimingProto -> new ParcelableCallAnalytics.EventTiming(
+ callTimingProto.getTimingName(),
+ callTimingProto.getTimeMillis())
+ ).collect(Collectors.toList());
+
+ ParcelableCallAnalytics result = new ParcelableCallAnalytics(
+ // rounds down to nearest 5 minute mark
+ analyticsProto.getStartTime5Min(),
+ analyticsProto.getCallDurationMillis(),
+ analyticsProto.getType(),
+ analyticsProto.getIsAdditionalCall(),
+ analyticsProto.getIsInterrupted(),
+ analyticsProto.getCallTechnologies(),
+ analyticsProto.getCallTerminationCode(),
+ analyticsProto.getIsEmergencyCall(),
+ analyticsProto.connectionService[0],
+ analyticsProto.getIsCreatedFromExistingConnection(),
+ events,
+ timings);
+
+ result.setIsVideoCall(analyticsProto.getIsVideoCall());
+ result.setVideoEvents(Arrays.stream(analyticsProto.videoEvents)
+ .map(videoEventProto -> new ParcelableCallAnalytics.VideoEvent(
+ videoEventProto.getEventName(),
+ videoEventProto.getTimeSinceLastEventMillis(),
+ videoEventProto.getVideoState())
+ ).collect(Collectors.toList()));
+
+ return result;
+ }
+
+ public TelecomLogClass.CallLog toProto() {
+ TelecomLogClass.CallLog result = new TelecomLogClass.CallLog();
+ result.setStartTime5Min(
+ startTime - startTime % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
+
// Rounds up to the nearest second.
long callDuration = (endTime == 0 || startTime == 0) ? 0 : endTime - startTime;
callDuration += (callDuration % MILLIS_IN_1_SECOND == 0) ?
0 : (MILLIS_IN_1_SECOND - callDuration % MILLIS_IN_1_SECOND);
- return new ParcelableCallAnalytics(
- // rounds down to nearest 5 minute mark
- startTime - startTime % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES,
- callDuration,
- callDirection,
- isAdditionalCall,
- isInterrupted,
- callTechnologies,
- callTerminationReason == null ?
- ParcelableCallAnalytics.STILL_CONNECTED :
- callTerminationReason.getCode(),
- isEmergency,
- connectionService,
- createdFromExistingConnection);
+ result.setCallDurationMillis(callDuration);
+
+ result.setType(callDirection)
+ .setIsAdditionalCall(isAdditionalCall)
+ .setIsInterrupted(isInterrupted)
+ .setCallTechnologies(callTechnologies)
+ .setCallTerminationCode(
+ callTerminationReason == null ?
+ ParcelableCallAnalytics.STILL_CONNECTED :
+ callTerminationReason.getCode())
+ .setIsEmergencyCall(isEmergency)
+ .setIsCreatedFromExistingConnection(createdFromExistingConnection)
+ .setIsEmergencyCall(isEmergency)
+ .setIsVideoCall(isVideo)
+ .setConnectionProperties(callProperties);
+
+ result.connectionService = new String[] {connectionService};
+ if (callEvents != null) {
+ result.callEvents = convertLogEventsToProtoEvents(callEvents.getEvents());
+ result.callTimings = callEvents.extractEventTimings().stream()
+ .map(Analytics::logEventTimingToProtoEventTiming)
+ .toArray(TelecomLogClass.EventTimingEntry[]::new);
+ }
+ result.videoEvents =
+ videoEvents.toArray(new TelecomLogClass.VideoEvent[videoEvents.size()]);
+ result.inCallServices = inCallServiceInfos.toArray(
+ new TelecomLogClass.InCallServiceInfo[inCallServiceInfos.size()]);
+
+ return result;
}
private String getCallDirectionString() {
@@ -232,6 +481,21 @@
return "NOT SET";
}
}
+
+ private String getInCallServicesString() {
+ StringBuilder s = new StringBuilder();
+ s.append("[\n");
+ for (TelecomLogClass.InCallServiceInfo service : inCallServiceInfos) {
+ s.append(" ");
+ s.append("name: ");
+ s.append(service.getInCallServiceName());
+ s.append(" type: ");
+ s.append(service.getInCallServiceType());
+ s.append("\n");
+ }
+ s.append("]");
+ return s.toString();
+ }
}
public static final String TAG = "TelecomAnalytics";
@@ -247,10 +511,30 @@
public static final int SIP_PHONE = ParcelableCallAnalytics.SIP_PHONE;
public static final int THIRD_PARTY_PHONE = ParcelableCallAnalytics.THIRD_PARTY_PHONE;
+ // Constants for video events
+ public static final int SEND_LOCAL_SESSION_MODIFY_REQUEST =
+ ParcelableCallAnalytics.VideoEvent.SEND_LOCAL_SESSION_MODIFY_REQUEST;
+ public static final int SEND_LOCAL_SESSION_MODIFY_RESPONSE =
+ ParcelableCallAnalytics.VideoEvent.SEND_LOCAL_SESSION_MODIFY_RESPONSE;
+ public static final int RECEIVE_REMOTE_SESSION_MODIFY_REQUEST =
+ ParcelableCallAnalytics.VideoEvent.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST;
+ public static final int RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE =
+ ParcelableCallAnalytics.VideoEvent.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE;
+
public static final long MILLIS_IN_1_SECOND = ParcelableCallAnalytics.MILLIS_IN_1_SECOND;
private static final Object sLock = new Object(); // Coarse lock for all of analytics
private static final Map<String, CallInfoImpl> sCallIdToInfo = new HashMap<>();
+ private static final List<SessionTiming> sSessionTimings = new LinkedList<>();
+
+ public static void addSessionTiming(String sessionName, long time) {
+ if (sLogSessionToSessionId.containsKey(sessionName)) {
+ synchronized (sLock) {
+ sSessionTimings.add(new SessionTiming(sLogSessionToSessionId.get(sessionName),
+ time));
+ }
+ }
+ }
public static CallInfo initiateCallAnalytics(String callId, int direction) {
Log.d(TAG, "Starting analytics for call " + callId);
@@ -261,26 +545,77 @@
return callInfo;
}
- public static ParcelableCallAnalytics[] dumpToParcelableAnalytics() {
- ParcelableCallAnalytics[] result;
+ public static TelecomAnalytics dumpToParcelableAnalytics() {
+ List<ParcelableCallAnalytics> calls = new LinkedList<>();
+ List<SessionTiming> sessionTimings = new LinkedList<>();
synchronized (sLock) {
- result = new ParcelableCallAnalytics[sCallIdToInfo.size()];
- int idx = 0;
- for (CallInfoImpl entry : sCallIdToInfo.values()) {
- result[idx] = entry.toParcelableAnalytics();
- idx++;
- }
+ calls.addAll(sCallIdToInfo.values().stream()
+ .map(CallInfoImpl::toParcelableAnalytics)
+ .collect(Collectors.toList()));
+ sessionTimings.addAll(sSessionTimings);
sCallIdToInfo.clear();
+ sSessionTimings.clear();
}
- return result;
+ return new TelecomAnalytics(sessionTimings, calls);
+ }
+
+ public static void dumpToEncodedProto(PrintWriter pw, String[] args) {
+ TelecomLogClass.TelecomLog result = new TelecomLogClass.TelecomLog();
+
+ synchronized (sLock) {
+ result.callLogs = sCallIdToInfo.values().stream()
+ .map(CallInfoImpl::toProto)
+ .toArray(TelecomLogClass.CallLog[]::new);
+ result.sessionTimings = sSessionTimings.stream()
+ .map(timing -> new TelecomLogClass.LogSessionTiming()
+ .setSessionEntryPoint(timing.getKey())
+ .setTimeMillis(timing.getTime()))
+ .toArray(TelecomLogClass.LogSessionTiming[]::new);
+ if (args.length > 1 && CLEAR_ANALYTICS_ARG.equals(args[1])) {
+ sCallIdToInfo.clear();
+ sSessionTimings.clear();
+ }
+ }
+ String encodedProto = Base64.encodeToString(
+ TelecomLogClass.TelecomLog.toByteArray(result), Base64.DEFAULT);
+ pw.write(encodedProto);
}
public static void dump(IndentingPrintWriter writer) {
synchronized (sLock) {
- for (Map.Entry<String, CallInfoImpl> entry : sCallIdToInfo.entrySet()) {
- writer.printf("Call %s: ", entry.getKey());
- writer.println(entry.getValue().toString());
+ int prefixLength = CallsManager.TELECOM_CALL_ID_PREFIX.length();
+ List<String> callIds = new ArrayList<>(sCallIdToInfo.keySet());
+ // Sort the analytics in increasing order of call IDs
+ try {
+ Collections.sort(callIds, (id1, id2) -> {
+ int i1, i2;
+ try {
+ i1 = Integer.valueOf(id1.substring(prefixLength));
+ } catch (NumberFormatException e) {
+ i1 = Integer.MAX_VALUE;
+ }
+
+ try {
+ i2 = Integer.valueOf(id2.substring(prefixLength));
+ } catch (NumberFormatException e) {
+ i2 = Integer.MAX_VALUE;
+ }
+ return i1 - i2;
+ });
+ } catch (IllegalArgumentException e) {
+ // do nothing, leave the list in a partially sorted state.
}
+
+ for (String callId : callIds) {
+ writer.printf("Call %s: ", callId);
+ writer.println(sCallIdToInfo.get(callId).toString());
+ }
+
+ Map<Integer, Double> averageTimings = SessionTiming.averageTimings(sSessionTimings);
+ averageTimings.entrySet().stream()
+ .filter(e -> sSessionIdToLogSession.containsKey(e.getKey()))
+ .forEach(e -> writer.printf("%s: %.2f\n",
+ sSessionIdToLogSession.get(e.getKey()), e.getValue()));
}
}
@@ -291,8 +626,9 @@
}
/**
- * Returns a deep copy of callIdToInfo that's safe to read/write without synchronization
+ * Returns a copy of callIdToInfo. Use only for testing.
*/
+ @VisibleForTesting
public static Map<String, CallInfoImpl> cloneData() {
synchronized (sLock) {
Map<String, CallInfoImpl> result = new HashMap<>(sCallIdToInfo.size());
@@ -302,4 +638,43 @@
return result;
}
}
+
+ private static TelecomLogClass.Event[] convertLogEventsToProtoEvents(
+ List<EventManager.Event> logEvents) {
+ long timeOfLastEvent = -1;
+ ArrayList<TelecomLogClass.Event> events = new ArrayList<>(logEvents.size());
+ for (EventManager.Event logEvent : logEvents) {
+ if (sLogEventToAnalyticsEvent.containsKey(logEvent.eventId)) {
+ TelecomLogClass.Event event = new TelecomLogClass.Event();
+ event.setEventName(sLogEventToAnalyticsEvent.get(logEvent.eventId));
+ event.setTimeSinceLastEventMillis(roundToOneSigFig(
+ timeOfLastEvent < 0 ? -1 : logEvent.time - timeOfLastEvent));
+ events.add(event);
+ timeOfLastEvent = logEvent.time;
+ }
+ }
+ return events.toArray(new TelecomLogClass.Event[events.size()]);
+ }
+
+ private static TelecomLogClass.EventTimingEntry logEventTimingToProtoEventTiming(
+ EventManager.EventRecord.EventTiming logEventTiming) {
+ int analyticsEventTimingName =
+ sLogEventTimingToAnalyticsEventTiming.containsKey(logEventTiming.name) ?
+ sLogEventTimingToAnalyticsEventTiming.get(logEventTiming.name) :
+ ParcelableCallAnalytics.EventTiming.INVALID;
+ return new TelecomLogClass.EventTimingEntry()
+ .setTimingName(analyticsEventTimingName)
+ .setTimeMillis(logEventTiming.time);
+ }
+
+ @VisibleForTesting
+ public static long roundToOneSigFig(long val) {
+ if (val == 0) {
+ return val;
+ }
+ int logVal = (int) Math.floor(Math.log10(val < 0 ? -val : val));
+ double s = Math.pow(10, logVal);
+ double dec = val / s;
+ return (long) (Math.round(dec) * s);
+ }
}
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index 31b2dc5..2173fa5 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -31,6 +31,7 @@
import android.telecom.Connection;
import android.telecom.Log;
import android.telecom.PhoneAccount;
+import android.telecom.VideoProfile;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -99,7 +100,7 @@
Log.i(TAG, "BT - answering call");
Call call = mCallsManager.getRingingCall();
if (call != null) {
- mCallsManager.answerCall(call, call.getVideoState());
+ mCallsManager.answerCall(call, VideoProfile.STATE_AUDIO_ONLY);
return true;
}
return false;
@@ -292,11 +293,17 @@
public CallsManagerListener mCallsManagerListener = new CallsManagerListenerBase() {
@Override
public void onCallAdded(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
updateHeadsetWithCallState(false /* force */);
}
@Override
public void onCallRemoved(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
mClccIndexMap.remove(call);
updateHeadsetWithCallState(false /* force */);
}
@@ -319,6 +326,9 @@
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
+ if (call.isExternalCall()) {
+ return;
+ }
// If a call is being put on hold because of a new connecting call, ignore the
// CONNECTING since the BT state update needs to send out the numHeld = 1 + dialing
// state atomically.
@@ -336,7 +346,8 @@
// state. We can assume that the active call will be automatically held which will
// send another update at which point we will be in the right state.
if (mCallsManager.getActiveCall() != null
- && oldState == CallState.CONNECTING && newState == CallState.DIALING) {
+ && oldState == CallState.CONNECTING &&
+ (newState == CallState.DIALING || newState == CallState.PULLING)) {
return;
}
updateHeadsetWithCallState(false /* force */);
@@ -344,6 +355,9 @@
@Override
public void onIsConferencedChanged(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
/*
* Filter certain onIsConferencedChanged callbacks. Unfortunately this needs to be done
* because conference change events are not atomic and multiple callbacks get fired
@@ -488,6 +502,12 @@
return false;
if (activeCall != null) {
mCallsManager.disconnectCall(activeCall);
+ if (ringingCall != null) {
+ mCallsManager.answerCall(ringingCall, VideoProfile.STATE_AUDIO_ONLY);
+ } else if (heldCall != null) {
+ mCallsManager.unholdCall(heldCall);
+ }
+ return true;
}
if (ringingCall != null) {
mCallsManager.answerCall(ringingCall, ringingCall.getVideoState());
@@ -502,7 +522,7 @@
updateHeadsetWithCallState(true /* force */);
return true;
} else if (ringingCall != null) {
- mCallsManager.answerCall(ringingCall, ringingCall.getVideoState());
+ mCallsManager.answerCall(ringingCall, VideoProfile.STATE_AUDIO_ONLY);
return true;
} else if (heldCall != null) {
// CallsManager will hold any active calls when unhold() is called on a
@@ -812,6 +832,7 @@
case CallState.CONNECTING:
case CallState.SELECT_PHONE_ACCOUNT:
case CallState.DIALING:
+ case CallState.PULLING:
// Yes, this is correctly returning ALERTING.
// "Dialing" for BT means that we have sent information to the service provider
// to place the call but there is no confirmation that the call is going through.
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 2012231..b9b2fda 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -107,7 +107,7 @@
void onExtrasRemoved(Call c, int source, List<String> keys);
void onHandleChanged(Call call);
void onCallerDisplayNameChanged(Call call);
- void onVideoStateChanged(Call call);
+ void onVideoStateChanged(Call call, int previousVideoState, int newVideoState);
void onTargetPhoneAccountChanged(Call call);
void onConnectionManagerPhoneAccountChanged(Call call);
void onPhoneAccountChanged(Call call);
@@ -164,7 +164,7 @@
@Override
public void onCallerDisplayNameChanged(Call call) {}
@Override
- public void onVideoStateChanged(Call call) {}
+ public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {}
@Override
public void onTargetPhoneAccountChanged(Call call) {}
@Override
@@ -439,8 +439,6 @@
|| callDirection == CALL_DIRECTION_INCOMING;
maybeLoadCannedSmsResponses();
mAnalytics = new Analytics.CallInfo();
-
- Log.addEvent(this, LogUtils.Events.CREATED);
}
/**
@@ -512,6 +510,7 @@
analyticsDirection = Analytics.UNKNOWN_DIRECTION;
}
mAnalytics = Analytics.initiateCallAnalytics(mId, analyticsDirection);
+ Log.addEvent(this, LogUtils.Events.CREATED);
}
public Analytics.CallInfo getAnalytics() {
@@ -595,6 +594,11 @@
return false;
}
+ // Only Redial a Call in the case of it being an Emergency Call.
+ if(!isEmergencyCall()) {
+ return false;
+ }
+
// Make sure that there are additional connection services to process.
if (mCreateConnectionProcessor == null
|| !mCreateConnectionProcessor.isProcessingComplete()
@@ -695,6 +699,9 @@
case CallState.DIALING:
event = LogUtils.Events.SET_DIALING;
break;
+ case CallState.PULLING:
+ event = LogUtils.Events.SET_PULLING;
+ break;
case CallState.DISCONNECTED:
event = LogUtils.Events.SET_DISCONNECTED;
data = getDisconnectCause();
@@ -1023,10 +1030,18 @@
connectionCapabilities = removeVideoCapabilities(connectionCapabilities);
}
+ int previousCapabilities = mConnectionCapabilities;
mConnectionCapabilities = connectionCapabilities;
for (Listener l : mListeners) {
l.onConnectionCapabilitiesChanged(this);
}
+
+ int xorCaps = previousCapabilities ^ mConnectionCapabilities;
+ Log.addEvent(this, LogUtils.Events.CAPABILITY_CHANGE,
+ "Current: [%s], Removed [%s], Added [%s]",
+ Connection.capabilitiesToStringShort(mConnectionCapabilities),
+ Connection.capabilitiesToStringShort(previousCapabilities & xorCaps),
+ Connection.capabilitiesToStringShort(mConnectionCapabilities & xorCaps));
}
}
@@ -1047,12 +1062,21 @@
if (wasExternal != isExternal) {
Log.v(this, "setConnectionProperties: external call changed isExternal = %b",
isExternal);
-
+ Log.addEvent(this, LogUtils.Events.IS_EXTERNAL, isExternal);
for (Listener l : mListeners) {
l.onExternalCallChanged(this, isExternal);
}
}
+
+ mAnalytics.addCallProperties(mConnectionProperties);
+
+ int xorProps = previousProperties ^ mConnectionProperties;
+ Log.addEvent(this, LogUtils.Events.PROPERTY_CHANGE,
+ "Current: [%s], Removed [%s], Added [%s]",
+ Connection.propertiesToStringShort(mConnectionProperties),
+ Connection.propertiesToStringShort(previousProperties & xorProps),
+ Connection.propertiesToStringShort(mConnectionProperties & xorProps));
}
}
@@ -1323,16 +1347,24 @@
*/
@VisibleForTesting
public void answer(int videoState) {
- Preconditions.checkNotNull(mConnectionService);
-
// Check to verify that the call is still in the ringing state. A call can change states
// between the time the user hits 'answer' and Telecom receives the command.
if (isRinging("answer")) {
+ if (!isVideoCallingSupported() && VideoProfile.isVideo(videoState)) {
+ // Video calling is not supported, yet the InCallService is attempting to answer as
+ // video. We will simply answer as audio-only.
+ videoState = VideoProfile.STATE_AUDIO_ONLY;
+ }
// At this point, we are asking the connection service to answer but we don't assume
// that it will work. Instead, we wait until confirmation from the connectino service
// that the call is in a non-STATE_RINGING state before changing the UI. See
// {@link ConnectionServiceAdapter#setActive} and other set* methods.
- mConnectionService.answer(this, videoState);
+ if (mConnectionService != null) {
+ mConnectionService.answer(this, videoState);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "answer call failed due to null CS callId=%s", getId());
+ }
Log.addEvent(this, LogUtils.Events.REQUEST_ACCEPT);
}
}
@@ -1345,15 +1377,18 @@
*/
@VisibleForTesting
public void reject(boolean rejectWithMessage, String textMessage) {
- Preconditions.checkNotNull(mConnectionService);
-
// Check to verify that the call is still in the ringing state. A call can change states
// between the time the user hits 'reject' and Telecomm receives the command.
if (isRinging("reject")) {
// Ensure video state history tracks video state at time of rejection.
mVideoStateHistory |= mVideoState;
- mConnectionService.reject(this, rejectWithMessage, textMessage);
+ if (mConnectionService != null) {
+ mConnectionService.reject(this, rejectWithMessage, textMessage);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "reject call failed due to null CS callId=%s", getId());
+ }
Log.addEvent(this, LogUtils.Events.REQUEST_REJECT);
}
}
@@ -1362,10 +1397,13 @@
* Puts the call on hold if it is currently active.
*/
void hold() {
- Preconditions.checkNotNull(mConnectionService);
-
if (mState == CallState.ACTIVE) {
- mConnectionService.hold(this);
+ if (mConnectionService != null) {
+ mConnectionService.hold(this);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "hold call failed due to null CS callId=%s", getId());
+ }
Log.addEvent(this, LogUtils.Events.REQUEST_HOLD);
}
}
@@ -1374,10 +1412,13 @@
* Releases the call from hold if it is currently active.
*/
void unhold() {
- Preconditions.checkNotNull(mConnectionService);
-
if (mState == CallState.ON_HOLD) {
- mConnectionService.unhold(this);
+ if (mConnectionService != null) {
+ mConnectionService.unhold(this);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "unhold call failed due to null CS callId=%s", getId());
+ }
Log.addEvent(this, LogUtils.Events.REQUEST_UNHOLD);
}
}
@@ -1431,7 +1472,12 @@
// If the change originated from an InCallService, notify the connection service.
if (source == SOURCE_INCALL_SERVICE) {
- mConnectionService.onExtrasChanged(this, mExtras);
+ if (mConnectionService != null) {
+ mConnectionService.onExtrasChanged(this, mExtras);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "putExtras failed due to null CS callId=%s", getId());
+ }
}
}
@@ -1461,7 +1507,12 @@
// If the change originated from an InCallService, notify the connection service.
if (source == SOURCE_INCALL_SERVICE) {
- mConnectionService.onExtrasChanged(this, mExtras);
+ if (mConnectionService != null) {
+ mConnectionService.onExtrasChanged(this, mExtras);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "removeExtras failed due to null CS callId=%s", getId());
+ }
}
}
@@ -1502,7 +1553,12 @@
}
void postDialContinue(boolean proceed) {
- mConnectionService.onPostDialContinue(this, proceed);
+ if (mConnectionService != null) {
+ mConnectionService.onPostDialContinue(this, proceed);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "postDialContinue failed due to null CS callId=%s", getId());
+ }
}
void conferenceWith(Call otherCall) {
@@ -1566,7 +1622,7 @@
* {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
* <p>
* An external call is a representation of a call which is taking place on another device
- * associated with a PhoneAccount on this device. Issuing a request to pull the external call
+ * associated with a PhoneAccount on this device. Issuing a request to pull the external call
* tells the {@link android.telecom.ConnectionService} that it should move the call from the
* other device to this one. An example of this is the IMS multi-endpoint functionality. A
* user may have two phones with the same phone number. If the user is engaged in an active
@@ -1604,7 +1660,12 @@
* @param extras Associated extras.
*/
public void sendCallEvent(String event, Bundle extras) {
- mConnectionService.sendCallEvent(this, event, extras);
+ if (mConnectionService != null) {
+ mConnectionService.sendCallEvent(this, event, extras);
+ } else {
+ Log.e(this, new NullPointerException(),
+ "sendCallEvent failed due to null CS callId=%s", getId());
+ }
}
void setParentCall(Call parentCall) {
@@ -1786,7 +1847,10 @@
*/
private void setCallerInfo(Uri handle, CallerInfo callerInfo) {
Trace.beginSection("setCallerInfo");
- Preconditions.checkNotNull(callerInfo);
+ if (callerInfo == null) {
+ Log.i(this, "CallerInfo lookup returned null, skipping update");
+ return;
+ }
if (!handle.equals(mHandle)) {
Log.i(this, "setCallerInfo received stale caller info for an old handle. Ignoring.");
@@ -1925,6 +1989,12 @@
* @param videoState The video state for the call.
*/
public void setVideoState(int videoState) {
+ // If the phone account associated with this call does not support video calling, then we
+ // will automatically set the video state to audio-only.
+ if (!isVideoCallingSupported()) {
+ videoState = VideoProfile.STATE_AUDIO_ONLY;
+ }
+
// Track which video states were applicable over the duration of the call.
// Only track the call state when the call is active or disconnected. This ensures we do
// not include the video state when:
@@ -1936,9 +2006,18 @@
mVideoStateHistory = mVideoStateHistory | videoState;
}
+ int previousVideoState = mVideoState;
mVideoState = videoState;
- for (Listener l : mListeners) {
- l.onVideoStateChanged(this);
+ if (mVideoState != previousVideoState) {
+ Log.addEvent(this, LogUtils.Events.VIDEO_STATE_CHANGED,
+ VideoProfile.videoStateToString(videoState));
+ for (Listener l : mListeners) {
+ l.onVideoStateChanged(this, previousVideoState, mVideoState);
+ }
+ }
+
+ if (VideoProfile.isVideo(videoState)) {
+ mAnalytics.setCallIsVideo(true);
}
}
@@ -2010,6 +2089,8 @@
return CallState.ACTIVE;
case Connection.STATE_DIALING:
return CallState.DIALING;
+ case Connection.STATE_PULLING_CALL:
+ return CallState.PULLING;
case Connection.STATE_DISCONNECTED:
return CallState.DISCONNECTED;
case Connection.STATE_HOLDING:
@@ -2086,6 +2167,7 @@
* @param extras The extras.
*/
public void onConnectionEvent(String event, Bundle extras) {
+ Log.addEvent(this, LogUtils.Events.CONNECTION_EVENT, event);
if (Connection.EVENT_ON_HOLD_TONE_START.equals(event)) {
mIsRemotelyHeld = true;
Log.addEvent(this, LogUtils.Events.REMOTELY_HELD);
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index a0d4781..4a35acc 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -73,6 +73,7 @@
put(CallState.CONNECTING, mActiveDialingOrConnectingCalls);
put(CallState.ACTIVE, mActiveDialingOrConnectingCalls);
put(CallState.DIALING, mActiveDialingOrConnectingCalls);
+ put(CallState.PULLING, mActiveDialingOrConnectingCalls);
put(CallState.RINGING, mRingingCalls);
put(CallState.ON_HOLD, mHoldingCalls);
}};
@@ -106,7 +107,7 @@
}
updateForegroundCall();
- if (newState == CallState.DISCONNECTED) {
+ if (shouldPlayDisconnectTone(oldState, newState)) {
playToneForDisconnectedCall(call);
}
@@ -178,12 +179,20 @@
*/
@Override
public void onExternalCallChanged(Call call, boolean isExternalCall) {
- if (isExternalCall) {
+ if (isExternalCall) {
Log.d(LOG_TAG, "Removing call which became external ID %s", call.getId());
removeCall(call);
} else if (!isExternalCall) {
Log.d(LOG_TAG, "Adding external call which was pulled with ID %s", call.getId());
addCall(call);
+
+ if (mCallsManager.isSpeakerphoneAutoEnabledForVideoCalls(call.getVideoState())) {
+ // 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(
+ CallAudioRouteStateMachine.SWITCH_SPEAKER);
+ }
}
}
@@ -315,6 +324,25 @@
CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);
}
+ @Override
+ public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
+ if (call != getForegroundCall()) {
+ Log.d(LOG_TAG, "Ignoring video state change from %s to %s for call %s -- not " +
+ "foreground.", VideoProfile.videoStateToString(previousVideoState),
+ VideoProfile.videoStateToString(newVideoState), call.getId());
+ return;
+ }
+
+ if (!VideoProfile.isVideo(previousVideoState) &&
+ mCallsManager.isSpeakerphoneAutoEnabledForVideoCalls(newVideoState)) {
+ 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(
+ CallAudioRouteStateMachine.SWITCH_SPEAKER);
+ }
+ }
+
public CallAudioState getCallAudioState() {
return mCallAudioRouteStateMachine.getCurrentCallAudioState();
}
@@ -395,8 +423,8 @@
}
@VisibleForTesting
- public void startRinging() {
- mRinger.startRinging(mForegroundCall);
+ public boolean startRinging() {
+ return mRinger.startRinging(mForegroundCall);
}
@VisibleForTesting
@@ -476,9 +504,13 @@
case CallState.ON_HOLD:
onCallLeavingHold();
break;
+ case CallState.PULLING:
+ onCallLeavingActiveDialingOrConnecting();
+ break;
case CallState.DIALING:
stopRingbackForCall(call);
onCallLeavingActiveDialingOrConnecting();
+ break;
}
}
@@ -494,6 +526,9 @@
case CallState.ON_HOLD:
onCallEnteringHold();
break;
+ case CallState.PULLING:
+ onCallEnteringActiveDialingOrConnecting();
+ break;
case CallState.DIALING:
onCallEnteringActiveDialingOrConnecting();
playRingbackForCall(call);
@@ -649,7 +684,7 @@
if (shouldPlayHoldTone()) {
if (mHoldTonePlayer == null) {
mHoldTonePlayer = mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
- mHoldTonePlayer.start();
+ mHoldTonePlayer.startTone();
}
} else {
if (mHoldTonePlayer != null) {
@@ -703,6 +738,15 @@
}
}
+ private boolean shouldPlayDisconnectTone(int oldState, int newState) {
+ if (newState != CallState.DISCONNECTED) {
+ return false;
+ }
+ return oldState == CallState.ACTIVE ||
+ oldState == CallState.DIALING ||
+ oldState == CallState.ON_HOLD;
+ }
+
@VisibleForTesting
public Set<Call> getTrackedCalls() {
return mCalls;
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index 2e3c5bd..7121a53 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -204,19 +204,22 @@
@Override
public void enter() {
Log.i(LOG_TAG, "Audio focus entering RINGING state");
- mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- if (mMostRecentMode == AudioManager.MODE_IN_CALL) {
- // Preserving behavior from the old CallAudioManager.
- Log.i(LOG_TAG, "Transition from IN_CALL -> RINGTONE."
- + " Resetting to NORMAL first.");
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ if (mCallAudioManager.startRinging()) {
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ if (mMostRecentMode == AudioManager.MODE_IN_CALL) {
+ // Preserving behavior from the old CallAudioManager.
+ Log.i(LOG_TAG, "Transition from IN_CALL -> RINGTONE."
+ + " Resetting to NORMAL first.");
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ }
+ mAudioManager.setMode(AudioManager.MODE_RINGTONE);
+ mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS);
+ } else {
+ Log.i(LOG_TAG, "Entering RINGING but not acquiring focus -- silent ringtone");
}
- mAudioManager.setMode(AudioManager.MODE_RINGTONE);
mCallAudioManager.stopCallWaiting();
- mCallAudioManager.startRinging();
- mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS);
}
@Override
@@ -528,4 +531,4 @@
return mUnfocusedState;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index e3d459c..28b3ec5 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -18,7 +18,11 @@
import android.app.ActivityManagerNative;
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.IAudioService;
@@ -110,6 +114,13 @@
public static final int ACTIVE_FOCUS = 2;
public static final int RINGING_FOCUS = 3;
+ private static final SparseArray<String> AUDIO_ROUTE_TO_LOG_EVENT = new SparseArray<String>() {{
+ put(CallAudioState.ROUTE_BLUETOOTH, LogUtils.Events.AUDIO_ROUTE_BT);
+ put(CallAudioState.ROUTE_EARPIECE, LogUtils.Events.AUDIO_ROUTE_EARPIECE);
+ put(CallAudioState.ROUTE_SPEAKER, LogUtils.Events.AUDIO_ROUTE_SPEAKER);
+ put(CallAudioState.ROUTE_WIRED_HEADSET, LogUtils.Events.AUDIO_ROUTE_HEADSET);
+ }};
+
private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
put(CONNECT_WIRED_HEADSET, "CONNECT_WIRED_HEADSET");
put(DISCONNECT_WIRED_HEADSET, "DISCONNECT_WIRED_HEADSET");
@@ -142,6 +153,34 @@
put(RUN_RUNNABLE, "RUN_RUNNABLE");
}};
+ /**
+ * BroadcastReceiver used to track changes in the notification interruption filter. This
+ * ensures changes to the notification interruption filter made by the user during a call are
+ * respected when restoring the notification interruption filter state.
+ */
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.startSession("CARSM.oR");
+ try {
+ String action = intent.getAction();
+
+ if (action.equals(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)) {
+ if (mAreNotificationSuppressed) {
+ // If we've already set the interruption filter, and the user changes it to
+ // something other than INTERRUPTION_FILTER_ALARMS, assume we will no longer
+ // try to change it back if the audio route changes.
+ mAreNotificationSuppressed =
+ mInterruptionFilterProxy.getCurrentInterruptionFilter()
+ == NotificationManager.INTERRUPTION_FILTER_ALARMS;
+ }
+ }
+ } finally {
+ Log.endSession();
+ }
+ }
+ };
+
private static final String ACTIVE_EARPIECE_ROUTE_NAME = "ActiveEarpieceRoute";
private static final String ACTIVE_BLUETOOTH_ROUTE_NAME = "ActiveBluetoothRoute";
private static final String ACTIVE_SPEAKER_ROUTE_NAME = "ActiveSpeakerRoute";
@@ -245,6 +284,9 @@
super.enter();
setSpeakerphoneOn(false);
setBluetoothOn(false);
+ if (mAudioFocusType == ACTIVE_FOCUS) {
+ setNotificationsSuppressed(true);
+ }
CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_EARPIECE,
mAvailableRoutes);
setSystemAudioState(newState);
@@ -252,6 +294,12 @@
}
@Override
+ public void exit() {
+ super.exit();
+ setNotificationsSuppressed(false);
+ }
+
+ @Override
public void updateSystemAudioState() {
updateInternalCallAudioState();
setSystemAudioState(mCurrentCallAudioState);
@@ -289,6 +337,10 @@
transitionTo(mActiveSpeakerRoute);
return HANDLED;
case SWITCH_FOCUS:
+ if (msg.arg1 == ACTIVE_FOCUS) {
+ setNotificationsSuppressed(true);
+ }
+
if (msg.arg1 == NO_FOCUS) {
reinitialize();
}
@@ -1066,6 +1118,7 @@
private int mAudioFocusType;
private boolean mWasOnSpeaker;
private boolean mIsMuted;
+ private boolean mAreNotificationSuppressed = false;
private final Context mContext;
private final CallsManager mCallsManager;
@@ -1074,6 +1127,7 @@
private final WiredHeadsetManager mWiredHeadsetManager;
private final StatusBarNotifier mStatusBarNotifier;
private final CallAudioManager.AudioServiceFactory mAudioServiceFactory;
+ private final InterruptionFilterProxy mInterruptionFilterProxy;
private final boolean mDoesDeviceSupportEarpieceRoute;
private final TelecomSystem.SyncRoot mLock;
private boolean mHasUserExplicitlyLeftBluetooth = false;
@@ -1093,6 +1147,7 @@
WiredHeadsetManager wiredHeadsetManager,
StatusBarNotifier statusBarNotifier,
CallAudioManager.AudioServiceFactory audioServiceFactory,
+ InterruptionFilterProxy interruptionFilterProxy,
boolean doesDeviceSupportEarpieceRoute) {
super(NAME);
addState(mActiveEarpieceRoute);
@@ -1112,6 +1167,11 @@
mWiredHeadsetManager = wiredHeadsetManager;
mStatusBarNotifier = statusBarNotifier;
mAudioServiceFactory = audioServiceFactory;
+ mInterruptionFilterProxy = interruptionFilterProxy;
+ // Register for misc other intent broadcasts.
+ IntentFilter intentFilter =
+ new IntentFilter(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+ context.registerReceiver(mReceiver, intentFilter);
mDoesDeviceSupportEarpieceRoute = doesDeviceSupportEarpieceRoute;
mLock = callsManager.getLock();
@@ -1219,10 +1279,54 @@
quitNow();
}
+ /**
+ * Sets whether notifications should be suppressed or not. Used when in a call to ensure the
+ * device will not vibrate due to notifications.
+ * Alarm-only filtering is activated when
+ *
+ * @param on {@code true} when notification suppression should be activated, {@code false} when
+ * it should be deactivated.
+ */
+ private void setNotificationsSuppressed(boolean on) {
+ if (mInterruptionFilterProxy == null) {
+ return;
+ }
+
+ Log.i(this, "setNotificationsSuppressed: on=%s; suppressed=%s", (on ? "yes" : "no"),
+ (mAreNotificationSuppressed ? "yes" : "no"));
+ if (on) {
+ if (!mAreNotificationSuppressed) {
+ // Enabling suppression of notifications.
+ int interruptionFilter = mInterruptionFilterProxy.getCurrentInterruptionFilter();
+ if (interruptionFilter == NotificationManager.INTERRUPTION_FILTER_ALL) {
+ // No interruption filter is specified, so suppress notifications by setting the
+ // current filter to alarms-only.
+ mAreNotificationSuppressed = true;
+ mInterruptionFilterProxy.setInterruptionFilter(
+ NotificationManager.INTERRUPTION_FILTER_ALARMS);
+ } else {
+ // Interruption filter is already chosen by the user, so do not attempt to change
+ // it.
+ mAreNotificationSuppressed = false;
+ }
+ }
+ } else {
+ // Disabling suppression of notifications.
+ if (mAreNotificationSuppressed) {
+ // We have implemented the alarms-only policy and the user has not changed it since
+ // we originally set it, so reset the notification filter.
+ mInterruptionFilterProxy.setInterruptionFilter(
+ NotificationManager.INTERRUPTION_FILTER_ALL);
+ }
+ mAreNotificationSuppressed = false;
+ }
+ }
+
private void setSpeakerphoneOn(boolean on) {
if (mAudioManager.isSpeakerphoneOn() != on) {
Log.i(this, "turning speaker phone %s", on);
mAudioManager.setSpeakerphoneOn(on);
+ mStatusBarNotifier.notifySpeakerphone(on);
}
}
@@ -1242,8 +1346,8 @@
private void setMuteOn(boolean mute) {
mIsMuted = mute;
- Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.MUTE,
- mute ? "on" : "off");
+ Log.addEvent(mCallsManager.getForegroundCall(), mute ? LogUtils.Events.MUTE : LogUtils.Events.UNMUTE);
+
if (mute != mAudioManager.isMicrophoneMute() && isInActiveState()) {
IAudioService audio = mAudioServiceFactory.getAudioService();
Log.i(this, "changing microphone mute state to: %b [serviceIsNull=%b]",
@@ -1257,6 +1361,7 @@
// user and not the current foreground, which we want to avoid.
audio.setMicrophoneMute(
mute, mContext.getOpPackageName(), getCurrentUserId());
+ mStatusBarNotifier.notifyMute(mute);
} catch (RemoteException e) {
Log.e(this, e, "Remote exception while toggling mute.");
@@ -1298,8 +1403,9 @@
newCallAudioState);
if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) {
if (newCallAudioState.getRoute() != mLastKnownCallAudioState.getRoute()) {
- Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
- CallAudioState.audioRouteToString(newCallAudioState.getRoute()));
+ Log.addEvent(mCallsManager.getForegroundCall(),
+ AUDIO_ROUTE_TO_LOG_EVENT.get(newCallAudioState.getRoute(),
+ LogUtils.Events.AUDIO_ROUTE));
}
mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState);
@@ -1424,6 +1530,7 @@
setMuteOn(mIsMuted);
mWasOnSpeaker = false;
mHasUserExplicitlyLeftBluetooth = false;
+ mLastKnownCallAudioState = initState;
transitionTo(mRouteCodeToQuiescentState.get(initState.getRoute()));
}
}
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 5fc7062..d89f54a 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -145,10 +145,12 @@
// 1) It was not in the "choose account" phase when disconnected
// 2) It is a conference call
// 3) Call was not explicitly canceled
+ // 4) Call is not an external call
if (isNewlyDisconnected &&
(oldState != CallState.SELECT_PHONE_ACCOUNT &&
!call.isConference() &&
- !isCallCanceled)) {
+ !isCallCanceled) &&
+ !call.isExternalCall()) {
int type;
if (!call.isIncoming()) {
type = Calls.OUTGOING_TYPE;
@@ -215,7 +217,8 @@
Long callDataUsage = call.getCallDataUsage() == Call.DATA_USAGE_NOT_SET ? null :
call.getCallDataUsage();
- int callFeatures = getCallFeatures(call.getVideoStateHistory());
+ int callFeatures = getCallFeatures(call.getVideoStateHistory(),
+ call.getDisconnectCause().getCode() == DisconnectCause.CALL_PULLED);
logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(),
@@ -288,13 +291,18 @@
* Based on the video state of the call, determines the call features applicable for the call.
*
* @param videoState The video state.
+ * @param isPulledCall {@code true} if this call was pulled to another device.
* @return The call features.
*/
- private static int getCallFeatures(int videoState) {
+ private static int getCallFeatures(int videoState, boolean isPulledCall) {
+ int features = 0;
if (VideoProfile.isVideo(videoState)) {
- return Calls.FEATURES_VIDEO;
+ features |= Calls.FEATURES_VIDEO;
}
- return 0;
+ if (isPulledCall) {
+ features |= Calls.FEATURES_PULLED_EXTERNALLY;
+ }
+ return features;
}
/**
diff --git a/src/com/android/server/telecom/CallState.java b/src/com/android/server/telecom/CallState.java
index 0d2ca48..0aa928f 100644
--- a/src/com/android/server/telecom/CallState.java
+++ b/src/com/android/server/telecom/CallState.java
@@ -103,6 +103,15 @@
*/
public static final int DISCONNECTING = 9;
+ /**
+ * Indicates that the call is in the process of being pulled to the local device.
+ * <p>
+ * This state should only be set on a call with
+ * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL} and
+ * {@link android.telecom.Connection#CAPABILITY_CAN_PULL_CALL}.
+ */
+ public static final int PULLING = 10;
+
public static String toString(int callState) {
switch (callState) {
case NEW:
@@ -125,6 +134,8 @@
return "ABORTED";
case DISCONNECTING:
return "DISCONNECTING";
+ case PULLING:
+ return "PULLING";
default:
return "UNKNOWN";
}
diff --git a/src/com/android/server/telecom/CallerInfoLookupHelper.java b/src/com/android/server/telecom/CallerInfoLookupHelper.java
index 61b7f21..f67a7f7 100644
--- a/src/com/android/server/telecom/CallerInfoLookupHelper.java
+++ b/src/com/android/server/telecom/CallerInfoLookupHelper.java
@@ -16,6 +16,7 @@
package com.android.server.telecom;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
@@ -44,7 +45,7 @@
* @param info
* @return true if the value should be cached, false otherwise.
*/
- void onCallerInfoQueryComplete(Uri handle, CallerInfo info);
+ void onCallerInfoQueryComplete(Uri handle, @Nullable CallerInfo info);
void onContactPhotoQueryComplete(Uri handle, CallerInfo info);
}
@@ -57,6 +58,7 @@
listeners = new LinkedList<>();
}
}
+
private final Map<Uri, CallerInfoQueryInfo> mQueryEntries = new HashMap<>();
private final CallerInfoAsyncQueryFactory mCallerInfoAsyncQueryFactory;
@@ -77,11 +79,13 @@
public void startLookup(final Uri handle, OnQueryCompleteListener listener) {
if (handle == null) {
+ listener.onCallerInfoQueryComplete(handle, null);
return;
}
final String number = handle.getSchemeSpecificPart();
if (TextUtils.isEmpty(number)) {
+ listener.onCallerInfoQueryComplete(handle, null);
return;
}
@@ -96,7 +100,7 @@
info.callerInfo.cachedPhotoIcon != null)) {
listener.onContactPhotoQueryComplete(handle, info.callerInfo);
} else if (info.imageQueryPending) {
- Log.i(this, "There is a previously incomplete query for handle %s. " +
+ Log.i(this, "There is a pending photo query for handle %s. " +
"Adding to listeners for this query.", Log.piiHandle(handle));
info.listeners.add(listener);
}
@@ -140,11 +144,15 @@
Log.continueSession((Session) cookie, "CILH.oQC");
try {
if (mQueryEntries.containsKey(handle)) {
+ Log.i(CallerInfoLookupHelper.this, "CI query for handle %s has completed;" +
+ " notifying all listeners.", Log.piiHandle(handle));
CallerInfoQueryInfo info = mQueryEntries.get(handle);
for (OnQueryCompleteListener l : info.listeners) {
l.onCallerInfoQueryComplete(handle, ci);
}
if (ci.contactDisplayPhotoUri == null) {
+ Log.i(CallerInfoLookupHelper.this, "There is no photo for this " +
+ "contact, skipping photo query");
mQueryEntries.remove(handle);
} else {
info.callerInfo = ci;
@@ -153,7 +161,7 @@
}
} else {
Log.i(CallerInfoLookupHelper.this, "CI query for handle %s has completed," +
- " but there are no listeners left.", handle);
+ " but there are no listeners left.", Log.piiHandle(handle));
}
} finally {
Log.endSession();
@@ -190,6 +198,7 @@
if (info.callerInfo == null) {
Log.w(CallerInfoLookupHelper.this, "Photo query finished, but the " +
"CallerInfo object previously looked up was not cached.");
+ mQueryEntries.remove(handle);
return;
}
info.callerInfo.cachedPhoto = photo;
@@ -200,7 +209,8 @@
mQueryEntries.remove(handle);
} else {
Log.i(CallerInfoLookupHelper.this, "Photo query for handle %s has" +
- " completed, but there are no listeners left.", handle);
+ " completed, but there are no listeners left.",
+ Log.piiHandle(handle));
}
} finally {
Log.endSession();
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index d089ee7..b5c99bc 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -17,6 +17,7 @@
package com.android.server.telecom;
import android.app.ActivityManager;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.Intent;
@@ -71,6 +72,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -104,7 +106,7 @@
void onRingbackRequested(Call call, boolean ringback);
void onIsConferencedChanged(Call call);
void onIsVoipAudioModeChanged(Call call);
- void onVideoStateChanged(Call call);
+ void onVideoStateChanged(Call call, int previousVideoState, int newVideoState);
void onCanAddCallChanged(boolean canAddCall);
void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
void onHoldToneRequested(Call call);
@@ -121,11 +123,13 @@
private static final int MAXIMUM_TOP_LEVEL_CALLS = 2;
private static final int[] OUTGOING_CALL_STATES =
- {CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING};
+ {CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING,
+ CallState.PULLING};
private static final int[] LIVE_CALL_STATES =
{CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING,
- CallState.ACTIVE};
+ CallState.PULLING, CallState.ACTIVE};
+
public static final String TELECOM_CALL_ID_PREFIX = "TC@";
// Maps call technologies in PhoneConstants to those in Analytics.
@@ -192,6 +196,7 @@
private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
private final Timeouts.Adapter mTimeoutsAdapter;
private final PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
+ private final NotificationManager mNotificationManager;
private final Set<Call> mLocallyDisconnectingCalls = new HashSet<>();
private final Set<Call> mPendingCallsToDisconnect = new HashSet<>();
/* Handler tied to thread in which CallManager was initialized. */
@@ -223,7 +228,8 @@
DefaultDialerManagerAdapter defaultDialerAdapter,
Timeouts.Adapter timeoutsAdapter,
AsyncRingtonePlayer asyncRingtonePlayer,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter) {
+ PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
+ InterruptionFilterProxy interruptionFilterProxy) {
mContext = context;
mLock = lock;
mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
@@ -241,6 +247,8 @@
mContactsAsyncHelper, mLock);
mDtmfLocalTonePlayer = new DtmfLocalTonePlayer();
+ mNotificationManager = (NotificationManager) context.getSystemService(
+ Context.NOTIFICATION_SERVICE);
CallAudioRouteStateMachine callAudioRouteStateMachine = new CallAudioRouteStateMachine(
context,
this,
@@ -248,6 +256,7 @@
wiredHeadsetManager,
statusBarNotifier,
audioServiceFactory,
+ interruptionFilterProxy,
CallAudioRouteStateMachine.doesDeviceSupportEarpieceRoute()
);
callAudioRouteStateMachine.initialize();
@@ -266,7 +275,7 @@
RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context);
SystemVibrator systemVibrator = new SystemVibrator(context);
mInCallController = new InCallController(
- context, mLock, this, systemStateProvider, defaultDialerAdapter);
+ context, mLock, this, systemStateProvider, defaultDialerAdapter, mTimeoutsAdapter);
mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
ringtoneFactory, systemVibrator, mInCallController);
@@ -347,6 +356,12 @@
@Override
public void onSuccessfulIncomingCall(Call incomingCall) {
Log.d(this, "onSuccessfulIncomingCall");
+ if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE)) {
+ Log.i(this, "Skipping call filtering due to ECBM");
+ onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
+ return;
+ }
+
List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
@@ -368,6 +383,7 @@
result.shouldAllowCall ? "successful incoming call" : "blocking call");
} else {
Log.i(this, "onCallFilteringCompleted: call already disconnected.");
+ return;
}
if (result.shouldAllowCall) {
@@ -473,7 +489,7 @@
@Override
public void onParentChanged(Call call) {
// parent-child relationship affects which call should be foreground, so do an update.
- updateCallsManagerState();
+ updateCanAddCall();
for (CallsManagerListener listener : mListeners) {
listener.onIsConferencedChanged(call);
}
@@ -482,7 +498,7 @@
@Override
public void onChildrenChanged(Call call) {
// parent-child relationship affects which call should be foreground, so do an update.
- updateCallsManagerState();
+ updateCanAddCall();
for (CallsManagerListener listener : mListeners) {
listener.onIsConferencedChanged(call);
}
@@ -496,9 +512,9 @@
}
@Override
- public void onVideoStateChanged(Call call) {
+ public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
for (CallsManagerListener listener : mListeners) {
- listener.onVideoStateChanged(call);
+ listener.onVideoStateChanged(call, previousVideoState, newVideoState);
}
}
@@ -625,7 +641,8 @@
return false;
}
- CallAudioState getAudioState() {
+ @VisibleForTesting
+ public CallAudioState getAudioState() {
return mCallAudioManager.getCallAudioState();
}
@@ -737,9 +754,10 @@
// Check to see if we can reuse any of the calls that are waiting to disconnect.
// See {@link Call#abort} and {@link #onCanceledViaNewOutgoingCall} for more information.
Call reusedCall = null;
- for (Call pendingCall : mPendingCallsToDisconnect) {
+ for (Iterator<Call> callIter = mPendingCallsToDisconnect.iterator(); callIter.hasNext();) {
+ Call pendingCall = callIter.next();
if (reusedCall == null && areHandlesEqual(pendingCall.getHandle(), handle)) {
- mPendingCallsToDisconnect.remove(pendingCall);
+ callIter.remove();
Log.i(this, "Reusing disconnected call %s", pendingCall);
reusedCall = pendingCall;
} else {
@@ -783,10 +801,10 @@
false /* forceAttachToExistingConnection */,
false /* isConference */
);
- call.setInitiatingUser(initiatingUser);
-
call.initAnalytics();
+ call.setInitiatingUser(initiatingUser);
+
isReusedCall = false;
}
@@ -798,11 +816,13 @@
// If this is an emergency video call, we need to check if the phone account supports
// emergency video calling.
- if (call.isEmergencyCall() && VideoProfile.isVideo(videoState)) {
+ // Also, ensure we don't try to place an outgoing call with video if video is not
+ // supported.
+ if (VideoProfile.isVideo(videoState)) {
PhoneAccount account =
mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle, initiatingUser);
- if (account != null &&
+ if (call.isEmergencyCall() && account != null &&
!account.hasCapabilities(PhoneAccount.CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
// Phone account doesn't support emergency video calling, so fallback to
// audio-only now to prevent the InCall UI from setting up video surfaces
@@ -810,6 +830,12 @@
Log.i(this, "startOutgoingCall - emergency video calls not supported; " +
"falling back to audio-only");
videoState = VideoProfile.STATE_AUDIO_ONLY;
+ } else if (account != null &&
+ !account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
+ // Phone account doesn't support video calling, so fallback to audio-only.
+ Log.i(this, "startOutgoingCall - video calls not supported; fallback to " +
+ "audio-only.");
+ videoState = VideoProfile.STATE_AUDIO_ONLY;
}
}
@@ -828,7 +854,7 @@
}
}
- if (phoneAccountHandle == null && accounts.size() > 0 && !call.isEmergencyCall()) {
+ if (phoneAccountHandle == null && accounts.size() > 0) {
// No preset account, check if default exists that supports the URI scheme for the
// handle and verify it can be used.
if(accounts.size() > 1) {
@@ -927,26 +953,24 @@
final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
R.bool.use_speaker_when_docked);
- final boolean isDocked = mDockManager.isDocked();
- final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabled(videoState);
+ final boolean useSpeakerForDock = isSpeakerphoneEnabledForDock();
+ final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabledForVideoCalls(videoState);
// Auto-enable speakerphone if the originating intent specified to do so, if the call
// is a video call, of if using speaker when docked
call.setStartWithSpeakerphoneOn(speakerphoneOn || useSpeakerForVideoCall
- || (useSpeakerWhenDocked && isDocked));
+ || (useSpeakerWhenDocked && useSpeakerForDock));
call.setVideoState(videoState);
if (speakerphoneOn) {
Log.i(this, "%s Starting with speakerphone as requested", call);
- } else if (useSpeakerWhenDocked && useSpeakerWhenDocked) {
+ } else if (useSpeakerWhenDocked && useSpeakerForDock) {
Log.i(this, "%s Starting with speakerphone because car is docked.", call);
} else if (useSpeakerForVideoCall) {
Log.i(this, "%s Starting with speakerphone because its a video call.", call);
}
if (call.isEmergencyCall()) {
- // Emergency -- CreateConnectionProcessor will choose accounts automatically
- call.setTargetPhoneAccount(null);
new AsyncEmergencyContactNotifier(mContext).execute();
}
@@ -996,7 +1020,8 @@
// STATE_DIALING, put it on hold before answering the call.
if (foregroundCall != null && foregroundCall != call &&
(foregroundCall.isActive() ||
- foregroundCall.getState() == CallState.DIALING)) {
+ foregroundCall.getState() == CallState.DIALING ||
+ foregroundCall.getState() == CallState.PULLING)) {
if (0 == (foregroundCall.getConnectionCapabilities()
& Connection.CAPABILITY_HOLD)) {
// This call does not support hold. If it is from a different connection
@@ -1029,7 +1054,7 @@
// We do not update the UI until we get confirmation of the answer() through
// {@link #markCallAsActive}.
call.answer(videoState);
- if (isSpeakerphoneAutoEnabled(videoState)) {
+ if (isSpeakerphoneAutoEnabledForVideoCalls(videoState)) {
call.setStartWithSpeakerphoneOn(true);
}
}
@@ -1043,7 +1068,7 @@
* @param videoState The video state of the call.
* @return {@code true} if the speakerphone should be enabled.
*/
- private boolean isSpeakerphoneAutoEnabled(int videoState) {
+ public boolean isSpeakerphoneAutoEnabledForVideoCalls(int videoState) {
return VideoProfile.isVideo(videoState) &&
!mWiredHeadsetManager.isPluggedIn() &&
!mBluetoothManager.isBluetoothAvailable() &&
@@ -1051,6 +1076,19 @@
}
/**
+ * Determines if the speakerphone should be enabled for when docked. Speakerphone
+ * should be enabled if the device is docked and bluetooth or the wired headset are
+ * not in use.
+ *
+ * @return {@code true} if the speakerphone should be enabled for the dock.
+ */
+ private boolean isSpeakerphoneEnabledForDock() {
+ return mDockManager.isDocked() &&
+ !mWiredHeadsetManager.isPluggedIn() &&
+ !mBluetoothManager.isBluetoothAvailable();
+ }
+
+ /**
* Determines if the speakerphone should be automatically enabled for video calls.
*
* @return {@code true} if the speakerphone should automatically be enabled.
@@ -1171,13 +1209,19 @@
if (!mCalls.contains(call)) {
Log.w(this, "Unknown call (%s) asked to be removed from hold", call);
} else {
+ boolean otherCallHeld = false;
Log.d(this, "unholding call: (%s)", call);
for (Call c : mCalls) {
// Only attempt to hold parent calls and not the individual children.
if (c != null && c.isAlive() && c != call && c.getParentCall() == null) {
+ otherCallHeld = true;
+ Log.addEvent(c, LogUtils.Events.SWAP);
c.hold();
}
}
+ if (otherCallHeld) {
+ Log.addEvent(call, LogUtils.Events.SWAP);
+ }
call.unhold();
}
}
@@ -1189,6 +1233,7 @@
}
handleCallTechnologyChange(c);
handleChildAddressChange(c);
+ updateCanAddCall();
}
// Construct the list of possible PhoneAccounts that the outgoing call can use based on the
@@ -1337,6 +1382,11 @@
maybeMoveToSpeakerPhone(call);
}
+ void markCallAsPulling(Call call) {
+ setCallState(call, CallState.PULLING, "pulling set explicitly");
+ maybeMoveToSpeakerPhone(call);
+ }
+
void markCallAsActive(Call call) {
setCallState(call, CallState.ACTIVE, "active set explicitly");
maybeMoveToSpeakerPhone(call);
@@ -1362,12 +1412,21 @@
*/
void markCallAsRemoved(Call call) {
removeCall(call);
+ Call foregroundCall = mCallAudioManager.getPossiblyHeldForegroundCall();
if (mLocallyDisconnectingCalls.contains(call)) {
mLocallyDisconnectingCalls.remove(call);
- Call foregroundCall = mCallAudioManager.getPossiblyHeldForegroundCall();
if (foregroundCall != null && foregroundCall.getState() == CallState.ON_HOLD) {
foregroundCall.unhold();
}
+ } else if (foregroundCall != null &&
+ !foregroundCall.can(Connection.CAPABILITY_SUPPORT_HOLD) &&
+ foregroundCall.getState() == CallState.ON_HOLD) {
+
+ // The new foreground call is on hold, however the carrier does not display the hold
+ // button in the UI. Therefore, we need to auto unhold the held call since the user has
+ // no means of unholding it themselves.
+ Log.i(this, "Auto-unholding held foreground call (call doesn't support hold)");
+ foregroundCall.unhold();
}
}
@@ -1424,13 +1483,14 @@
mCallAudioManager.toggleMute();
return true;
} else {
- ringingCall.answer(ringingCall.getVideoState());
+ ringingCall.answer(VideoProfile.STATE_AUDIO_ONLY);
return true;
}
} else if (HeadsetMediaButton.LONG_PRESS == type) {
Log.d(this, "handleHeadsetHook: longpress -> hangup");
Call callToHangup = getFirstCallWithState(
- CallState.RINGING, CallState.DIALING, CallState.ACTIVE, CallState.ON_HOLD);
+ CallState.RINGING, CallState.DIALING, CallState.PULLING, CallState.ACTIVE,
+ CallState.ON_HOLD);
if (callToHangup != null) {
callToHangup.disconnect();
return true;
@@ -1443,7 +1503,8 @@
/**
* Returns true if telecom supports adding another top-level call.
*/
- boolean canAddCall() {
+ @VisibleForTesting
+ public boolean canAddCall() {
boolean isDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) != 0;
if (!isDeviceProvisioned) {
@@ -1460,9 +1521,18 @@
if (call.isEmergencyCall()) {
// We never support add call if one of the calls is an emergency call.
return false;
+ } else if (call.isExternalCall()) {
+ // External calls don't count.
+ continue;
} else if (call.getParentCall() == null) {
count++;
}
+ Bundle extras = call.getExtras();
+ if (extras != null) {
+ if (extras.getBoolean(Connection.EXTRA_DISABLE_ADD_CALL, false)) {
+ return false;
+ }
+ }
// We do not check states for canAddCall. We treat disconnected calls the same
// and wait until they are removed instead. If we didn't count disconnected calls,
@@ -1473,6 +1543,7 @@
return false;
}
}
+
return true;
}
@@ -1546,6 +1617,10 @@
continue;
}
+ if (call.isExternalCall()) {
+ continue;
+ }
+
if (currentState == call.getState()) {
return call;
}
@@ -1628,7 +1703,16 @@
* @param incomingCall Incoming call that has been rejected
*/
private void rejectCallAndLog(Call incomingCall) {
- incomingCall.reject(false, null);
+ if (incomingCall.getConnectionService() != null) {
+ // Only reject the call if it has not already been destroyed. If a call ends while
+ // incoming call filtering is taking place, it is possible that the call has already
+ // been destroyed, and as such it will be impossible to send the reject to the
+ // associated ConnectionService.
+ incomingCall.reject(false, null);
+ } else {
+ Log.i(this, "rejectCallAndLog - call already destroyed.");
+ }
+
// Since the call was not added to the list of calls, we have to call the missed
// call notifier and the call logger manually.
// Do we need missed call notification for direct to Voicemail calls?
@@ -1653,7 +1737,7 @@
extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
SystemClock.elapsedRealtime());
- updateCallsManagerState();
+ updateCanAddCall();
// onCallAdded for calls which immediately take the foreground (like the first call).
for (CallsManagerListener listener : mListeners) {
if (LogUtils.SYSTRACE_DEBUG) {
@@ -1685,7 +1769,7 @@
// Only broadcast changes for calls that are being tracked.
if (shouldNotify) {
- updateCallsManagerState();
+ updateCanAddCall();
for (CallsManagerListener listener : mListeners) {
if (LogUtils.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " onCallRemoved");
@@ -1726,7 +1810,7 @@
Trace.beginSection("onCallStateChanged");
// Only broadcast state change for calls that are being tracked.
if (mCalls.contains(call)) {
- updateCallsManagerState();
+ updateCanAddCall();
for (CallsManagerListener listener : mListeners) {
if (LogUtils.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " onCallStateChanged");
@@ -1757,10 +1841,6 @@
}
}
- private void updateCallsManagerState() {
- updateCanAddCall();
- }
-
private boolean isPotentialMMICode(Uri handle) {
return (handle != null && handle.getSchemeSpecificPart() != null
&& handle.getSchemeSpecificPart().contains("#"));
@@ -1796,7 +1876,9 @@
int count = 0;
for (int state : states) {
for (Call call : mCalls) {
- if (call.getParentCall() == null && call.getState() == state) {
+ if (call.getParentCall() == null && call.getState() == state &&
+ !call.isExternalCall()) {
+
count++;
}
}
@@ -1821,7 +1903,7 @@
}
private boolean hasMaximumDialingCalls() {
- return MAXIMUM_DIALING_CALLS <= getNumCallsWithState(CallState.DIALING);
+ return MAXIMUM_DIALING_CALLS <= getNumCallsWithState(CallState.DIALING, CallState.PULLING);
}
private boolean makeRoomForOutgoingCall(Call call, boolean isEmergency) {
@@ -1959,6 +2041,8 @@
* @return The new call.
*/
Call createCallForExistingConnection(String callId, ParcelableConnection connection) {
+ boolean isDowngradedConference = (connection.getConnectionProperties()
+ & Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0;
Call call = new Call(
callId,
mContext,
@@ -1974,7 +2058,7 @@
connection.getPhoneAccount(), /* targetPhoneAccountHandle */
Call.CALL_DIRECTION_UNDEFINED /* callDirection */,
false /* forceAttachToExistingConnection */,
- false /* isConference */,
+ isDowngradedConference /* isConference */,
connection.getConnectTimeMillis() /* connectTimeMillis */);
call.initAnalytics();
diff --git a/src/com/android/server/telecom/CallsManagerListenerBase.java b/src/com/android/server/telecom/CallsManagerListenerBase.java
index 9bfa098..a4c76c1 100644
--- a/src/com/android/server/telecom/CallsManagerListenerBase.java
+++ b/src/com/android/server/telecom/CallsManagerListenerBase.java
@@ -69,7 +69,7 @@
}
@Override
- public void onVideoStateChanged(Call call) {
+ public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
}
@Override
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 22ea7ad..b30f52d 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -16,6 +16,7 @@
package com.android.server.telecom;
+import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
@@ -34,6 +35,7 @@
import android.telecom.Logging.Session;
import android.telecom.ParcelableConference;
import android.telecom.ParcelableConnection;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
@@ -68,7 +70,7 @@
@Override
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.hCCC");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -84,7 +86,7 @@
@Override
public void setActive(String callId, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.sA");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_ACTIVE);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -104,7 +106,7 @@
@Override
public void setRinging(String callId, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.sR");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_RINGING);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -143,7 +145,7 @@
@Override
public void setDialing(String callId, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.sD");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_DIALING);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -162,9 +164,27 @@
}
@Override
+ public void setPulling(String callId, Session.Info sessionInfo) {
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_PULLING);
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ logIncoming("setPulling %s", callId);
+ Call call = mCallIdMapper.getCall(callId);
+ if (call != null) {
+ mCallsManager.markCallAsPulling(call);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ Log.endSession();
+ }
+ }
+
+ @Override
public void setDisconnected(String callId, DisconnectCause disconnectCause,
Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.sD");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_DISCONNECTED);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -185,7 +205,7 @@
@Override
public void setOnHold(String callId, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.sOH");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_ON_HOLD);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -226,7 +246,7 @@
@Override
public void removeCall(String callId, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.rC");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_REMOVE_CALL);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -291,7 +311,7 @@
@Override
public void setIsConferenced(String callId, String conferenceCallId,
Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.sIC");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_IS_CONFERENCED);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -327,15 +347,7 @@
// deliver the message anyway that they want. b/20530631.
Call call = mCallIdMapper.getCall(callId);
if (call != null) {
- // Just refresh the connection capabilities so that the UI
- // is forced to reenable the merge button as the capability
- // is still on the connection. Note when b/20530631 is fixed, we need
- // to revisit this fix to remove this hacky way of unhiding the merge
- // button (side effect of reprocessing the capabilities) and plumb
- // the failure event all the way to InCallUI instead of stopping
- // it here. That way we can also handle the UI of notifying that
- // the merged has failed.
- call.setConnectionCapabilities(call.getConnectionCapabilities(), true);
+ call.onConnectionEvent(Connection.EVENT_CALL_MERGE_FAILED, null);
} else {
Log.w(this, "setConferenceMergeFailed, unknown call id: %s", callId);
}
@@ -349,7 +361,7 @@
@Override
public void addConferenceCall(String callId, ParcelableConference parcelableConference,
Session.Info sessionInfo) {
- Log.startSession(sessionInfo, "CSW.aCC");
+ Log.startSession(sessionInfo, LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -621,17 +633,42 @@
}
@Override
- public void addExistingConnection(String callId, ParcelableConnection connection,
- Session.Info sessionInfo) {
+ public void addExistingConnection(String callId, ParcelableConnection connection,
+ Session.Info sessionInfo) {
Log.startSession(sessionInfo, "CSW.aEC");
+ UserHandle userHandle = Binder.getCallingUserHandle();
+ // Check that the Calling Package matches PhoneAccountHandle's Component Package
+ PhoneAccountHandle callingPhoneAccountHandle = connection.getPhoneAccount();
+ if (callingPhoneAccountHandle != null) {
+ mAppOpsManager.checkPackage(Binder.getCallingUid(),
+ callingPhoneAccountHandle.getComponentName().getPackageName());
+ }
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- logIncoming("addExistingConnection %s %s", callId, connection);
- Call existingCall = mCallsManager
- .createCallForExistingConnection(callId, connection);
- mCallIdMapper.addCall(existingCall, callId);
- existingCall.setConnectionService(ConnectionServiceWrapper.this);
+ // Make sure that the PhoneAccount associated with the incoming
+ // ParcelableConnection is in fact registered to Telecom and is being called
+ // from the correct user.
+ List<PhoneAccountHandle> accountHandles =
+ mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null /*uriScheme*/,
+ false /*includeDisabledAccounts*/, userHandle);
+ PhoneAccountHandle phoneAccountHandle = null;
+ for (PhoneAccountHandle accountHandle : accountHandles) {
+ if(accountHandle.equals(callingPhoneAccountHandle)) {
+ phoneAccountHandle = accountHandle;
+ }
+ }
+ if (phoneAccountHandle != null) {
+ logIncoming("addExistingConnection %s %s", callId, connection);
+ Call existingCall = mCallsManager
+ .createCallForExistingConnection(callId, connection);
+ mCallIdMapper.addCall(existingCall, callId);
+ existingCall.setConnectionService(ConnectionServiceWrapper.this);
+ } else {
+ Log.e(this, new RemoteException("The PhoneAccount being used is not " +
+ "currently registered with Telecom."), "Unable to " +
+ "addExistingConnection.");
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -668,6 +705,7 @@
private final ConnectionServiceRepository mConnectionServiceRepository;
private final PhoneAccountRegistrar mPhoneAccountRegistrar;
private final CallsManager mCallsManager;
+ private final AppOpsManager mAppOpsManager;
/**
* Creates a connection service.
@@ -695,6 +733,7 @@
});
mPhoneAccountRegistrar = phoneAccountRegistrar;
mCallsManager = callsManager;
+ mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
}
/** See {@link IConnectionService#addConnectionServiceAdapter}. */
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 2389935..2b88848 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -133,7 +133,7 @@
mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
}
adjustAttemptsForConnectionManager();
- adjustAttemptsForEmergency();
+ adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
mAttemptRecordIterator = mAttemptRecords.iterator();
attemptNextPhoneAccount();
}
@@ -295,7 +295,7 @@
// If we are possibly attempting to call a local emergency number, ensure that the
// plain PSTN connection services are listed, and nothing else.
- private void adjustAttemptsForEmergency() {
+ private void adjustAttemptsForEmergency(PhoneAccountHandle preferredPAH) {
if (mCall.isEmergencyCall()) {
Log.i(this, "Emergency number detected");
mAttemptRecords.clear();
@@ -314,16 +314,29 @@
allAccounts.add(TelephonyUtil.getDefaultEmergencyPhoneAccount());
}
- // First, add SIM phone accounts which can place emergency calls.
+ // First, possibly add the SIM phone account that the user prefers
+ PhoneAccount preferredPA = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
+ preferredPAH);
+ if (preferredPA != null &&
+ preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) &&
+ preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+ Log.i(this, "Will try PSTN account %s for emergency",
+ preferredPA.getAccountHandle());
+ mAttemptRecords.add(new CallAttemptRecord(preferredPAH, preferredPAH));
+ }
+
+ // Next, add all SIM phone accounts which can place emergency calls.
+ TelephonyUtil.sortSimPhoneAccounts(mContext, allAccounts);
for (PhoneAccount phoneAccount : allAccounts) {
if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) &&
phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
- Log.i(this, "Will try PSTN account %s for emergency",
- phoneAccount.getAccountHandle());
- mAttemptRecords.add(
- new CallAttemptRecord(
- phoneAccount.getAccountHandle(),
- phoneAccount.getAccountHandle()));
+ PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle();
+ // Don't add the preferred account since it has already been added previously.
+ if (!phoneAccountHandle.equals(preferredPAH)) {
+ Log.i(this, "Will try PSTN account %s for emergency", phoneAccountHandle);
+ mAttemptRecords.add(new CallAttemptRecord(phoneAccountHandle,
+ phoneAccountHandle));
+ }
}
}
@@ -426,7 +439,7 @@
public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) {
// Failure of some sort; record the reasons for failure and try again if possible
Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause);
- if(shouldFailCallIfConnectionManagerFails(errorDisconnectCause)){
+ if (shouldFailCallIfConnectionManagerFails(errorDisconnectCause)) {
notifyCallConnectionFailure(errorDisconnectCause);
return;
}
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
index 7c0fd19..399c28a 100644
--- a/src/com/android/server/telecom/CreateConnectionTimeout.java
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -115,7 +115,8 @@
int state = call.getState();
return state == CallState.NEW
|| state == CallState.CONNECTING
- || state == CallState.DIALING;
+ || state == CallState.DIALING
+ || state == CallState.PULLING;
}
private long getTimeoutLengthMillis() {
diff --git a/src/com/android/server/telecom/HeadsetMediaButton.java b/src/com/android/server/telecom/HeadsetMediaButton.java
index a5cf9ec..f9ba60e 100644
--- a/src/com/android/server/telecom/HeadsetMediaButton.java
+++ b/src/com/android/server/telecom/HeadsetMediaButton.java
@@ -136,6 +136,9 @@
/** ${inheritDoc} */
@Override
public void onCallRemoved(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
if (!mCallsManager.hasAnyCalls()) {
mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 0, 0).sendToTarget();
}
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index fe19480..e775818 100644
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -48,7 +48,7 @@
@Override
public void answerCall(String callId, int videoState) {
try {
- Log.startSession("ICA.aC", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -71,7 +71,7 @@
@Override
public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
try {
- Log.startSession("ICA.rC", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -163,7 +163,7 @@
@Override
public void disconnectCall(String callId) {
try {
- Log.startSession("ICA.dC", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -186,7 +186,7 @@
@Override
public void holdCall(String callId) {
try {
- Log.startSession("ICA.hC", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -208,7 +208,7 @@
@Override
public void unholdCall(String callId) {
try {
- Log.startSession("ICA.uC", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -253,7 +253,7 @@
@Override
public void mute(boolean shouldMute) {
try {
- Log.startSession("ICA.m", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -270,7 +270,7 @@
@Override
public void setAudioRoute(int route) {
try {
- Log.startSession("ICA.sAR", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -287,7 +287,7 @@
@Override
public void conference(String callId, String otherCallId) {
try {
- Log.startSession("ICA.c", mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerComponentName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 95e137f..43c0e48 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -80,6 +80,60 @@
public void dump(IndentingPrintWriter pw) {}
}
+ private class InCallServiceInfo {
+ private final ComponentName mComponentName;
+ private boolean mIsExternalCallsSupported;
+ private final int mType;
+
+ public InCallServiceInfo(ComponentName componentName,
+ boolean isExternalCallsSupported,
+ int type) {
+ mComponentName = componentName;
+ mIsExternalCallsSupported = isExternalCallsSupported;
+ mType = type;
+ }
+
+ public ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ public boolean isExternalCallsSupported() {
+ return mIsExternalCallsSupported;
+ }
+
+ public int getType() {
+ return mType;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ InCallServiceInfo that = (InCallServiceInfo) o;
+
+ if (mIsExternalCallsSupported != that.mIsExternalCallsSupported) {
+ return false;
+ }
+ return mComponentName.equals(that.mComponentName);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mComponentName, mIsExternalCallsSupported);
+ }
+
+ @Override
+ public String toString() {
+ return "[" + mComponentName + " supportsExternal? " + mIsExternalCallsSupported + "]";
+ }
+ }
+
private class InCallServiceBindingConnection extends InCallServiceConnection {
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@@ -115,12 +169,12 @@
}
};
- private final ComponentName mComponentName;
+ private final InCallServiceInfo mInCallServiceInfo;
private boolean mIsConnected = false;
private boolean mIsBound = false;
- public InCallServiceBindingConnection(ComponentName componentName) {
- mComponentName = componentName;
+ public InCallServiceBindingConnection(InCallServiceInfo info) {
+ mInCallServiceInfo = info;
}
@Override
@@ -131,7 +185,7 @@
}
Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
- intent.setComponent(mComponentName);
+ intent.setComponent(mInCallServiceInfo.getComponentName());
if (call != null && !call.isIncoming() && !call.isExternalCall()){
intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS,
call.getIntentExtras());
@@ -139,7 +193,7 @@
call.getTargetPhoneAccount());
}
- Log.i(this, "Attempting to bind to InCall %s, with %s", mComponentName, intent);
+ Log.i(this, "Attempting to bind to InCall %s, with %s", mInCallServiceInfo, intent);
mIsConnected = true;
if (!mContext.bindServiceAsUser(intent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
@@ -148,6 +202,12 @@
mIsConnected = false;
}
+ if (call != null && mIsConnected) {
+ call.getAnalytics().addInCallService(
+ mInCallServiceInfo.getComponentName().flattenToShortString(),
+ mInCallServiceInfo.getType());
+ }
+
return mIsConnected;
}
@@ -170,10 +230,10 @@
protected void onConnected(IBinder service) {
boolean shouldRemainConnected =
- InCallController.this.onConnected(mComponentName, service);
+ InCallController.this.onConnected(mInCallServiceInfo, service);
if (!shouldRemainConnected) {
// Sometimes we can opt to disconnect for certain reasons, like if the
- // InCallService rejected our intialization step, or the calls went away
+ // InCallService rejected our initialization step, or the calls went away
// in the time it took us to bind to the InCallService. In such cases, we go
// ahead and disconnect ourselves.
disconnect();
@@ -181,7 +241,7 @@
}
protected void onDisconnected() {
- InCallController.this.onDisconnected(mComponentName);
+ InCallController.this.onDisconnected(mInCallServiceInfo.getComponentName());
disconnect(); // Unbind explicitly if we get disconnected.
if (mListener != null) {
mListener.onDisconnect(InCallServiceBindingConnection.this);
@@ -216,8 +276,9 @@
};
public EmergencyInCallServiceConnection(
- ComponentName componentName, InCallServiceConnection subConnection) {
- super(componentName);
+ InCallServiceInfo info, InCallServiceConnection subConnection) {
+
+ super(info);
mSubConnection = subConnection;
if (mSubConnection != null) {
mSubConnection.setListener(mSubListener);
@@ -501,7 +562,7 @@
}
@Override
- public void onVideoStateChanged(Call call) {
+ public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
updateCall(call);
}
@@ -537,7 +598,7 @@
private static final int IN_CALL_SERVICE_TYPE_NON_UI = 4;
/** The in-call app implementations, see {@link IInCallService}. */
- private final Map<ComponentName, IInCallService> mInCallServices = new ArrayMap<>();
+ private final Map<InCallServiceInfo, IInCallService> mInCallServices = new ArrayMap<>();
/**
* The {@link ComponentName} of the bound In-Call UI Service.
@@ -554,17 +615,19 @@
private final CallsManager mCallsManager;
private final SystemStateProvider mSystemStateProvider;
private final DefaultDialerManagerAdapter mDefaultDialerAdapter;
+ private final Timeouts.Adapter mTimeoutsAdapter;
private CarSwappingInCallServiceConnection mInCallServiceConnection;
private NonUIInCallServiceConnectionCollection mNonUIInCallServiceConnections;
public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
SystemStateProvider systemStateProvider,
- DefaultDialerManagerAdapter defaultDialerAdapter) {
+ DefaultDialerManagerAdapter defaultDialerAdapter, Timeouts.Adapter timeoutsAdapter) {
mContext = context;
mLock = lock;
mCallsManager = callsManager;
mSystemStateProvider = systemStateProvider;
mDefaultDialerAdapter = defaultDialerAdapter;
+ mTimeoutsAdapter = timeoutsAdapter;
Resources resources = mContext.getResources();
mSystemInCallComponentName = new ComponentName(
@@ -585,16 +648,26 @@
// Track the call if we don't already know about it.
addCall(call);
- for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
- ComponentName componentName = entry.getKey();
+ List<ComponentName> componentsUpdated = new ArrayList<>();
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
+ InCallServiceInfo info = entry.getKey();
+
+ if (call.isExternalCall() && !info.isExternalCallsSupported()) {
+ continue;
+ }
+
+ componentsUpdated.add(info.getComponentName());
IInCallService inCallService = entry.getValue();
+
ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
- true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar());
+ true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
+ info.isExternalCallsSupported());
try {
inCallService.addCall(parcelableCall);
} catch (RemoteException ignored) {
}
}
+ Log.i(this, "Call added to components: %s", componentsUpdated);
}
}
@@ -614,7 +687,7 @@
unbindFromServices();
}
}
- }.prepare(), Timeouts.getCallRemoveUnbindInCallServicesDelay(
+ }.prepare(), mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
mContext.getContentResolver()));
}
call.removeListener(mCallListener);
@@ -624,8 +697,62 @@
@Override
public void onExternalCallChanged(Call call, boolean isExternalCall) {
Log.i(this, "onExternalCallChanged: %s -> %b", call, isExternalCall);
- // TODO: Need to add logic which ensures changes to a call's external state adds or removes
- // the call from the InCallServices depending on whether they support external calls.
+
+ List<ComponentName> componentsUpdated = new ArrayList<>();
+ if (!isExternalCall) {
+ // The call was external but it is no longer external. We must now add it to any
+ // InCallServices which do not support external calls.
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
+ InCallServiceInfo info = entry.getKey();
+
+ if (info.isExternalCallsSupported()) {
+ // For InCallServices which support external calls, the call will have already
+ // been added to the connection service, so we do not need to add it again.
+ continue;
+ }
+
+ componentsUpdated.add(info.getComponentName());
+ IInCallService inCallService = entry.getValue();
+
+ ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
+ true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
+ info.isExternalCallsSupported());
+ try {
+ inCallService.addCall(parcelableCall);
+ } catch (RemoteException ignored) {
+ }
+ }
+ Log.i(this, "Previously external call added to components: %s", componentsUpdated);
+ } else {
+ // The call was regular but it is now external. We must now remove it from any
+ // InCallServices which do not support external calls.
+ // Remove the call by sending a call update indicating the call was disconnected.
+ ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
+ call,
+ false /* includeVideoProvider */,
+ mCallsManager.getPhoneAccountRegistrar(),
+ false /* supportsExternalCalls */,
+ android.telecom.Call.STATE_DISCONNECTED /* overrideState */);
+
+ Log.i(this, "Removing external call %s ==> %s", call, parcelableCall);
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
+ InCallServiceInfo info = entry.getKey();
+ if (info.isExternalCallsSupported()) {
+ // For InCallServices which support external calls, we do not need to remove
+ // the call.
+ continue;
+ }
+
+ componentsUpdated.add(info.getComponentName());
+ IInCallService inCallService = entry.getValue();
+
+ try {
+ inCallService.updateCall(parcelableCall);
+ } catch (RemoteException ignored) {
+ }
+ }
+ Log.i(this, "External call removed from components: %s", componentsUpdated);
+ }
}
@Override
@@ -715,6 +842,10 @@
if (!mInCallServices.isEmpty()) {
for (IInCallService inCallService : mInCallServices.values()) {
try {
+ Log.i(this, "notifyConnectionEvent {Call: %s, Event: %s, Extras:[%s]}",
+ (call != null ? call.toString() :"null"),
+ (event != null ? event : "null") ,
+ (extras != null ? extras.toString() : "null"));
inCallService.onConnectionEvent(mCallIdMapper.getCallId(call), event, extras);
} catch (RemoteException ignored) {
}
@@ -727,10 +858,14 @@
*/
private void unbindFromServices() {
if (isBoundToServices()) {
- mInCallServiceConnection.disconnect();
- mInCallServiceConnection = null;
- mNonUIInCallServiceConnections.disconnect();
- mNonUIInCallServiceConnections = null;
+ if (mInCallServiceConnection != null) {
+ mInCallServiceConnection.disconnect();
+ mInCallServiceConnection = null;
+ }
+ if (mNonUIInCallServiceConnections != null) {
+ mNonUIInCallServiceConnections.disconnect();
+ mNonUIInCallServiceConnections = null;
+ }
}
}
@@ -743,23 +878,25 @@
@VisibleForTesting
public void bindToServices(Call call) {
InCallServiceConnection dialerInCall = null;
- ComponentName defaultDialerComponent = getDefaultDialerComponent();
- Log.i(this, "defaultDialer: " + defaultDialerComponent);
- if (defaultDialerComponent != null &&
- !defaultDialerComponent.equals(mSystemInCallComponentName)) {
- dialerInCall = new InCallServiceBindingConnection(defaultDialerComponent);
+ InCallServiceInfo defaultDialerComponentInfo = getDefaultDialerComponent();
+ Log.i(this, "defaultDialer: " + defaultDialerComponentInfo);
+ if (defaultDialerComponentInfo != null &&
+ !defaultDialerComponentInfo.getComponentName().equals(mSystemInCallComponentName)) {
+ dialerInCall = new InCallServiceBindingConnection(defaultDialerComponentInfo);
}
Log.i(this, "defaultDialer: " + dialerInCall);
+ InCallServiceInfo systemInCallInfo = getInCallServiceComponent(mSystemInCallComponentName,
+ IN_CALL_SERVICE_TYPE_SYSTEM_UI);
EmergencyInCallServiceConnection systemInCall =
- new EmergencyInCallServiceConnection(mSystemInCallComponentName, dialerInCall);
+ new EmergencyInCallServiceConnection(systemInCallInfo, dialerInCall);
systemInCall.setHasEmergency(mCallsManager.hasEmergencyCall());
InCallServiceConnection carModeInCall = null;
- ComponentName carModeComponent = getCarModeComponent();
- if (carModeComponent != null &&
- !carModeComponent.equals(mSystemInCallComponentName)) {
- carModeInCall = new InCallServiceBindingConnection(carModeComponent);
+ InCallServiceInfo carModeComponentInfo = getCarModeComponent();
+ if (carModeComponentInfo != null &&
+ !carModeComponentInfo.getComponentName().equals(mSystemInCallComponentName)) {
+ carModeInCall = new InCallServiceBindingConnection(carModeComponentInfo);
}
mInCallServiceConnection =
@@ -767,18 +904,17 @@
mInCallServiceConnection.setCarMode(shouldUseCarModeUI());
mInCallServiceConnection.connect(call);
-
- List<ComponentName> nonUIInCallComponents =
- getInCallServiceComponents(null, IN_CALL_SERVICE_TYPE_NON_UI);
+ List<InCallServiceInfo> nonUIInCallComponents =
+ getInCallServiceComponents(IN_CALL_SERVICE_TYPE_NON_UI);
List<InCallServiceBindingConnection> nonUIInCalls = new LinkedList<>();
- for (ComponentName componentName : nonUIInCallComponents) {
- nonUIInCalls.add(new InCallServiceBindingConnection(componentName));
+ for (InCallServiceInfo serviceInfo : nonUIInCallComponents) {
+ nonUIInCalls.add(new InCallServiceBindingConnection(serviceInfo));
}
mNonUIInCallServiceConnections = new NonUIInCallServiceConnectionCollection(nonUIInCalls);
mNonUIInCallServiceConnections.connect(call);
}
- private ComponentName getDefaultDialerComponent() {
+ private InCallServiceInfo getDefaultDialerComponent() {
String packageName = mDefaultDialerAdapter.getDefaultDialerApplication(
mContext, mCallsManager.getCurrentUserHandle().getIdentifier());
Log.d(this, "Default Dialer package: " + packageName);
@@ -786,25 +922,57 @@
return getInCallServiceComponent(packageName, IN_CALL_SERVICE_TYPE_DIALER_UI);
}
- private ComponentName getCarModeComponent() {
- return getInCallServiceComponent(null, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
+ private InCallServiceInfo getCarModeComponent() {
+ // Seems strange to cast a String to null, but the signatures of getInCallServiceComponent
+ // differ in the types of the first parameter, and passing in null is inherently ambiguous.
+ return getInCallServiceComponent((String) null, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
}
- private ComponentName getInCallServiceComponent(String packageName, int type) {
- List<ComponentName> list = getInCallServiceComponents(packageName, type);
+ private InCallServiceInfo getInCallServiceComponent(ComponentName componentName, int type) {
+ List<InCallServiceInfo> list = getInCallServiceComponents(componentName, type);
+ if (list != null && !list.isEmpty()) {
+ return list.get(0);
+ } else {
+ // Last Resort: Try to bind to the ComponentName given directly.
+ Log.e(this, new Exception(), "Package Manager could not find ComponentName: "
+ + componentName +". Trying to bind anyway.");
+ return new InCallServiceInfo(componentName, false, type);
+ }
+ }
+
+ private InCallServiceInfo getInCallServiceComponent(String packageName, int type) {
+ List<InCallServiceInfo> list = getInCallServiceComponents(packageName, type);
if (list != null && !list.isEmpty()) {
return list.get(0);
}
return null;
}
- private List<ComponentName> getInCallServiceComponents(String packageName, int type) {
- List<ComponentName> retval = new LinkedList<>();
+ private List<InCallServiceInfo> getInCallServiceComponents(int type) {
+ return getInCallServiceComponents(null, null, type);
+ }
+
+ private List<InCallServiceInfo> getInCallServiceComponents(String packageName, int type) {
+ return getInCallServiceComponents(packageName, null, type);
+ }
+
+ private List<InCallServiceInfo> getInCallServiceComponents(ComponentName componentName,
+ int type) {
+ return getInCallServiceComponents(null, componentName, type);
+ }
+
+ private List<InCallServiceInfo> getInCallServiceComponents(String packageName,
+ ComponentName componentName, int requestedType) {
+
+ List<InCallServiceInfo> retval = new LinkedList<>();
Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE);
if (packageName != null) {
serviceIntent.setPackage(packageName);
}
+ if (componentName != null) {
+ serviceIntent.setComponent(componentName);
+ }
PackageManager packageManager = mContext.getPackageManager();
for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
@@ -814,8 +982,15 @@
ServiceInfo serviceInfo = entry.serviceInfo;
if (serviceInfo != null) {
- if (type == 0 || type == getInCallServiceType(entry.serviceInfo, packageManager)) {
- retval.add(new ComponentName(serviceInfo.packageName, serviceInfo.name));
+ boolean isExternalCallsSupported = serviceInfo.metaData != null &&
+ serviceInfo.metaData.getBoolean(
+ TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, false);
+ if (requestedType == 0 || requestedType == getInCallServiceType(entry.serviceInfo,
+ packageManager)) {
+
+ retval.add(new InCallServiceInfo(
+ new ComponentName(serviceInfo.packageName, serviceInfo.name),
+ isExternalCallsSupported, requestedType));
}
}
}
@@ -861,7 +1036,6 @@
return IN_CALL_SERVICE_TYPE_CAR_MODE_UI;
}
-
// Check to see that it is the default dialer package
boolean isDefaultDialerPackage = Objects.equals(serviceInfo.packageName,
mDefaultDialerAdapter.getDefaultDialerApplication(
@@ -899,16 +1073,16 @@
* this class and in-call app by sending the first update to in-call app. This method is
* called after a successful binding connection is established.
*
- * @param componentName The service {@link ComponentName}.
+ * @param info Info about the service, including its {@link ComponentName}.
* @param service The {@link IInCallService} implementation.
* @return True if we successfully connected.
*/
- private boolean onConnected(ComponentName componentName, IBinder service) {
- Trace.beginSection("onConnected: " + componentName);
- Log.i(this, "onConnected to %s", componentName);
+ private boolean onConnected(InCallServiceInfo info, IBinder service) {
+ Trace.beginSection("onConnected: " + info.getComponentName());
+ Log.i(this, "onConnected to %s", info.getComponentName());
IInCallService inCallService = IInCallService.Stub.asInterface(service);
- mInCallServices.put(componentName, inCallService);
+ mInCallServices.put(info, inCallService);
try {
inCallService.setInCallAdapter(
@@ -916,7 +1090,7 @@
mCallsManager,
mCallIdMapper,
mLock,
- componentName.getPackageName()));
+ info.getComponentName().getPackageName()));
} catch (RemoteException e) {
Log.e(this, e, "Failed to set the in-call adapter.");
Trace.endSection();
@@ -925,28 +1099,32 @@
// Upon successful connection, send the state of the world to the service.
List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls());
- if (!calls.isEmpty()) {
- Log.i(this, "Adding %s calls to InCallService after onConnected: %s", calls.size(),
- componentName);
- for (Call call : calls) {
- try {
- // Track the call if we don't already know about it.
- addCall(call);
- inCallService.addCall(ParcelableCallUtils.toParcelableCall(
- call,
- true /* includeVideoProvider */,
- mCallsManager.getPhoneAccountRegistrar()));
- } catch (RemoteException ignored) {
- }
- }
+ Log.i(this, "Adding %s calls to InCallService after onConnected: %s, including external " +
+ "calls", calls.size(), info.getComponentName());
+ int numCallsSent = 0;
+ for (Call call : calls) {
try {
- inCallService.onCallAudioStateChanged(mCallsManager.getAudioState());
- inCallService.onCanAddCallChanged(mCallsManager.canAddCall());
+ if (call.isExternalCall() && !info.isExternalCallsSupported()) {
+ continue;
+ }
+
+ // Track the call if we don't already know about it.
+ addCall(call);
+ numCallsSent += 1;
+ inCallService.addCall(ParcelableCallUtils.toParcelableCall(
+ call,
+ true /* includeVideoProvider */,
+ mCallsManager.getPhoneAccountRegistrar(),
+ info.isExternalCallsSupported()));
} catch (RemoteException ignored) {
}
- } else {
- return false;
}
+ try {
+ inCallService.onCallAudioStateChanged(mCallsManager.getAudioState());
+ inCallService.onCanAddCallChanged(mCallsManager.canAddCall());
+ } catch (RemoteException ignored) {
+ }
+ Log.i(this, "%s calls sent to InCallService.", numCallsSent);
Trace.endSection();
return true;
}
@@ -980,16 +1158,23 @@
*/
private void updateCall(Call call, boolean videoProviderChanged) {
if (!mInCallServices.isEmpty()) {
- ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
- call,
- videoProviderChanged /* includeVideoProvider */,
- mCallsManager.getPhoneAccountRegistrar());
- Log.i(this, "Sending updateCall %s ==> %s", call, parcelableCall);
+ Log.i(this, "Sending updateCall %s", call);
List<ComponentName> componentsUpdated = new ArrayList<>();
- for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
- ComponentName componentName = entry.getKey();
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
+ InCallServiceInfo info = entry.getKey();
+ if (call.isExternalCall() && !info.isExternalCallsSupported()) {
+ continue;
+ }
+
+ ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
+ call,
+ videoProviderChanged /* includeVideoProvider */,
+ mCallsManager.getPhoneAccountRegistrar(),
+ info.isExternalCallsSupported());
+ ComponentName componentName = info.getComponentName();
IInCallService inCallService = entry.getValue();
componentsUpdated.add(componentName);
+
try {
inCallService.updateCall(parcelableCall);
} catch (RemoteException ignored) {
@@ -1022,8 +1207,8 @@
public void dump(IndentingPrintWriter pw) {
pw.println("mInCallServices (InCalls registered):");
pw.increaseIndent();
- for (ComponentName componentName : mInCallServices.keySet()) {
- pw.println(componentName);
+ for (InCallServiceInfo info : mInCallServices.keySet()) {
+ pw.println(info);
}
pw.decreaseIndent();
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index 9a10480..62c692b 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -276,7 +276,12 @@
mSession = Log.createSubsession();
}
- start();
+ super.start();
+ }
+
+ @Override
+ public void start() {
+ Log.w(this, "Do not call the start method directly; use startTone instead.");
}
/**
diff --git a/src/com/android/server/telecom/InCallWakeLockController.java b/src/com/android/server/telecom/InCallWakeLockController.java
index a0db54e..ac93bb5 100644
--- a/src/com/android/server/telecom/InCallWakeLockController.java
+++ b/src/com/android/server/telecom/InCallWakeLockController.java
@@ -38,16 +38,25 @@
@Override
public void onCallAdded(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
handleWakeLock();
}
@Override
public void onCallRemoved(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
handleWakeLock();
}
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
+ if (call.isExternalCall()) {
+ return;
+ }
handleWakeLock();
}
diff --git a/src/com/android/server/telecom/InterruptionFilterProxy.java b/src/com/android/server/telecom/InterruptionFilterProxy.java
new file mode 100644
index 0000000..434c341
--- /dev/null
+++ b/src/com/android/server/telecom/InterruptionFilterProxy.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 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;
+
+/**
+ * Defines common functionality used by {@link CallAudioRouteStateMachine} to control the current
+ * interruption filter for notifications while in a call. Used to ensure that this functionality
+ * can be mocked out in unit tests.
+ */
+public interface InterruptionFilterProxy {
+ void setInterruptionFilter(int interruptionFilter);
+ int getCurrentInterruptionFilter();
+}
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 8de8fc9..95ab7db 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -56,9 +56,6 @@
*/
@VisibleForTesting
public class NewOutgoingCallIntentBroadcaster {
- private static final String EXTRA_ACTUAL_NUMBER_TO_DIAL =
- "android.telecom.extra.ACTUAL_NUMBER_TO_DIAL";
-
/**
* Legacy string constants used to retrieve gateway provider extras from intents. These still
* need to be copied from the source call intent to the destination intent in order to
@@ -68,14 +65,13 @@
public static final String EXTRA_GATEWAY_PROVIDER_PACKAGE =
"com.android.phone.extra.GATEWAY_PROVIDER_PACKAGE";
public static final String EXTRA_GATEWAY_URI = "com.android.phone.extra.GATEWAY_URI";
- public static final String EXTRA_GATEWAY_ORIGINAL_URI =
- "com.android.phone.extra.GATEWAY_ORIGINAL_URI";
private final CallsManager mCallsManager;
private final Call mCall;
private final Intent mIntent;
private final Context mContext;
private final PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
+ private final TelecomSystem.SyncRoot mLock;
/*
* Whether or not the outgoing call intent originated from the default phone application. If
@@ -93,6 +89,7 @@
mIntent = intent;
mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
mIsDefaultOrSystemPhoneApp = isDefaultPhoneApp;
+ mLock = mCallsManager.getLock();
}
/**
@@ -106,63 +103,65 @@
try {
Log.startSession("NOCBIR.oR");
Trace.beginSection("onReceiveNewOutgoingCallBroadcast");
- Log.v(this, "onReceive: %s", intent);
+ synchronized (mLock) {
+ Log.v(this, "onReceive: %s", intent);
- // 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.pii(resultNumber));
+ // 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.pii(resultNumber));
- boolean endEarly = false;
- if (resultNumber == null) {
- Log.v(this, "Call cancelled (null number), returning...");
- endEarly = true;
- } else if (mPhoneNumberUtilsAdapter.isPotentialLocalEmergencyNumber(
- mContext, resultNumber)) {
- Log.w(this, "Cannot modify outgoing call to emergency number %s.",
- resultNumber);
- endEarly = true;
- }
-
- if (endEarly) {
- if (mCall != null) {
- mCall.disconnect(true /* wasViaNewOutgoingCall */);
+ boolean endEarly = false;
+ if (resultNumber == null) {
+ Log.v(this, "Call cancelled (null number), returning...");
+ endEarly = true;
+ } else if (mPhoneNumberUtilsAdapter.isPotentialLocalEmergencyNumber(
+ mContext, resultNumber)) {
+ Log.w(this, "Cannot modify outgoing call to emergency number %s.",
+ resultNumber);
+ endEarly = true;
}
- return;
+
+ if (endEarly) {
+ if (mCall != null) {
+ mCall.disconnect(true /* wasViaNewOutgoingCall */);
+ }
+ return;
+ }
+
+ // If this call is already disconnected then we have nothing more to do.
+ if (mCall.isDisconnected()) {
+ Log.w(this, "Call has already been disconnected," +
+ " ignore the broadcast Call %s", mCall);
+ return;
+ }
+
+ Uri resultHandleUri = Uri.fromParts(
+ mPhoneNumberUtilsAdapter.isUriNumber(resultNumber) ?
+ PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL,
+ resultNumber, null);
+
+ Uri originalUri = mIntent.getData();
+
+ if (originalUri.getSchemeSpecificPart().equals(resultNumber)) {
+ Log.v(this, "Call number unmodified after" +
+ " new outgoing call intent broadcast.");
+ } else {
+ Log.v(this, "Retrieved modified handle after outgoing call intent" +
+ " broadcast: Original: %s, Modified: %s",
+ Log.pii(originalUri),
+ Log.pii(resultHandleUri));
+ }
+
+ GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri);
+ mCall.setNewOutgoingCallIntentBroadcastIsDone();
+ mCallsManager.placeOutgoingCall(mCall, resultHandleUri, gatewayInfo,
+ mIntent.getBooleanExtra(
+ TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false),
+ mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
+ VideoProfile.STATE_AUDIO_ONLY));
}
-
- // If this call is already disconnected then we have nothing more to do.
- if (mCall.isDisconnected()) {
- Log.w(this,
- "Call has already been disconnected, ignore the broadcast Call %s", mCall);
- return;
- }
-
- Uri resultHandleUri = Uri.fromParts(
- mPhoneNumberUtilsAdapter.isUriNumber(resultNumber) ?
- PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL,
- resultNumber, null);
-
- Uri originalUri = mIntent.getData();
-
- if (originalUri.getSchemeSpecificPart().equals(resultNumber)) {
- Log.v(this, "Call number unmodified after new outgoing call intent broadcast.");
- } else {
- Log.v(this, "Retrieved modified handle after outgoing call intent broadcast: "
- + "Original: %s, Modified: %s",
- Log.pii(originalUri),
- Log.pii(resultHandleUri));
- }
-
- GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri);
- mCall.setNewOutgoingCallIntentBroadcastIsDone();
- mCallsManager.placeOutgoingCall(mCall, resultHandleUri, gatewayInfo,
- mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,
- false),
- mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
- VideoProfile.STATE_AUDIO_ONLY));
-
} finally {
Trace.endSection();
Log.endSession();
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 9b65197..9cc61b3 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -28,11 +28,13 @@
* Utilities dealing with {@link ParcelableCall}.
*/
public class ParcelableCallUtils {
+ private static final int CALL_STATE_OVERRIDE_NONE = -1;
+
public static class Converter {
public ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider,
PhoneAccountRegistrar phoneAccountRegistrar) {
return ParcelableCallUtils.toParcelableCall(
- call, includeVideoProvider, phoneAccountRegistrar);
+ call, includeVideoProvider, phoneAccountRegistrar, false);
}
}
@@ -45,13 +47,45 @@
* method creates a {@link VideoCallImpl} instance on access it is important for the
* recipient of the {@link ParcelableCall} to know if the video provider changed.
* @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}.
+ * @param supportsExternalCalls Indicates whether the call should be parcelled for an
+ * {@link InCallService} which supports external calls or not.
+ */
+ public static ParcelableCall toParcelableCall(
+ Call call,
+ boolean includeVideoProvider,
+ PhoneAccountRegistrar phoneAccountRegistrar,
+ boolean supportsExternalCalls) {
+ return toParcelableCall(call, includeVideoProvider, phoneAccountRegistrar,
+ supportsExternalCalls, CALL_STATE_OVERRIDE_NONE /* overrideState */);
+ }
+
+ /**
+ * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance.
+ *
+ * @param call The {@link Call} to parcel.
+ * @param includeVideoProvider {@code true} if the video provider should be parcelled with the
+ * {@link Call}, {@code false} otherwise. Since the {@link ParcelableCall#getVideoCall()}
+ * method creates a {@link VideoCallImpl} instance on access it is important for the
+ * recipient of the {@link ParcelableCall} to know if the video provider changed.
+ * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}.
+ * @param supportsExternalCalls Indicates whether the call should be parcelled for an
+ * {@link InCallService} which supports external calls or not.
+ * @param overrideState When not {@link #CALL_STATE_OVERRIDE_NONE}, use the provided state as an
+ * override to whatever is defined in the call.
* @return The {@link ParcelableCall} containing all call information from the {@link Call}.
*/
public static ParcelableCall toParcelableCall(
Call call,
boolean includeVideoProvider,
- PhoneAccountRegistrar phoneAccountRegistrar) {
- int state = getParcelableState(call);
+ PhoneAccountRegistrar phoneAccountRegistrar,
+ boolean supportsExternalCalls,
+ int overrideState) {
+ int state;
+ if (overrideState == CALL_STATE_OVERRIDE_NONE) {
+ state = getParcelableState(call, supportsExternalCalls);
+ } else {
+ state = overrideState;
+ }
int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities());
int properties = convertConnectionToCallProperties(call.getConnectionProperties());
if (call.isConference()) {
@@ -63,7 +97,7 @@
}
// If this is a single-SIM device, the "default SIM" will always be the only SIM.
- boolean isDefaultSmsAccount =
+ boolean isDefaultSmsAccount = phoneAccountRegistrar != null &&
phoneAccountRegistrar.isUserSelectedSmsPhoneAccount(call.getTargetPhoneAccount());
if (call.isRespondViaSmsCapable() && isDefaultSmsAccount) {
capabilities |= android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT;
@@ -141,7 +175,7 @@
call.getExtras());
}
- private static int getParcelableState(Call call) {
+ private static int getParcelableState(Call call, boolean supportsExternalCalls) {
int state = CallState.NEW;
switch (call.getState()) {
case CallState.ABORTED:
@@ -157,6 +191,19 @@
case CallState.DIALING:
state = android.telecom.Call.STATE_DIALING;
break;
+ case CallState.PULLING:
+ if (supportsExternalCalls) {
+ // The InCallService supports external calls, so it must handle
+ // STATE_PULLING_CALL.
+ state = android.telecom.Call.STATE_PULLING_CALL;
+ } else {
+ // The InCallService does NOT support external calls, so remap
+ // STATE_PULLING_CALL to STATE_DIALING. In essence, pulling a call can be seen
+ // as a form of dialing, so it is appropriate for InCallServices which do not
+ // handle external calls.
+ state = android.telecom.Call.STATE_DIALING;
+ }
+ break;
case CallState.DISCONNECTING:
state = android.telecom.Call.STATE_DISCONNECTING;
break;
@@ -267,11 +314,14 @@
Connection.PROPERTY_GENERIC_CONFERENCE,
android.telecom.Call.Details.PROPERTY_GENERIC_CONFERENCE,
- Connection.PROPERTY_SHOW_CALLBACK_NUMBER,
+ Connection.PROPERTY_EMERGENCY_CALLBACK_MODE,
android.telecom.Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE,
Connection.PROPERTY_IS_EXTERNAL_CALL,
- android.telecom.Call.Details.PROPERTY_IS_EXTERNAL_CALL
+ android.telecom.Call.Details.PROPERTY_IS_EXTERNAL_CALL,
+
+ Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY,
+ android.telecom.Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY
};
private static int convertConnectionToCallProperties(int connectionProperties) {
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index bd96d12..143ea53 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -60,7 +60,6 @@
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -77,8 +76,12 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Handles writing and reading PhoneAccountHandle registration entries. This is a simple verbatim
@@ -245,6 +248,46 @@
}
/**
+ * @return The {@link DefaultPhoneAccountHandle} containing the user-selected default calling
+ * account and group Id for the {@link UserHandle} specified.
+ */
+ private DefaultPhoneAccountHandle getUserSelectedDefaultPhoneAccount(UserHandle userHandle) {
+ if (userHandle == null) {
+ return null;
+ }
+ DefaultPhoneAccountHandle defaultPhoneAccountHandle = mState.defaultOutgoingAccountHandles
+ .get(userHandle);
+ if (defaultPhoneAccountHandle == null) {
+ return null;
+ }
+
+ return defaultPhoneAccountHandle;
+ }
+
+ /**
+ * @return The currently registered PhoneAccount in Telecom that has the same group Id.
+ */
+ private PhoneAccount getPhoneAccountByGroupId(String groupId, ComponentName groupComponentName,
+ UserHandle userHandle, PhoneAccountHandle excludePhoneAccountHandle) {
+ if (groupId == null || groupId.isEmpty() || userHandle == null) {
+ return null;
+ }
+ // Get the PhoneAccount with the same group Id (and same ComponentName) that is not the
+ // newAccount that was just added
+ List<PhoneAccount> accounts = getAllPhoneAccounts(userHandle).stream()
+ .filter(account -> groupId.equals(account.getGroupId()) &&
+ !account.getAccountHandle().equals(excludePhoneAccountHandle) &&
+ Objects.equals(account.getAccountHandle().getComponentName(),
+ groupComponentName))
+ .collect(Collectors.toList());
+ // There should be one or no PhoneAccounts with the same group Id
+ if (accounts.size() > 1) {
+ Log.w(this, "Found multiple PhoneAccounts registered to the same Group Id!");
+ }
+ return accounts.isEmpty() ? null : accounts.get(0);
+ }
+
+ /**
* Sets the phone account with which to place all calls by default. Set by the user
* within phone settings.
*/
@@ -278,7 +321,8 @@
}
mState.defaultOutgoingAccountHandles
- .put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle));
+ .put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle,
+ account.getGroupId()));
}
write();
@@ -592,6 +636,8 @@
}
mState.accounts.add(account);
+ // Set defaults and replace based on the group Id.
+ maybeReplaceOldAccount(account);
// Reset enabled state to whatever the value was if the account was already registered,
// or _true_ if this is a SIM-based account. All SIM-based accounts are always enabled.
account.setIsEnabled(
@@ -698,6 +744,40 @@
}
}
+ private void maybeReplaceOldAccount(PhoneAccount newAccount) {
+ UserHandle newAccountUserHandle = newAccount.getAccountHandle().getUserHandle();
+ DefaultPhoneAccountHandle defaultHandle =
+ getUserSelectedDefaultPhoneAccount(newAccountUserHandle);
+ if (defaultHandle == null || defaultHandle.groupId.isEmpty()) {
+ Log.v(this, "maybeReplaceOldAccount: Not replacing PhoneAccount, no group Id or " +
+ "default.");
+ return;
+ }
+ if (!defaultHandle.groupId.equals(newAccount.getGroupId())) {
+ Log.v(this, "maybeReplaceOldAccount: group Ids are not equal.");
+ return;
+ }
+ if (Objects.equals(newAccount.getAccountHandle().getComponentName(),
+ defaultHandle.phoneAccountHandle.getComponentName())) {
+ // Move default calling account over to new user, since the ComponentNames and Group Ids
+ // are the same.
+ setUserSelectedOutgoingPhoneAccount(newAccount.getAccountHandle(),
+ newAccountUserHandle);
+ } else {
+ Log.v(this, "maybeReplaceOldAccount: group Ids are equal, but ComponentName is not" +
+ " the same as the default. Not replacing default PhoneAccount.");
+ }
+ PhoneAccount replacementAccount = getPhoneAccountByGroupId(newAccount.getGroupId(),
+ newAccount.getAccountHandle().getComponentName(), newAccountUserHandle,
+ newAccount.getAccountHandle());
+ if (replacementAccount != null) {
+ // Unregister the old PhoneAccount.
+ Log.v(this, "maybeReplaceOldAccount: Unregistering old PhoneAccount: " +
+ replacementAccount.getAccountHandle());
+ unregisterPhoneAccount(replacementAccount.getAccountHandle());
+ }
+ }
+
/**
* Determines if the connection service specified by a {@link PhoneAccountHandle} requires the
* {@link Manifest.permission#BIND_TELECOM_CONNECTION_SERVICE} permission.
@@ -905,10 +985,13 @@
public final PhoneAccountHandle phoneAccountHandle;
+ public final String groupId;
+
public DefaultPhoneAccountHandle(UserHandle userHandle,
- PhoneAccountHandle phoneAccountHandle) {
+ PhoneAccountHandle phoneAccountHandle, String groupId) {
this.userHandle = userHandle;
this.phoneAccountHandle = phoneAccountHandle;
+ this.groupId = groupId;
}
}
@@ -1155,6 +1238,13 @@
serializer.endTag(null, tagName);
}
+ protected void writeNonNullString(String tagName, String value, XmlSerializer serializer)
+ throws IOException {
+ serializer.startTag(null, tagName);
+ serializer.text(value != null ? value : "");
+ serializer.endTag(null, tagName);
+ }
+
/**
* Reads a string array from the XML parser.
*
@@ -1293,8 +1383,9 @@
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (parser.getName().equals(DEFAULT_OUTGOING)) {
if (s.versionNumber < 9) {
- // Migration old default phone account handle here by assuming the
- // default phone account handle is belong to primary user.
+ // Migrate old default phone account handle here by assuming the
+ // default phone account handle belongs to the primary user. Also,
+ // assume there are no groups.
parser.nextTag();
PhoneAccountHandle phoneAccountHandle = sPhoneAccountHandleXml
.readFromXml(parser, s.versionNumber, context);
@@ -1304,7 +1395,7 @@
UserHandle userHandle = primaryUser.getUserHandle();
DefaultPhoneAccountHandle defaultPhoneAccountHandle
= new DefaultPhoneAccountHandle(userHandle,
- phoneAccountHandle);
+ phoneAccountHandle, "" /* groupId */);
s.defaultOutgoingAccountHandles
.put(userHandle, defaultPhoneAccountHandle);
}
@@ -1344,6 +1435,7 @@
private static final String CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE
= "default_outgoing_phone_account_handle";
private static final String USER_SERIAL_NUMBER = "user_serial_number";
+ private static final String GROUP_ID = "group_id";
private static final String ACCOUNT_HANDLE = "account_handle";
@Override
@@ -1355,6 +1447,7 @@
if (serialNumber != -1) {
serializer.startTag(null, CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE);
writeLong(USER_SERIAL_NUMBER, serialNumber, serializer);
+ writeNonNullString(GROUP_ID, o.groupId, serializer);
serializer.startTag(null, ACCOUNT_HANDLE);
sPhoneAccountHandleXml.writeToXml(o.phoneAccountHandle, serializer,
context);
@@ -1372,6 +1465,7 @@
int outerDepth = parser.getDepth();
PhoneAccountHandle accountHandle = null;
String userSerialNumberString = null;
+ String groupId = "";
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (parser.getName().equals(ACCOUNT_HANDLE)) {
parser.nextTag();
@@ -1380,6 +1474,9 @@
} else if (parser.getName().equals(USER_SERIAL_NUMBER)) {
parser.next();
userSerialNumberString = parser.getText();
+ } else if (parser.getName().equals(GROUP_ID)) {
+ parser.next();
+ groupId = parser.getText();
}
}
UserHandle userHandle = null;
@@ -1393,8 +1490,9 @@
"Could not parse UserHandle " + userSerialNumberString);
}
}
- if (accountHandle != null && userHandle != null) {
- return new DefaultPhoneAccountHandle(userHandle, accountHandle);
+ if (accountHandle != null && userHandle != null && groupId != null) {
+ return new DefaultPhoneAccountHandle(userHandle, accountHandle,
+ groupId);
}
}
return null;
diff --git a/src/com/android/server/telecom/PhoneStateBroadcaster.java b/src/com/android/server/telecom/PhoneStateBroadcaster.java
index 8c9a5ad..a44fc03 100644
--- a/src/com/android/server/telecom/PhoneStateBroadcaster.java
+++ b/src/com/android/server/telecom/PhoneStateBroadcaster.java
@@ -44,6 +44,9 @@
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
+ if (call.isExternalCall()) {
+ return;
+ }
updateStates(call);
}
@@ -84,8 +87,8 @@
int callState = TelephonyManager.CALL_STATE_IDLE;
if (mCallsManager.hasRingingCall()) {
callState = TelephonyManager.CALL_STATE_RINGING;
- } else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.ACTIVE,
- CallState.ON_HOLD) != null) {
+ } else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.PULLING,
+ CallState.ACTIVE, CallState.ON_HOLD) != null) {
callState = TelephonyManager.CALL_STATE_OFFHOOK;
}
sendPhoneStateChangedBroadcast(call, callState);
diff --git a/src/com/android/server/telecom/ProximitySensorManager.java b/src/com/android/server/telecom/ProximitySensorManager.java
index 4ddb121..a79c0ed 100644
--- a/src/com/android/server/telecom/ProximitySensorManager.java
+++ b/src/com/android/server/telecom/ProximitySensorManager.java
@@ -39,6 +39,9 @@
@Override
public void onCallRemoved(Call call) {
+ if (call.isExternalCall()) {
+ return;
+ }
if (mCallsManager.getCalls().isEmpty()) {
Log.i(this, "All calls removed, resetting proximity sensor to default state");
turnOff(true);
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index e711c18..6b2a39e 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -30,6 +30,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.telecom.Connection;
import android.telecom.Log;
import android.telecom.Response;
import android.telephony.PhoneNumberUtils;
@@ -132,8 +133,7 @@
public void onIncomingCallRejected(Call call, boolean rejectWithMessage, String textMessage) {
if (rejectWithMessage
&& call.getHandle() != null
- && !call.can(
- android.telecom.Call.Details.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
+ && !call.can(Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
int subId = mCallsManager.getPhoneAccountRegistrar().getSubscriptionIdForPhoneAccount(
call.getTargetPhoneAccount());
rejectCallWithMessage(call.getContext(), call.getHandle().getSchemeSpecificPart(),
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 4c4da75..a5bcca0 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -95,30 +95,32 @@
mInCallController = inCallController;
}
- public void startRinging(Call foregroundCall) {
+ public boolean startRinging(Call foregroundCall) {
+ AudioManager audioManager =
+ (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ boolean isRingerAudible = audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
+
if (mSystemSettingsUtil.isTheaterModeOn(mContext)) {
- return;
+ return false;
}
if (foregroundCall == null) {
Log.wtf(this, "startRinging called with null foreground call.");
- return;
+ return false;
}
if (mInCallController.doesConnectedDialerSupportRinging()) {
Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING);
- return;
+ return isRingerAudible;
}
stopCallWaiting();
if (!shouldRingForContact(foregroundCall.getContactUri())) {
- return;
+ return false;
}
- AudioManager audioManager =
- (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- if (audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0) {
+ if (isRingerAudible) {
mRingingCall = foregroundCall;
Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
// Because we wait until a contact info query to complete before processing a
@@ -127,7 +129,7 @@
// request the custom ringtone from the call and expect it to be current.
mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
} else {
- Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0");
+ Log.i(this, "startRingingOrCallWaiting, skipping because volume is 0");
}
if (shouldVibrate(mContext) && !mIsVibrating) {
@@ -135,6 +137,8 @@
VIBRATION_ATTRIBUTES);
mIsVibrating = true;
}
+
+ return isRingerAudible;
}
public void startCallWaiting(Call call) {
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index bf29395..c6ce910 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -43,6 +43,7 @@
import android.telecom.ParcelableCallAnalytics;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomAnalytics;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.SubscriptionManager;
@@ -57,8 +58,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -1146,11 +1145,11 @@
}
@Override
- public List<ParcelableCallAnalytics> dumpCallAnalytics() {
+ public TelecomAnalytics dumpCallAnalytics() {
try {
Log.startSession("TSI.dCA");
enforcePermission(DUMP);
- return Arrays.asList(Analytics.dumpToParcelableAnalytics());
+ return Analytics.dumpToParcelableAnalytics();
} finally {
Log.endSession();
}
@@ -1174,6 +1173,11 @@
return;
}
+ if (args.length > 0 && Analytics.ANALYTICS_DUMPSYS_ARG.equals(args[0])) {
+ Analytics.dumpToEncodedProto(writer, args);
+ return;
+ }
+
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
if (mCallsManager != null) {
pw.println("CallsManager: ");
@@ -1294,6 +1298,7 @@
call = mCallsManager.getFirstCallWithState(
CallState.ACTIVE,
CallState.DIALING,
+ CallState.PULLING,
CallState.RINGING,
CallState.ON_HOLD);
}
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index ca74333..5bbce5c 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -180,7 +180,8 @@
bluetoothPhoneServiceImplFactory,
Timeouts.Adapter timeoutsAdapter,
AsyncRingtonePlayer asyncRingtonePlayer,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter) {
+ PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
+ InterruptionFilterProxy interruptionFilterProxy) {
mContext = context.getApplicationContext();
LogUtils.initLogging(mContext);
@@ -222,7 +223,8 @@
defaultDialerAdapter,
timeoutsAdapter,
asyncRingtonePlayer,
- phoneNumberUtilsAdapter);
+ phoneNumberUtilsAdapter,
+ interruptionFilterProxy);
mRespondViaSmsManager = new RespondViaSmsManager(mCallsManager, mLock);
mCallsManager.setRespondViaSmsManager(mRespondViaSmsManager);
diff --git a/src/com/android/server/telecom/TelephonyUtil.java b/src/com/android/server/telecom/TelephonyUtil.java
index 69adaf9..50b8901 100644
--- a/src/com/android/server/telecom/TelephonyUtil.java
+++ b/src/com/android/server/telecom/TelephonyUtil.java
@@ -22,9 +22,15 @@
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
/**
* Utilities to deal with the system telephony services. The system telephony services are treated
* differently from 3rd party services in some situations (emergency calls, audio focus, etc...).
@@ -67,4 +73,55 @@
return handle != null && PhoneNumberUtils.isLocalEmergencyNumber(
context, handle.getSchemeSpecificPart());
}
+
+ public static void sortSimPhoneAccounts(Context context, List<PhoneAccount> accounts) {
+ final TelephonyManager telephonyManager = TelephonyManager.from(context);
+
+ // Sort the accounts according to how we want to display them.
+ Collections.sort(accounts, new Comparator<PhoneAccount>() {
+ @Override
+ public int compare(PhoneAccount account1, PhoneAccount account2) {
+ int retval = 0;
+
+ // SIM accounts go first
+ boolean isSim1 = account1.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+ boolean isSim2 = account2.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+ if (isSim1 != isSim2) {
+ retval = isSim1 ? -1 : 1;
+ }
+
+ int subId1 = telephonyManager.getSubIdForPhoneAccount(account1);
+ int subId2 = telephonyManager.getSubIdForPhoneAccount(account2);
+ if (subId1 != SubscriptionManager.INVALID_SUBSCRIPTION_ID &&
+ subId2 != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ retval = (SubscriptionManager.getSlotId(subId1) <
+ SubscriptionManager.getSlotId(subId2)) ? -1 : 1;
+ }
+
+ // Then order by package
+ if (retval == 0) {
+ String pkg1 = account1.getAccountHandle().getComponentName().getPackageName();
+ String pkg2 = account2.getAccountHandle().getComponentName().getPackageName();
+ retval = pkg1.compareTo(pkg2);
+ }
+
+ // Finally, order by label
+ if (retval == 0) {
+ String label1 = nullToEmpty(account1.getLabel().toString());
+ String label2 = nullToEmpty(account2.getLabel().toString());
+ retval = label1.compareTo(label2);
+ }
+
+ // Then by hashcode
+ if (retval == 0) {
+ retval = account1.hashCode() - account2.hashCode();
+ }
+ return retval;
+ }
+ });
+ }
+
+ private static String nullToEmpty(String str) {
+ return str == null ? "" : str;
+ }
}
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index 0c8e985..7529683 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -33,6 +33,10 @@
return Timeouts.getCallScreeningTimeoutMillis(cr);
}
+ public long getCallRemoveUnbindInCallServicesDelay(ContentResolver cr) {
+ return Timeouts.getCallRemoveUnbindInCallServicesDelay(cr);
+ }
+
public long getRetryBluetoothConnectAudioBackoffMillis(ContentResolver cr) {
return Timeouts.getRetryBluetoothConnectAudioBackoffMillis(cr);
}
@@ -61,22 +65,13 @@
}
/**
- * Returns the longest period, in milliseconds, to wait for the query for direct-to-voicemail
- * to complete. If the query goes beyond this timeout, the incoming call screen is shown to the
- * user.
- */
- public static long getDirectToVoicemailMillis(ContentResolver contentResolver) {
- return get(contentResolver, "direct_to_voicemail_ms", 500L);
- }
-
- /**
* Returns the amount of time to wait before disconnecting a call that was canceled via
* NEW_OUTGOING_CALL broadcast. This timeout allows apps which repost the call using a gateway
* to reuse the existing call, preventing the call from causing a start->end->start jank in the
* in-call UI.
*/
public static long getNewOutgoingCallCancelMillis(ContentResolver contentResolver) {
- return get(contentResolver, "new_outgoing_call_cancel_ms", 400L);
+ return get(contentResolver, "new_outgoing_call_cancel_ms", 100000L);
}
/**
@@ -140,11 +135,4 @@
public static long getCallScreeningTimeoutMillis(ContentResolver contentResolver) {
return get(contentResolver, "call_screening_timeout", 5000L /* 5 seconds */);
}
-
- /**
- * Returns the amount of time to wait for the block checker to allow or disallow a call.
- */
- public static long getBlockCheckTimeoutMillis(ContentResolver contentResolver) {
- return get(contentResolver, "block_check_timeout_millis", 500L);
- }
}
diff --git a/src/com/android/server/telecom/VideoProviderProxy.java b/src/com/android/server/telecom/VideoProviderProxy.java
index 4792d39..e14aba7 100644
--- a/src/com/android/server/telecom/VideoProviderProxy.java
+++ b/src/com/android/server/telecom/VideoProviderProxy.java
@@ -30,7 +30,6 @@
import com.android.internal.telecom.IVideoProvider;
import java.util.Collections;
-import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -131,6 +130,30 @@
Log.startSession("VPP.rSMR");
synchronized (mLock) {
logFromVideoProvider("receiveSessionModifyRequest: " + videoProfile);
+ Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_REQUEST,
+ VideoProfile.videoStateToString(videoProfile.getVideoState()));
+
+ mCall.getAnalytics().addVideoEvent(
+ Analytics.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST,
+ videoProfile.getVideoState());
+
+ if (!mCall.isVideoCallingSupported() &&
+ VideoProfile.isVideo(videoProfile.getVideoState())) {
+ // If video calling is not supported by the phone account, and we receive
+ // a request to upgrade to video, automatically reject it without informing
+ // the InCallService.
+ Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE, "video not supported");
+ VideoProfile responseProfile = new VideoProfile(
+ VideoProfile.STATE_AUDIO_ONLY);
+ try {
+ mConectionServiceVideoProvider.sendSessionModifyResponse(
+ responseProfile);
+ } catch (RemoteException e) {
+ }
+
+ // Don't want to inform listeners of the request as we've just rejected it.
+ return;
+ }
// Inform other Telecom components of the session modification request.
for (Listener listener : mListeners) {
@@ -155,10 +178,19 @@
@Override
public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
VideoProfile responseProfile) {
+ logFromVideoProvider("receiveSessionModifyResponse: status=" + status +
+ " requestProfile=" + requestProfile + " responseProfile=" + responseProfile);
+ String eventMessage = "Status Code : " + status + " Video State: " +
+ (responseProfile != null ? responseProfile.getVideoState() : "null");
+ Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_RESPONSE, eventMessage);
synchronized (mLock) {
- logFromVideoProvider("receiveSessionModifyResponse: status=" + status +
- " requestProfile=" + requestProfile + " responseProfile=" +
- responseProfile);
+ if (status == Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS) {
+ mCall.getAnalytics().addVideoEvent(
+ Analytics.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE,
+ responseProfile == null ?
+ VideoProfile.STATE_AUDIO_ONLY :
+ responseProfile.getVideoState());
+ }
VideoProviderProxy.this.receiveSessionModifyResponse(status, requestProfile,
responseProfile);
}
@@ -173,7 +205,8 @@
@Override
public void handleCallSessionEvent(int event) {
synchronized (mLock) {
- logFromVideoProvider("handleCallSessionEvent: " + event);
+ logFromVideoProvider("handleCallSessionEvent: " +
+ Connection.VideoProvider.sessionEventToString(event));
VideoProviderProxy.this.handleCallSessionEvent(event);
}
}
@@ -338,6 +371,11 @@
public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
synchronized (mLock) {
logFromInCall("sendSessionModifyRequest: from=" + fromProfile + " to=" + toProfile);
+ Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_REQUEST,
+ VideoProfile.videoStateToString(toProfile.getVideoState()));
+ mCall.getAnalytics().addVideoEvent(
+ Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST,
+ toProfile.getVideoState());
try {
mConectionServiceVideoProvider.sendSessionModifyRequest(fromProfile, toProfile);
} catch (RemoteException e) {
@@ -355,6 +393,11 @@
public void onSendSessionModifyResponse(VideoProfile responseProfile) {
synchronized (mLock) {
logFromInCall("sendSessionModifyResponse: " + responseProfile);
+ Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE,
+ VideoProfile.videoStateToString(responseProfile.getVideoState()));
+ mCall.getAnalytics().addVideoEvent(
+ Analytics.SEND_LOCAL_SESSION_MODIFY_RESPONSE,
+ responseProfile.getVideoState());
try {
mConectionServiceVideoProvider.sendSessionModifyResponse(responseProfile);
} catch (RemoteException e) {
@@ -435,7 +478,7 @@
* @param toLog The message to log.
*/
private void logFromInCall(String toLog) {
- Log.v(this, "IC->VP: " + toLog);
+ Log.i(this, "IC->VP (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog);
}
/**
@@ -445,6 +488,6 @@
* @param toLog The message to log.
*/
private void logFromVideoProvider(String toLog) {
- Log.v(this, "VP->IC: " + toLog);
+ Log.i(this, "VP->IC (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog);
}
}
diff --git a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
index 38c84fa..2f78d23 100644
--- a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
+++ b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
@@ -34,7 +34,8 @@
private final Context mContext;
private final BlockCheckerAdapter mBlockCheckerAdapter;
private Call mIncomingCall;
- private Session mLogSubsession;
+ private Session mBackgroundTaskSubsession;
+ private Session mPostExecuteSubsession;
private CallFilterResultCallback mCallback;
public AsyncBlockCheckFilter(Context context, BlockCheckerAdapter blockCheckerAdapter) {
@@ -53,13 +54,14 @@
@Override
protected void onPreExecute() {
- mLogSubsession = Log.createSubsession();
+ mBackgroundTaskSubsession = Log.createSubsession();
+ mPostExecuteSubsession = Log.createSubsession();
}
@Override
protected Boolean doInBackground(String... params) {
try {
- Log.continueSession(mLogSubsession, "ABCF.dIB");
+ Log.continueSession(mBackgroundTaskSubsession, "ABCF.dIB");
Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_INITIATED);
return mBlockCheckerAdapter.isBlocked(mContext, params[0]);
} finally {
@@ -69,23 +71,28 @@
@Override
protected void onPostExecute(Boolean isBlocked) {
- CallFilteringResult result;
- if (isBlocked) {
- result = new CallFilteringResult(
- false, // shouldAllowCall
- true, //shouldReject
- false, //shouldAddToCallLog
- false // shouldShowNotification
- );
- } else {
- result = new CallFilteringResult(
- true, // shouldAllowCall
- false, // shouldReject
- true, // shouldAddToCallLog
- true // shouldShowNotification
- );
+ Log.continueSession(mPostExecuteSubsession, "ABCF.oPE");
+ try {
+ CallFilteringResult result;
+ if (isBlocked) {
+ result = new CallFilteringResult(
+ false, // shouldAllowCall
+ true, //shouldReject
+ false, //shouldAddToCallLog
+ false // shouldShowNotification
+ );
+ } else {
+ result = new CallFilteringResult(
+ true, // shouldAllowCall
+ false, // shouldReject
+ true, // shouldAddToCallLog
+ true // shouldShowNotification
+ );
+ }
+ Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_FINISHED, result);
+ mCallback.onCallFilteringComplete(mIncomingCall, result);
+ } finally {
+ Log.endSession();
}
- Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_FINISHED, result);
- mCallback.onCallFilteringComplete(mIncomingCall, result);
}
}
diff --git a/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java b/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
index ffa327a..41e4351 100644
--- a/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
+++ b/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
@@ -24,6 +24,8 @@
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.LogUtils;
+import java.util.Objects;
+
public class DirectToVoicemailCallFilter implements IncomingCallFilter.CallFilter {
private final CallerInfoLookupHelper mCallerInfoLookupHelper;
@@ -35,13 +37,14 @@
public void startFilterLookup(final Call call, CallFilterResultCallback callback) {
Log.addEvent(call, LogUtils.Events.DIRECT_TO_VM_INITIATED);
final Uri callHandle = call.getHandle();
+
mCallerInfoLookupHelper.startLookup(callHandle,
new CallerInfoLookupHelper.OnQueryCompleteListener() {
@Override
public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
CallFilteringResult result;
- if (callHandle.equals(handle)) {
- if (info.shouldSendToVoicemail) {
+ if (Objects.equals(callHandle, handle)) {
+ if (info != null && info.shouldSendToVoicemail) {
result = new CallFilteringResult(
false, // shouldAllowCall
true, // shouldReject
diff --git a/src/com/android/server/telecom/components/ChangeDefaultDialerDialog.java b/src/com/android/server/telecom/components/ChangeDefaultDialerDialog.java
index 5fd7904..107389b 100644
--- a/src/com/android/server/telecom/components/ChangeDefaultDialerDialog.java
+++ b/src/com/android/server/telecom/components/ChangeDefaultDialerDialog.java
@@ -21,11 +21,18 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Color;
+import android.graphics.Typeface;
import android.os.Bundle;
import android.telecom.DefaultDialerManager;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
import android.util.Log;
import com.android.internal.app.AlertActivity;
@@ -57,7 +64,7 @@
}
// Show dialog to require user confirmation.
- buildDialog(oldPackage, mNewPackage);
+ buildDialog(mNewPackage);
}
@Override
@@ -81,36 +88,26 @@
}
if (!DefaultDialerManager.getInstalledDialerApplications(this).contains(newPackage)) {
- Log.w(TAG, "Provided package name does not correspond to an installed Dialer "
+ Log.w(TAG, "Provided package name does not correspond to an installed Phone "
+ "application.");
return false;
}
if (!TextUtils.isEmpty(oldPackage) && TextUtils.equals(oldPackage, newPackage)) {
- Log.w(TAG, "Provided package name is already the current default Dialer application.");
+ Log.w(TAG, "Provided package name is already the current default Phone application.");
return false;
}
return true;
}
- private boolean buildDialog(String oldPackage, String newPackage) {
+ private boolean buildDialog(String newPackage) {
final PackageManager pm = getPackageManager();
- final String newPackageLabel =
- getApplicationLabelForPackageName(pm, newPackage);
+ final String newPackageLabel = getApplicationLabelForPackageName(pm, newPackage);
final AlertController.AlertParams p = mAlertParams;
- p.mTitle = getString(R.string.change_default_dialer_dialog_title);
- if (!TextUtils.isEmpty(oldPackage)) {
- String oldPackageLabel =
- getApplicationLabelForPackageName(pm, oldPackage);
- p.mMessage = getString(R.string.change_default_dialer_with_previous_app_set_text,
- newPackageLabel,
- oldPackageLabel);
- } else {
- p.mMessage = getString(R.string.change_default_dialer_no_previous_app_set_text,
- newPackageLabel);
- }
- p.mPositiveButtonText = getString(android.R.string.yes);
- p.mNegativeButtonText = getString(android.R.string.no);
+ p.mTitle = getString(R.string.change_default_dialer_dialog_title, newPackageLabel);
+ p.mMessage = getString(R.string.change_default_dialer_warning_message, newPackageLabel);
+ p.mPositiveButtonText = getString(R.string.change_default_dialer_dialog_affirmative);
+ p.mNegativeButtonText = getString(R.string.change_default_dialer_dialog_negative);
p.mPositiveButtonListener = this;
p.mNegativeButtonListener = this;
setupAlert();
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index 898ace9..d3cd073 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -16,6 +16,8 @@
package com.android.server.telecom.components;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
@@ -36,7 +38,9 @@
import com.android.server.telecom.HeadsetMediaButtonFactory;
import com.android.server.telecom.InCallWakeLockControllerFactory;
import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.InterruptionFilterProxy;
import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
import com.android.server.telecom.ProximitySensorManagerFactory;
import com.android.server.telecom.InCallWakeLockController;
@@ -72,6 +76,9 @@
*/
static void initializeTelecomSystem(Context context) {
if (TelecomSystem.getInstance() == null) {
+ final NotificationManager notificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
TelecomSystem.setInstance(
new TelecomSystem(
context,
@@ -150,7 +157,18 @@
},
new Timeouts.Adapter(),
new AsyncRingtonePlayer(),
- new PhoneNumberUtilsAdapterImpl()
+ new PhoneNumberUtilsAdapterImpl(),
+ new InterruptionFilterProxy() {
+ @Override
+ public void setInterruptionFilter(int interruptionFilter) {
+ notificationManager.setInterruptionFilter(interruptionFilter);
+ }
+
+ @Override
+ public int getCurrentInterruptionFilter() {
+ return notificationManager.getCurrentInterruptionFilter();
+ }
+ }
));
}
if (BluetoothAdapter.getDefaultAdapter() != null) {
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index 67fe2b2..6362f66 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -31,6 +31,7 @@
import com.android.server.telecom.Constants;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.R;
import com.android.server.telecom.TelecomBroadcastIntentProcessor;
import com.android.server.telecom.TelecomSystem;
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
index b30e372..0150dbe 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -165,6 +165,9 @@
capabilities |= CAPABILITY_RESPOND_VIA_TEXT;
setConnectionCapabilities(capabilities);
+ if (isIncoming) {
+ putExtra(Connection.EXTRA_ANSWERING_DROPS_FG_CALL, true);
+ }
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(
mHangupReceiver, new IntentFilter(TestCallActivity.ACTION_HANGUP_CALLS));
final IntentFilter filter =
diff --git a/tests/Android.mk b/tests/Android.mk
index e639b55..8a8113b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,11 +21,17 @@
android-ex-camera2 \
android-support-v4 \
guava \
- mockito-target
+ mockito-target \
+ platform-test-annotations
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
- $(call all-java-files-under, ../src)
+ $(call all-java-files-under, ../src) \
+ $(call all-proto-files-under, ../proto)
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../proto/
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/res \
@@ -46,6 +52,9 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.server.telecom.*
+LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := com.android.server.telecom.tests.*
+
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
new file mode 100644
index 0000000..b22ae82
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016 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 android.content.Context;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.telecom.InCallService;
+import android.telecom.Log;
+import android.telecom.ParcelableCallAnalytics;
+import android.telecom.TelecomAnalytics;
+import android.telecom.TelecomManager;
+import android.telecom.VideoCallImpl;
+import android.telecom.VideoProfile;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.telecom.Analytics;
+import com.android.server.telecom.LogUtils;
+import com.android.server.telecom.TelecomLogClass;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+public class AnalyticsTests extends TelecomSystemTest {
+ @MediumTest
+ public void testAnalyticsSingleCall() throws Exception {
+ IdPair testCall = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+
+ assertTrue(analyticsMap.containsKey(testCall.mCallId));
+
+ Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
+ assertTrue(callAnalytics.startTime > 0);
+ assertEquals(0, callAnalytics.endTime);
+ assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
+ assertFalse(callAnalytics.isInterrupted);
+ assertNull(callAnalytics.callTerminationReason);
+ assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+ callAnalytics.connectionService);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+
+ analyticsMap = Analytics.cloneData();
+ callAnalytics = analyticsMap.get(testCall.mCallId);
+ assertTrue(callAnalytics.endTime > 0);
+ assertNotNull(callAnalytics.callTerminationReason);
+ assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
+
+ StringWriter sr = new StringWriter();
+ IndentingPrintWriter ip = new IndentingPrintWriter(sr, " ");
+ Analytics.dump(ip);
+ String dumpResult = sr.toString();
+ String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
+ "isInterrupted", "callTechnologies", "callTerminationReason", "connectionService"};
+ for (String field : expectedFields) {
+ assertTrue(dumpResult.contains(field));
+ }
+ }
+
+ @MediumTest
+ public void testAnalyticsDumping() throws Exception {
+ Analytics.reset();
+ IdPair testCall = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+ Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId);
+
+ TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE);
+ List<ParcelableCallAnalytics> analyticsList = tm.dumpAnalytics().getCallAnalytics();
+
+ assertEquals(1, analyticsList.size());
+ ParcelableCallAnalytics pCA = analyticsList.get(0);
+
+ assertTrue(Math.abs(expectedAnalytics.startTime - pCA.getStartTimeMillis()) <
+ ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
+ assertEquals(0, pCA.getStartTimeMillis() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
+ assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) -
+ pCA.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
+ assertEquals(0, pCA.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
+
+ assertEquals(expectedAnalytics.callDirection, pCA.getCallType());
+ assertEquals(expectedAnalytics.isAdditionalCall, pCA.isAdditionalCall());
+ assertEquals(expectedAnalytics.isInterrupted, pCA.isInterrupted());
+ assertEquals(expectedAnalytics.callTechnologies, pCA.getCallTechnologies());
+ assertEquals(expectedAnalytics.callTerminationReason.getCode(),
+ pCA.getCallTerminationCode());
+ assertEquals(expectedAnalytics.connectionService, pCA.getConnectionService());
+ List<ParcelableCallAnalytics.AnalyticsEvent> analyticsEvents = pCA.analyticsEvents();
+ Set<Integer> capturedEvents = new HashSet<>();
+ for (ParcelableCallAnalytics.AnalyticsEvent e : analyticsEvents) {
+ capturedEvents.add(e.getEventName());
+ assertIsRoundedToOneSigFig(e.getTimeSinceLastEvent());
+ }
+ assertTrue(capturedEvents.contains(ParcelableCallAnalytics.AnalyticsEvent.SET_ACTIVE));
+ assertTrue(capturedEvents.contains(
+ ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED));
+ }
+
+ @MediumTest
+ public void testAnalyticsTwoCalls() throws Exception {
+ IdPair testCall1 = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+ IdPair testCall2 = startAndMakeActiveOutgoingCall(
+ "650-555-1213",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+ assertTrue(analyticsMap.containsKey(testCall1.mCallId));
+ assertTrue(analyticsMap.containsKey(testCall2.mCallId));
+
+ Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
+ Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
+ assertTrue(callAnalytics1.startTime > 0);
+ assertTrue(callAnalytics2.startTime > 0);
+ assertEquals(0, callAnalytics1.endTime);
+ assertEquals(0, callAnalytics2.endTime);
+
+ assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
+ assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
+
+ assertTrue(callAnalytics1.isInterrupted);
+ assertTrue(callAnalytics2.isAdditionalCall);
+
+ assertNull(callAnalytics1.callTerminationReason);
+ assertNull(callAnalytics2.callTerminationReason);
+
+ assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+ callAnalytics1.connectionService);
+ assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+ callAnalytics1.connectionService);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
+
+ analyticsMap = Analytics.cloneData();
+ callAnalytics1 = analyticsMap.get(testCall1.mCallId);
+ callAnalytics2 = analyticsMap.get(testCall2.mCallId);
+ assertTrue(callAnalytics1.endTime > 0);
+ assertTrue(callAnalytics2.endTime > 0);
+ assertNotNull(callAnalytics1.callTerminationReason);
+ assertNotNull(callAnalytics2.callTerminationReason);
+ assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
+ assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
+ }
+
+ @MediumTest
+ public void testAnalyticsVideo() throws Exception {
+ Analytics.reset();
+ IdPair callIds = startAndMakeActiveOutgoingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ CountDownLatch counter = new CountDownLatch(1);
+ InCallService.VideoCall.Callback callback = mock(InCallService.VideoCall.Callback.class);
+
+ doAnswer(invocation -> {
+ counter.countDown();
+ return null;
+ }).when(callback)
+ .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class),
+ any(VideoProfile.class));
+
+ mConnectionServiceFixtureA.sendSetVideoProvider(
+ mConnectionServiceFixtureA.mLatestConnectionId);
+ InCallService.VideoCall videoCall =
+ mInCallServiceFixtureX.getCall(callIds.mCallId).getVideoCallImpl();
+ videoCall.registerCallback(callback);
+ ((VideoCallImpl) videoCall).setVideoState(VideoProfile.STATE_BIDIRECTIONAL);
+
+ videoCall.sendSessionModifyRequest(new VideoProfile(VideoProfile.STATE_RX_ENABLED));
+ counter.await(10000, TimeUnit.MILLISECONDS);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ Analytics.dumpToEncodedProto(pw, new String[]{});
+ TelecomLogClass.TelecomLog analyticsProto =
+ TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT));
+
+ assertEquals(1, analyticsProto.callLogs.length);
+ TelecomLogClass.VideoEvent[] videoEvents = analyticsProto.callLogs[0].videoEvents;
+ assertEquals(2, videoEvents.length);
+
+ assertEquals(Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST, videoEvents[0].getEventName());
+ assertEquals(VideoProfile.STATE_RX_ENABLED, videoEvents[0].getVideoState());
+ assertEquals(-1, videoEvents[0].getTimeSinceLastEventMillis());
+
+ assertEquals(Analytics.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE,
+ videoEvents[1].getEventName());
+ assertEquals(VideoProfile.STATE_RX_ENABLED, videoEvents[1].getVideoState());
+ assertIsRoundedToOneSigFig(videoEvents[1].getTimeSinceLastEventMillis());
+ }
+
+ @SmallTest
+ public void testAnalyticsRounding() {
+ long[] testVals = {0, -1, -10, -100, -57836, 1, 10, 100, 1000, 458457};
+ long[] expected = {0, -1, -10, -100, -60000, 1, 10, 100, 1000, 500000};
+ for (int i = 0; i < testVals.length; i++) {
+ assertEquals(expected[i], Analytics.roundToOneSigFig(testVals[i]));
+ }
+ }
+
+ @SmallTest
+ public void testAnalyticsLogSessionTiming() throws Exception {
+ long minTime = 50;
+ Log.startSession(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL);
+ Thread.sleep(minTime);
+ Log.endSession();
+ TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE);
+ List<TelecomAnalytics.SessionTiming> sessions = tm.dumpAnalytics().getSessionTimings();
+ sessions.stream()
+ .filter(s -> LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL.equals(
+ Analytics.sSessionIdToLogSession.get(s.getKey())))
+ .forEach(s -> assertTrue(s.getTime() >= minTime));
+ }
+
+ @MediumTest
+ public void testAnalyticsDumpToProto() throws Exception {
+ Analytics.reset();
+ IdPair testCall = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+ Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ Analytics.dumpToEncodedProto(pw, new String[]{});
+ TelecomLogClass.TelecomLog analyticsProto =
+ TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT));
+
+ assertEquals(1, analyticsProto.callLogs.length);
+ TelecomLogClass.CallLog callLog = analyticsProto.callLogs[0];
+
+ assertTrue(Math.abs(expectedAnalytics.startTime - callLog.getStartTime5Min()) <
+ ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
+ assertEquals(0, callLog.getStartTime5Min() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
+ assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) -
+ callLog.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
+ assertEquals(0,
+ callLog.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
+
+ assertEquals(expectedAnalytics.callDirection, callLog.getType());
+ assertEquals(expectedAnalytics.isAdditionalCall, callLog.getIsAdditionalCall());
+ assertEquals(expectedAnalytics.isInterrupted, callLog.getIsInterrupted());
+ assertEquals(expectedAnalytics.callTechnologies, callLog.getCallTechnologies());
+ assertEquals(expectedAnalytics.callTerminationReason.getCode(),
+ callLog.getCallTerminationCode());
+ assertEquals(expectedAnalytics.connectionService, callLog.connectionService[0]);
+ TelecomLogClass.Event[] analyticsEvents = callLog.callEvents;
+ Set<Integer> capturedEvents = new HashSet<>();
+ for (TelecomLogClass.Event e : analyticsEvents) {
+ capturedEvents.add(e.getEventName());
+ assertIsRoundedToOneSigFig(e.getTimeSinceLastEventMillis());
+ }
+ assertTrue(capturedEvents.contains(ParcelableCallAnalytics.AnalyticsEvent.SET_ACTIVE));
+ assertTrue(capturedEvents.contains(
+ ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED));
+ }
+
+ @MediumTest
+ public void testAnalyticsConnectionProperties() throws Exception {
+ Analytics.reset();
+ IdPair testCall = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ int properties1 = Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE
+ | Connection.PROPERTY_WIFI
+ | Connection.PROPERTY_EMERGENCY_CALLBACK_MODE;
+ int properties2 = Connection.PROPERTY_HIGH_DEF_AUDIO
+ | Connection.PROPERTY_WIFI;
+ int expectedProperties = properties1 | properties2;
+
+ mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties =
+ properties1;
+ mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId);
+ mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties =
+ properties2;
+ mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ Analytics.dumpToEncodedProto(pw, new String[]{});
+ TelecomLogClass.TelecomLog analyticsProto =
+ TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT));
+
+ assertEquals(expectedProperties,
+ analyticsProto.callLogs[0].getConnectionProperties() & expectedProperties);
+ }
+
+ private void assertIsRoundedToOneSigFig(long x) {
+ assertEquals(x, Analytics.roundToOneSigFig(x));
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 92ec515..c44185c 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -27,7 +27,6 @@
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.media.AudioManager;
@@ -44,28 +43,21 @@
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.ParcelableCall;
-import android.telecom.ParcelableCallAnalytics;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.telecom.IInCallAdapter;
import com.android.internal.telephony.CallerInfo;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.telecom.Analytics;
import com.google.common.base.Predicate;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
@@ -73,13 +65,6 @@
import org.mockito.ArgumentCaptor;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-
/**
* Performs various basic call tests in Telecom.
*/
@@ -690,131 +675,6 @@
assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY));
}
- @MediumTest
- public void testAnalyticsSingleCall() throws Exception {
- IdPair testCall = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
-
- assertTrue(analyticsMap.containsKey(testCall.mCallId));
-
- Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
- assertTrue(callAnalytics.startTime > 0);
- assertEquals(0, callAnalytics.endTime);
- assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
- assertFalse(callAnalytics.isInterrupted);
- assertNull(callAnalytics.callTerminationReason);
- assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
- callAnalytics.connectionService);
-
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
-
- analyticsMap = Analytics.cloneData();
- callAnalytics = analyticsMap.get(testCall.mCallId);
- assertTrue(callAnalytics.endTime > 0);
- assertNotNull(callAnalytics.callTerminationReason);
- assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
-
- StringWriter sr = new StringWriter();
- IndentingPrintWriter ip = new IndentingPrintWriter(sr, " ");
- Analytics.dump(ip);
- String dumpResult = sr.toString();
- String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
- "isInterrupted", "callTechnologies", "callTerminationReason", "connectionService"};
- for (String field : expectedFields) {
- assertTrue(dumpResult.contains(field));
- }
- }
-
- @SmallTest
- public void testAnalyticsDumping() throws Exception {
- Analytics.reset();
- IdPair testCall = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
- Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId);
-
- TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE);
- List<ParcelableCallAnalytics> analyticsList = tm.dumpAnalytics();
-
- assertEquals(1, analyticsList.size());
- ParcelableCallAnalytics pCA = analyticsList.get(0);
-
- assertTrue(Math.abs(expectedAnalytics.startTime - pCA.getStartTimeMillis()) <
- ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
- assertEquals(0, pCA.getStartTimeMillis() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
- assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) -
- pCA.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
- assertEquals(0, pCA.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
-
- assertEquals(expectedAnalytics.callDirection, pCA.getCallType());
- assertEquals(expectedAnalytics.isAdditionalCall, pCA.isAdditionalCall());
- assertEquals(expectedAnalytics.isInterrupted, pCA.isInterrupted());
- assertEquals(expectedAnalytics.callTechnologies, pCA.getCallTechnologies());
- assertEquals(expectedAnalytics.callTerminationReason.getCode(),
- pCA.getCallTerminationCode());
- assertEquals(expectedAnalytics.connectionService, pCA.getConnectionService());
- }
-
- @MediumTest
- public void testAnalyticsTwoCalls() throws Exception {
- IdPair testCall1 = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- IdPair testCall2 = startAndMakeActiveOutgoingCall(
- "650-555-1213",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
- assertTrue(analyticsMap.containsKey(testCall1.mCallId));
- assertTrue(analyticsMap.containsKey(testCall2.mCallId));
-
- Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
- Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
- assertTrue(callAnalytics1.startTime > 0);
- assertTrue(callAnalytics2.startTime > 0);
- assertEquals(0, callAnalytics1.endTime);
- assertEquals(0, callAnalytics2.endTime);
-
- assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
- assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
-
- assertTrue(callAnalytics1.isInterrupted);
- assertTrue(callAnalytics2.isAdditionalCall);
-
- assertNull(callAnalytics1.callTerminationReason);
- assertNull(callAnalytics2.callTerminationReason);
-
- assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
- callAnalytics1.connectionService);
- assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
- callAnalytics1.connectionService);
-
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
-
- analyticsMap = Analytics.cloneData();
- callAnalytics1 = analyticsMap.get(testCall1.mCallId);
- callAnalytics2 = analyticsMap.get(testCall2.mCallId);
- assertTrue(callAnalytics1.endTime > 0);
- assertTrue(callAnalytics2.endTime > 0);
- assertNotNull(callAnalytics1.callTerminationReason);
- assertNotNull(callAnalytics2.callTerminationReason);
- assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
- assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
- }
-
private void blockNumber(String phoneNumber) throws Exception {
blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() {
@Override
@@ -849,6 +709,44 @@
}
/**
+ * Tests to make sure that the Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is set on a
+ * Call that is based on a Connection with the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY
+ * property set.
+ */
+ @MediumTest
+ public void testCdmaEnhancedPrivacyVoiceCall() throws Exception {
+ mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
+ Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY;
+
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+
+ assertTrue(Call.Details.hasProperty(
+ mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(),
+ Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY));
+ }
+
+ /**
+ * Tests to make sure that Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY is dropped
+ * when the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is removed from the Connection.
+ */
+ @MediumTest
+ public void testDropCdmaEnhancedPrivacyVoiceCall() throws Exception {
+ mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
+ Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY;
+
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ mConnectionServiceFixtureA.mLatestConnection.setConnectionProperties(0);
+
+ assertFalse(Call.Details.hasProperty(
+ mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(),
+ Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY));
+ }
+
+ /**
* Tests the {@link Call#pullExternalCall()} API. Ensures that an external call which is
* pullable can be pulled.
*
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
index f9502dd..38ea10e 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
@@ -18,6 +18,7 @@
import android.media.AudioManager;
import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallAudioModeStateMachine;
@@ -32,6 +33,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class CallAudioModeStateMachineTest extends StateMachineTestBase<CallAudioModeStateMachine> {
private static class ModeTestParameters extends TestParameters {
@@ -100,6 +102,37 @@
parametrizedTestStateMachine(testCases);
}
+ @SmallTest
+ public void testNoFocusWhenRingerSilenced() throws Throwable {
+ CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mAudioManager);
+ sm.setCallAudioManager(mCallAudioManager);
+ sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
+ waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
+
+ resetMocks();
+ when(mCallAudioManager.startRinging()).thenReturn(false);
+
+ sm.sendMessage(CallAudioModeStateMachine.NEW_RINGING_CALL,
+ new CallAudioModeStateMachine.MessageArgs(
+ false, // hasActiveOrDialingCalls
+ true, // hasRingingCalls
+ false, // hasHoldingCalls
+ false, // isTonePlaying
+ false, // foregroundCallIsVoip
+ null // session
+ ));
+ waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
+
+ assertEquals(CallAudioModeStateMachine.RING_STATE_NAME, sm.getCurrentStateName());
+
+ verify(mAudioManager, never()).requestAudioFocusForCall(anyInt(), anyInt());
+ verify(mAudioManager, never()).setMode(anyInt());
+
+ verify(mCallAudioManager, never()).stopRinging();
+
+ verify(mCallAudioManager).stopCallWaiting();
+ }
+
private List<ModeTestParameters> generateTestCases() {
List<ModeTestParameters> result = new ArrayList<>();
result.add(new ModeTestParameters(
@@ -516,6 +549,7 @@
waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
resetMocks();
+ when(mCallAudioManager.startRinging()).thenReturn(true);
sm.sendMessage(params.messageType, params.externalState);
waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 4e5fe69..dddf9e6 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -16,6 +16,7 @@
package com.android.server.telecom.tests;
+import android.app.NotificationManager;
import android.content.Context;
import android.media.AudioManager;
import android.media.IAudioService;
@@ -31,6 +32,7 @@
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.InterruptionFilterProxy;
import com.android.server.telecom.StatusBarNotifier;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.WiredHeadsetManager;
@@ -43,11 +45,16 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
@@ -65,27 +72,37 @@
static class RoutingTestParameters extends TestParameters {
public String name;
public int initialRoute;
+ public int initialNotificationFilter;
public int availableRoutes; // may excl. speakerphone, because that's always available
public int speakerInteraction; // one of NONE, ON, or OFF
public int bluetoothInteraction; // one of NONE, ON, or OFF
public int action;
public int expectedRoute;
public int expectedAvailableRoutes; // also may exclude the speakerphone.
+ public int expectedNotificationFilter; // expected end notification filter.
+ public boolean isNotificationChangeExpected; // indicates whether we expect the notification
+ // filter to change during the process of the
+ // test.
public boolean doesDeviceSupportEarpiece; // set to false in the case of Wear devices
public boolean shouldRunWithFocus;
- public RoutingTestParameters(String name, int initialRoute, int availableRoutes, int
- speakerInteraction, int bluetoothInteraction, int action, int expectedRoute, int
- expectedAvailableRoutes, boolean doesDeviceSupportEarpiece,
+ public RoutingTestParameters(String name, int initialRoute,
+ int initialNotificationFilter, int availableRoutes, int speakerInteraction,
+ int bluetoothInteraction, int action, int expectedRoute,
+ int expectedAvailableRoutes, int expectedNotificationFilter,
+ boolean isNotificationChangeExpected, boolean doesDeviceSupportEarpiece,
boolean shouldRunWithFocus) {
this.name = name;
this.initialRoute = initialRoute;
+ this.initialNotificationFilter = initialNotificationFilter;
this.availableRoutes = availableRoutes;
this.speakerInteraction = speakerInteraction;
this.bluetoothInteraction = bluetoothInteraction;
this.action = action;
this.expectedRoute = expectedRoute;
this.expectedAvailableRoutes = expectedAvailableRoutes;
+ this.expectedNotificationFilter = expectedNotificationFilter;
+ this.isNotificationChangeExpected = isNotificationChangeExpected;
this.doesDeviceSupportEarpiece = doesDeviceSupportEarpiece;
this.shouldRunWithFocus = shouldRunWithFocus;
}
@@ -95,12 +112,15 @@
return "RoutingTestParameters{" +
"name='" + name + '\'' +
", initialRoute=" + initialRoute +
+ ", initialNotificationFilter=" + initialNotificationFilter +
", availableRoutes=" + availableRoutes +
", speakerInteraction=" + speakerInteraction +
", bluetoothInteraction=" + bluetoothInteraction +
", action=" + action +
", expectedRoute=" + expectedRoute +
", expectedAvailableRoutes=" + expectedAvailableRoutes +
+ ", expectedNotificationFilter= " + expectedNotificationFilter +
+ ", isNotificationChangeExpected=" + isNotificationChangeExpected +
", doesDeviceSupportEarpiece=" + doesDeviceSupportEarpiece +
", shouldRunWithFocus=" + shouldRunWithFocus +
'}';
@@ -114,6 +134,7 @@
@Mock WiredHeadsetManager mockWiredHeadsetManager;
@Mock StatusBarNotifier mockStatusBarNotifier;
@Mock Call fakeCall;
+ @Mock InterruptionFilterProxy mMockInterruptionFilterProxy;
private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
private static final int TEST_TIMEOUT = 500;
@@ -138,10 +159,29 @@
when(mockCallsManager.getLock()).thenReturn(mLock);
when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
when(fakeCall.isAlive()).thenReturn(true);
+ setupInterruptionFilterMocks();
+
doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
any(CallAudioState.class));
}
+ private void setupInterruptionFilterMocks() {
+ // These mock implementations keep track of when the caller sets the current notification
+ // filter, and ensures the same value is returned via getCurrentInterruptionFilter.
+ final int objId = Objects.hashCode(mMockInterruptionFilterProxy);
+ when(mMockInterruptionFilterProxy.getCurrentInterruptionFilter()).thenReturn(
+ NotificationManager.INTERRUPTION_FILTER_ALL);
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock i) {
+ int requestedFilter = (int) i.getArguments()[0];
+ when(mMockInterruptionFilterProxy.getCurrentInterruptionFilter()).thenReturn(
+ requestedFilter);
+ return null;
+ }
+ }).when(mMockInterruptionFilterProxy).setInterruptionFilter(anyInt());
+ }
+
@LargeTest
public void testStateMachineTransitionsWithFocus() throws Throwable {
List<RoutingTestParameters> paramList = generateTransitionTests(true);
@@ -163,6 +203,7 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
true);
when(mockBluetoothManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
@@ -203,11 +244,13 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
true);
when(mockBluetoothManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(true);
when(mockAudioManager.isSpeakerphoneOn()).thenReturn(true);
+
CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH,
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH);
stateMachine.initialize(initState);
@@ -222,15 +265,16 @@
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
verifyNewSystemCallAudioState(initState, expectedEndState);
+ // Expecting to end up in earpiece, so we expect notifications to be filtered.
+ assertEquals(NotificationManager.INTERRUPTION_FILTER_ALARMS,
+ mMockInterruptionFilterProxy.getCurrentInterruptionFilter());
resetMocks();
-
stateMachine.sendMessageWithSessionInfo(
CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH);
stateMachine.sendMessageWithSessionInfo(
CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
-
assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState());
}
@@ -243,11 +287,13 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
true);
when(mockBluetoothManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(true);
when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false);
+
CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH,
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH);
stateMachine.initialize(initState);
@@ -257,6 +303,9 @@
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
verify(mockBluetoothManager, never()).connectBluetoothAudio();
+ // Shouldn't change interruption filter when in bluetooth route.
+ assertEquals(NotificationManager.INTERRUPTION_FILTER_ALL,
+ mMockInterruptionFilterProxy.getCurrentInterruptionFilter());
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
CallAudioRouteStateMachine.ACTIVE_FOCUS);
@@ -273,6 +322,7 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
true);
when(mockBluetoothManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
@@ -287,7 +337,6 @@
when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(true);
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
-
verify(mockBluetoothManager, never()).connectBluetoothAudio();
CallAudioState expectedEndState = new CallAudioState(false,
CallAudioState.ROUTE_BLUETOOTH,
@@ -373,6 +422,7 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
doesDeviceSupportEarpiece);
stateMachine.initialize();
assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
@@ -383,12 +433,15 @@
params.add(new RoutingTestParameters(
"Connect headset during earpiece", // name
CallAudioState.ROUTE_EARPIECE, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE, // availableRoutes
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -396,12 +449,15 @@
params.add(new RoutingTestParameters(
"Connect headset during bluetooth", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
NONE, // speakerInteraction
OFF, // bluetoothInteraction
CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // expectedAvai
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -409,12 +465,15 @@
params.add(new RoutingTestParameters(
"Connect headset during speakerphone", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE, // availableRoutes
OFF, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -422,12 +481,15 @@
params.add(new RoutingTestParameters(
"Disconnect headset during headset", // name
CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -435,12 +497,15 @@
params.add(new RoutingTestParameters(
"Disconnect headset during headset with bluetooth available", // name
CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -448,12 +513,15 @@
params.add(new RoutingTestParameters(
"Disconnect headset during bluetooth", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -461,12 +529,15 @@
params.add(new RoutingTestParameters(
"Disconnect headset during speakerphone", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -474,12 +545,15 @@
params.add(new RoutingTestParameters(
"Disconnect headset during speakerphone with bluetooth available", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -487,12 +561,15 @@
params.add(new RoutingTestParameters(
"Connect bluetooth during earpiece", // name
CallAudioState.ROUTE_EARPIECE, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE, // availableRoutes
NONE, // speakerInteraction
ON, // bluetoothInteraction
CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -500,12 +577,15 @@
params.add(new RoutingTestParameters(
"Connect bluetooth during wired headset", // name
CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes
NONE, // speakerInteraction
ON, // bluetoothInteraction
CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvai
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -513,12 +593,15 @@
params.add(new RoutingTestParameters(
"Connect bluetooth during speakerphone", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE, // availableRoutes
OFF, // speakerInteraction
ON, // bluetoothInteraction
CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -526,12 +609,31 @@
params.add(new RoutingTestParameters(
"Disconnect bluetooth during bluetooth without headset in", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
NONE, // speakerInteraction
OFF, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
+ true, // doesDeviceSupportEarpiece
+ shouldRunWithFocus
+ ));
+
+ params.add(new RoutingTestParameters(
+ "Disconnect bluetooth during bluetooth without headset in, priority mode ", // name
+ CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, // initialNotificationFilter
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
+ NONE, // speakerInteraction
+ OFF, // bluetoothInteraction
+ CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ CallAudioState.ROUTE_EARPIECE, // expectedRoute
+ CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -539,12 +641,15 @@
params.add(new RoutingTestParameters(
"Disconnect bluetooth during bluetooth with headset in", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
NONE, // speakerInteraction
OFF, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -552,12 +657,15 @@
params.add(new RoutingTestParameters(
"Disconnect bluetooth during speakerphone", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -565,12 +673,15 @@
params.add(new RoutingTestParameters(
"Disconnect bluetooth during earpiece", // name
CallAudioState.ROUTE_EARPIECE, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
NONE, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -578,12 +689,15 @@
params.add(new RoutingTestParameters(
"Switch to speakerphone from earpiece", // name
CallAudioState.ROUTE_EARPIECE, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE, // availableRoutes
ON, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_SPEAKER, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -591,12 +705,15 @@
params.add(new RoutingTestParameters(
"Switch to speakerphone from headset", // name
CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes
ON, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_SPEAKER, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -604,12 +721,15 @@
params.add(new RoutingTestParameters(
"Switch to speakerphone from bluetooth", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
ON, // speakerInteraction
OFF, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_SPEAKER, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // expectedAvai
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -617,12 +737,15 @@
params.add(new RoutingTestParameters(
"Switch to earpiece from bluetooth", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
NONE, // speakerInteraction
OFF, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_EARPIECE, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -630,12 +753,47 @@
params.add(new RoutingTestParameters(
"Switch to earpiece from speakerphone", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE, // availableRoutes
OFF, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_EARPIECE, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
+ true, // doesDeviceSupportEarpiece
+ shouldRunWithFocus
+ ));
+
+ params.add(new RoutingTestParameters(
+ "Switch to earpiece from speakerphone, priority notifications", // name
+ CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, // initialNotificationFilter
+ CallAudioState.ROUTE_EARPIECE, // availableRoutes
+ OFF, // speakerInteraction
+ NONE, // bluetoothInteraction
+ CallAudioRouteStateMachine.SWITCH_EARPIECE, // action
+ CallAudioState.ROUTE_EARPIECE, // expectedRoute
+ CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
+ true, // doesDeviceSupportEarpiece
+ shouldRunWithFocus
+ ));
+
+ params.add(new RoutingTestParameters(
+ "Switch to earpiece from speakerphone, silent mode", // name
+ CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_NONE, // initialNotificationFilter
+ CallAudioState.ROUTE_EARPIECE, // availableRoutes
+ OFF, // speakerInteraction
+ NONE, // bluetoothInteraction
+ CallAudioRouteStateMachine.SWITCH_EARPIECE, // action
+ CallAudioState.ROUTE_EARPIECE, // expectedRoute
+ CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_NONE, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -643,12 +801,15 @@
params.add(new RoutingTestParameters(
"Switch to bluetooth from speakerphone", // name
CallAudioState.ROUTE_SPEAKER, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
OFF, // speakerInteraction
ON, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_BLUETOOTH, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -656,12 +817,15 @@
params.add(new RoutingTestParameters(
"Switch to bluetooth from earpiece", // name
CallAudioState.ROUTE_EARPIECE, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
NONE, // speakerInteraction
ON, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_BLUETOOTH, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ true, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -669,12 +833,15 @@
params.add(new RoutingTestParameters(
"Switch to bluetooth from wired headset", // name
CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
NONE, // speakerInteraction
ON, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_BLUETOOTH, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // expectedAvai
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
true, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -682,12 +849,15 @@
params.add(new RoutingTestParameters(
"Switch from bluetooth to wired/earpiece when neither are available", // name
CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
ON, // speakerInteraction
OFF, // bluetoothInteraction
CallAudioRouteStateMachine.SWITCH_BASELINE_ROUTE, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
false, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -695,12 +865,15 @@
params.add(new RoutingTestParameters(
"Disconnect wired headset when device does not support earpiece", // name
CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes
ON, // speakerInteraction
NONE, // bluetoothInteraction
CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
false, // doesDeviceSupportEarpiece
shouldRunWithFocus
));
@@ -721,6 +894,8 @@
private void runParametrizedTestCaseWithFocus(final RoutingTestParameters params)
throws Throwable {
resetMocks();
+ when(mMockInterruptionFilterProxy.getCurrentInterruptionFilter()).thenReturn(
+ params.initialNotificationFilter);
// Construct a fresh state machine on every case
final CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
@@ -730,6 +905,7 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
params.doesDeviceSupportEarpiece);
// Set up bluetooth and speakerphone state
@@ -738,13 +914,14 @@
when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(
(params.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0
|| (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
- when(mockAudioManager.isSpeakerphoneOn()).thenReturn(
- params.initialRoute == CallAudioState.ROUTE_SPEAKER);
+ doReturn(params.initialRoute == CallAudioState.ROUTE_SPEAKER).when(mockAudioManager).
+ isSpeakerphoneOn();
// Set the initial CallAudioState object
final CallAudioState initState = new CallAudioState(false,
params.initialRoute, (params.availableRoutes | CallAudioState.ROUTE_SPEAKER));
stateMachine.initialize(initState);
+
// Make the state machine have focus so that we actually do something
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
CallAudioRouteStateMachine.ACTIVE_FOCUS);
@@ -752,6 +929,22 @@
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+ // Capture the changes made to the interruption filter and verify that the last change
+ // made to it matches the expected interruption filter.
+ if (params.isNotificationChangeExpected) {
+ ArgumentCaptor<Integer> interruptionCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockInterruptionFilterProxy, timeout(TEST_TIMEOUT).atLeastOnce())
+ .setInterruptionFilter(interruptionCaptor.capture());
+ List<Integer> interruptionFilterValues = interruptionCaptor.getAllValues();
+
+ int lastChange = interruptionFilterValues.get(interruptionFilterValues.size() - 1)
+ .intValue();
+ assertEquals(params.expectedNotificationFilter, lastChange);
+ } else {
+ Thread.sleep(TEST_TIMEOUT);
+ verify(mMockInterruptionFilterProxy, never()).setInterruptionFilter(anyInt());
+ }
+
stateMachine.quitStateMachine();
// Verify interactions with the speakerphone and bluetooth systems
@@ -797,6 +990,7 @@
mockWiredHeadsetManager,
mockStatusBarNotifier,
mAudioServiceFactory,
+ mMockInterruptionFilterProxy,
params.doesDeviceSupportEarpiece);
// Set up bluetooth and speakerphone state
@@ -857,7 +1051,9 @@
private void resetMocks() {
reset(mockAudioManager, mockBluetoothManager, mockCallsManager,
- mockConnectionServiceWrapper);
+ mockConnectionServiceWrapper, mMockInterruptionFilterProxy);
+ mMockInterruptionFilterProxy = mock(InterruptionFilterProxy.class);
+ setupInterruptionFilterMocks();
when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
when(mockCallsManager.getLock()).thenReturn(mLock);
doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index 7304ec1..590304c 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -31,6 +31,7 @@
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.telecom.DisconnectCause;
@@ -423,6 +424,7 @@
}
@MediumTest
+ @Postsubmit
public void testLogCallDirectionOutgoingWithMultiUserCapability() {
when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
.thenReturn(makeFakePhoneAccount(mOtherUserAccountHandle,
@@ -516,6 +518,7 @@
}
@MediumTest
+ @Postsubmit
public void testLogCallDirectionOutgoingFromManagedProfile() {
when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
.thenReturn(makeFakePhoneAccount(mManagedProfileAccountHandle, 0));
diff --git a/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java b/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
index a7602ce..2ae717d 100644
--- a/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
@@ -21,6 +21,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.test.suitebuilder.annotation.SmallTest;
import android.telecom.Logging.Session;
import com.android.internal.telephony.CallerInfo;
@@ -43,6 +44,7 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -93,6 +95,16 @@
}
}
+ @SmallTest
+ public void testLookupWithEmptyHandle() {
+ CallerInfoLookupHelper.OnQueryCompleteListener listener = mock(
+ CallerInfoLookupHelper.OnQueryCompleteListener.class);
+ mCallerInfoLookupHelper.startLookup(Uri.EMPTY, listener);
+
+ verify(listener).onCallerInfoQueryComplete(eq(Uri.EMPTY), isNull(CallerInfo.class));
+ verifyProperCleanup();
+ }
+
public void testSimpleLookup() {
CallerInfoLookupHelper.OnQueryCompleteListener listener = mock(
CallerInfoLookupHelper.OnQueryCompleteListener.class);
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 887d635..8d40966 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -103,24 +103,43 @@
@Override
public Connection onCreateOutgoingConnection(
PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
- mLatestConnection = new FakeConnection(request.getVideoState(), request.getAddress());
- return mLatestConnection;
+ FakeConnection fakeConnection = new FakeConnection(request.getVideoState(),
+ request.getAddress());
+ mLatestConnection = fakeConnection;
+ if (mCapabilities != NOT_SPECIFIED) {
+ fakeConnection.setConnectionCapabilities(mCapabilities);
+ }
+ if (mProperties != NOT_SPECIFIED) {
+ fakeConnection.setConnectionProperties(mProperties);
+ }
+ return fakeConnection;
}
@Override
public void onConference(Connection cxn1, Connection cxn2) {
- // Usually, this is implemented by something in Telephony, which does a bunch of radio
- // work to conference the two connections together. Here we just short-cut that and
- // declare them conferenced.
- Conference fakeConference = new FakeConference();
- fakeConference.addConnection(cxn1);
- fakeConference.addConnection(cxn2);
- mLatestConference = fakeConference;
- addConference(fakeConference);
+ if (((FakeConnection) cxn1).getIsConferenceCreated()) {
+ // Usually, this is implemented by something in Telephony, which does a bunch of
+ // radio work to conference the two connections together. Here we just short-cut
+ // that and declare them conferenced.
+ Conference fakeConference = new FakeConference();
+ fakeConference.addConnection(cxn1);
+ fakeConference.addConnection(cxn2);
+ mLatestConference = fakeConference;
+ addConference(fakeConference);
+ } else {
+ try {
+ sendSetConferenceMergeFailed(cxn1.getTelecomCallId());
+ } catch (Exception e) {
+ Log.w(this, "Exception on sendSetConferenceMergeFailed: " + e.getMessage());
+ }
+ }
}
}
public class FakeConnection extends Connection {
+ // Set to false if you wish the Conference merge to fail.
+ boolean mIsConferenceCreated = true;
+
public FakeConnection(int videoState, Uri address) {
super();
int capabilities = getConnectionCapabilities();
@@ -137,6 +156,14 @@
public void onExtrasChanged(Bundle extras) {
mExtrasLock.countDown();
}
+
+ public boolean getIsConferenceCreated() {
+ return mIsConferenceCreated;
+ }
+
+ public void setIsConferenceCreated(boolean isConferenceCreated) {
+ mIsConferenceCreated = isConferenceCreated;
+ }
}
public class FakeConference extends Conference {
@@ -205,6 +232,7 @@
c.videoState = request.getVideoState();
c.mockVideoProvider = new MockVideoProvider();
c.videoProvider = c.mockVideoProvider.getInterface();
+ c.isConferenceCreated = true;
mConnectionById.put(id, c);
mConnectionServiceDelegateAdapter.createConnection(connectionManagerPhoneAccount,
id, request, isIncoming, isUnknown, null /*Session.Info*/);
@@ -329,6 +357,7 @@
int videoState;
boolean isVoipAudioMode;
Bundle extras;
+ boolean isConferenceCreated;
}
public class ConferenceInfo {
@@ -418,6 +447,11 @@
}
}
+ public void sendSetConnectionProperties(String id) throws Exception {
+ for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
+ a.setConnectionProperties(id, mConnectionById.get(id).properties, null /*Session.Info*/);
+ }
+ }
public void sendSetIsConferenced(String id) throws Exception {
for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
a.setIsConferenced(id, mConnectionById.get(id).conferenceId, null /*Session.Info*/);
@@ -537,6 +571,12 @@
}
}
+ public void sendSetConferenceMergeFailed(String id) throws Exception {
+ for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
+ a.setConferenceMergeFailed(id, null /*Session.Info*/);
+ }
+ }
+
/**
* Waits until the {@link Connection#onExtrasChanged(Bundle)} API has been called on a
* {@link Connection} or {@link Conference}.
diff --git a/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java b/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java
index ac74604..2ebb6fc 100644
--- a/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java
@@ -42,7 +42,6 @@
public void setUp() throws Exception {
super.setUp();
- when(mCall.getHandle()).thenReturn(TEST_HANDLE);
}
@SmallTest
@@ -79,13 +78,32 @@
));
}
+ @SmallTest
+ public void testNullResponseFromLookupHelper() {
+ CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyLookupStart(null);
+
+ queryListener.onCallerInfoQueryComplete(null, null);
+ verify(mCallback).onCallFilteringComplete(mCall,
+ new CallFilteringResult(
+ true, // shouldAllowCall
+ false, // shouldReject
+ true, // shouldAddToCallLog
+ true // shouldShowNotification
+ ));
+ }
+
private CallerInfoLookupHelper.OnQueryCompleteListener verifyLookupStart() {
+ return verifyLookupStart(TEST_HANDLE);
+ }
+
+ private CallerInfoLookupHelper.OnQueryCompleteListener verifyLookupStart(Uri handle) {
+ when(mCall.getHandle()).thenReturn(handle);
DirectToVoicemailCallFilter filter =
new DirectToVoicemailCallFilter(mCallerInfoLookupHelper);
filter.startFilterLookup(mCall, mCallback);
ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> captor =
ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
- verify(mCallerInfoLookupHelper).startLookup(eq(TEST_HANDLE), captor.capture());
+ verify(mCallerInfoLookupHelper).startLookup(eq(handle), captor.capture());
return captor.getValue();
}
}
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index e86e4ae..de4d453 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
@@ -28,8 +29,8 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
-import android.telecom.ConnectionService;
import android.telecom.InCallService;
+import android.telecom.ParcelableCall;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.test.mock.MockContext;
@@ -38,6 +39,7 @@
import com.android.internal.telecom.IInCallAdapter;
import com.android.internal.telecom.IInCallService;
+import com.android.server.telecom.Analytics;
import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
@@ -47,6 +49,7 @@
import com.android.server.telecom.SystemStateProvider;
import com.android.server.telecom.TelecomServiceImpl.DefaultDialerManagerAdapter;
import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.Timeouts;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -54,17 +57,14 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.util.Collections;
import java.util.LinkedList;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyChar;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -83,6 +83,7 @@
@Mock Resources mMockResources;
@Mock MockContext mMockContext;
@Mock DefaultDialerManagerAdapter mMockDefaultDialerAdapter;
+ @Mock Timeouts.Adapter mTimeoutsAdapter;
private static final int CURRENT_USER_ID = 900973;
private static final String DEF_PKG = "defpkg";
@@ -100,11 +101,12 @@
public void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
+ when(mMockCall.getAnalytics()).thenReturn(new Analytics.CallInfo());
doReturn(mMockResources).when(mMockContext).getResources();
doReturn(SYS_PKG).when(mMockResources).getString(R.string.ui_default_package);
doReturn(SYS_CLASS).when(mMockResources).getString(R.string.incall_default_class);
mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
- mMockSystemStateProvider, mMockDefaultDialerAdapter);
+ mMockSystemStateProvider, mMockDefaultDialerAdapter, mTimeoutsAdapter);
}
@Override
@@ -118,11 +120,9 @@
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
when(mMockCall.isIncoming()).thenReturn(true);
+ when(mMockCall.isExternalCall()).thenReturn(false);
- Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
- when(mMockPackageManager.queryIntentServicesAsUser(
- queryIntent, PackageManager.GET_META_DATA, CURRENT_USER_ID))
- .thenReturn(new LinkedList<ResolveInfo>());
+ setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -150,11 +150,10 @@
when(mMockCall.isIncoming()).thenReturn(false);
when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mMockCall.getIntentExtras()).thenReturn(callExtras);
+ when(mMockCall.isExternalCall()).thenReturn(false);
Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
- when(mMockPackageManager.queryIntentServicesAsUser(
- queryIntent, PackageManager.GET_META_DATA, CURRENT_USER_ID))
- .thenReturn(new LinkedList<ResolveInfo>());
+ setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -185,36 +184,18 @@
when(mMockCall.isIncoming()).thenReturn(false);
when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mMockCall.getIntentExtras()).thenReturn(callExtras);
+ when(mMockCall.isExternalCall()).thenReturn(false);
when(mMockDefaultDialerAdapter.getDefaultDialerApplication(mMockContext, CURRENT_USER_ID))
.thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
- Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
- when(mMockPackageManager.queryIntentServicesAsUser(
- any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID)))
- .thenReturn(new LinkedList<ResolveInfo>() {{
- add(new ResolveInfo() {{
- serviceInfo = new ServiceInfo();
- serviceInfo.packageName = DEF_PKG;
- serviceInfo.name = DEF_CLASS;
- serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
- serviceInfo.metaData = new Bundle();
- serviceInfo.metaData.putBoolean(
- TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
- }});
- add(new ResolveInfo() {{
- serviceInfo = new ServiceInfo();
- serviceInfo.packageName = SYS_PKG;
- serviceInfo.name = SYS_CLASS;
- serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
- }});
- }});
+ setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mMockPackageManager, times(3)).queryIntentServicesAsUser(
+ verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
queryIntentCaptor.capture(),
eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
@@ -253,37 +234,20 @@
when(mMockCall.isIncoming()).thenReturn(false);
when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mMockCall.getIntentExtras()).thenReturn(callExtras);
+ when(mMockCall.isExternalCall()).thenReturn(false);
when(mMockDefaultDialerAdapter.getDefaultDialerApplication(mMockContext, CURRENT_USER_ID))
.thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.CURRENT))).thenReturn(true);
- Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
- when(mMockPackageManager.queryIntentServicesAsUser(
- any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID)))
- .thenReturn(new LinkedList<ResolveInfo>() {{
- add(new ResolveInfo() {{
- serviceInfo = new ServiceInfo();
- serviceInfo.packageName = DEF_PKG;
- serviceInfo.name = DEF_CLASS;
- serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
- serviceInfo.metaData = new Bundle();
- serviceInfo.metaData.putBoolean(
- TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
- }});
- add(new ResolveInfo() {{
- serviceInfo = new ServiceInfo();
- serviceInfo.packageName = SYS_PKG;
- serviceInfo.name = SYS_CLASS;
- serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
- }});
- }});
+ setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+
mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mMockPackageManager, times(3)).queryIntentServicesAsUser(
+ verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
queryIntentCaptor.capture(),
eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
@@ -319,40 +283,26 @@
when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
+ when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
+ when(mMockCallsManager.getAudioState()).thenReturn(null);
+ when(mMockCallsManager.canAddCall()).thenReturn(false);
when(mMockCall.isIncoming()).thenReturn(false);
when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mMockCall.getIntentExtras()).thenReturn(callExtras);
+ when(mMockCall.isExternalCall()).thenReturn(false);
+ when(mMockCall.getConferenceableCalls()).thenReturn(Collections.emptyList());
when(mMockDefaultDialerAdapter.getDefaultDialerApplication(mMockContext, CURRENT_USER_ID))
.thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(
any(Intent.class), any(ServiceConnection.class), anyInt(), any(UserHandle.class)))
.thenReturn(true);
- Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
- when(mMockPackageManager.queryIntentServicesAsUser(
- any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID)))
- .thenReturn(new LinkedList<ResolveInfo>() {{
- add(new ResolveInfo() {{
- serviceInfo = new ServiceInfo();
- serviceInfo.packageName = DEF_PKG;
- serviceInfo.name = DEF_CLASS;
- serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
- serviceInfo.metaData = new Bundle();
- serviceInfo.metaData.putBoolean(
- TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
- }});
- add(new ResolveInfo() {{
- serviceInfo = new ServiceInfo();
- serviceInfo.packageName = SYS_PKG;
- serviceInfo.name = SYS_CLASS;
- serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
- }});
- }});
+ setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mMockPackageManager, times(3)).queryIntentServicesAsUser(
+ verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
queryIntentCaptor.capture(),
eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
@@ -408,4 +358,164 @@
assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
}
+
+ /**
+ * Ensures that the {@link InCallController} will bind to an {@link InCallService} which
+ * supports external calls.
+ */
+ @MediumTest
+ public void testBindToService_IncludeExternal() throws Exception {
+ setupMocks(true /* isExternalCall */);
+ setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+ mInCallController.bindToServices(mMockCall);
+
+ // Query for the different InCallServices
+ ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
+ queryIntentCaptor.capture(),
+ eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+
+ // Verify call for default dialer InCallService
+ assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
+ // Verify call for car-mode InCallService
+ assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
+ // Verify call for non-UI InCallServices
+ assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
+
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(1)).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.CURRENT));
+
+ Intent bindIntent = bindIntentCaptor.getValue();
+ assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+ assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
+ assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
+ }
+
+ /**
+ * Make sure that if a call goes away before the in-call service finishes binding and another
+ * call gets connected soon after, the new call will still be sent to the in-call service.
+ */
+ @MediumTest
+ public void testUnbindDueToCallDisconnect() throws Exception {
+ when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
+ when(mMockCall.isIncoming()).thenReturn(true);
+ when(mMockCall.isExternalCall()).thenReturn(false);
+ when(mMockDefaultDialerAdapter.getDefaultDialerApplication(mMockContext, CURRENT_USER_ID))
+ .thenReturn(DEF_PKG);
+ when(mMockContext.bindServiceAsUser(
+ any(Intent.class), any(ServiceConnection.class), anyInt(), any(UserHandle.class)))
+ .thenReturn(true);
+ when(mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(any(ContentResolver.class)))
+ .thenReturn(500L);
+
+ when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
+ setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+ mInCallController.bindToServices(mMockCall);
+
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+ ArgumentCaptor.forClass(ServiceConnection.class);
+ verify(mMockContext, times(1)).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ serviceConnectionCaptor.capture(),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.CURRENT));
+
+ // Pretend that the call has gone away.
+ when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
+ mInCallController.onCallRemoved(mMockCall);
+
+ // Start the connection, make sure we don't unbind, and make sure that we don't send
+ // anything to the in-call service yet.
+ ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
+ ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
+ IBinder mockBinder = mock(IBinder.class);
+ IInCallService mockInCallService = mock(IInCallService.class);
+ when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
+
+ serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
+ verify(mockInCallService).setInCallAdapter(any(IInCallAdapter.class));
+ verify(mMockContext, never()).unbindService(serviceConnection);
+ verify(mockInCallService, never()).addCall(any(ParcelableCall.class));
+
+ // Now, we add in the call again and make sure that it's sent to the InCallService.
+ when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
+ mInCallController.onCallAdded(mMockCall);
+ verify(mockInCallService).addCall(any(ParcelableCall.class));
+ }
+
+ private void setupMocks(boolean isExternalCall) {
+ when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
+ when(mMockCall.isIncoming()).thenReturn(false);
+ when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
+ when(mMockDefaultDialerAdapter.getDefaultDialerApplication(mMockContext, CURRENT_USER_ID))
+ .thenReturn(DEF_PKG);
+ when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
+ anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
+ when(mMockCall.isExternalCall()).thenReturn(isExternalCall);
+ }
+
+ private ResolveInfo getDefResolveInfo(final boolean includeExternalCalls) {
+ return new ResolveInfo() {{
+ serviceInfo = new ServiceInfo();
+ serviceInfo.packageName = DEF_PKG;
+ serviceInfo.name = DEF_CLASS;
+ serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+ serviceInfo.metaData = new Bundle();
+ serviceInfo.metaData.putBoolean(
+ TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
+ if (includeExternalCalls) {
+ serviceInfo.metaData.putBoolean(
+ TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
+ }
+ }};
+ }
+
+ private ResolveInfo getSysResolveinfo() {
+ return new ResolveInfo() {{
+ serviceInfo = new ServiceInfo();
+ serviceInfo.packageName = SYS_PKG;
+ serviceInfo.name = SYS_CLASS;
+ serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+ }};
+ }
+
+ private void setupMockPackageManager(final boolean useDefaultDialer,
+ final boolean useSystemDialer, final boolean includeExternalCalls) {
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ Intent intent = (Intent) args[0];
+ String packageName = intent.getPackage();
+ ComponentName componentName = intent.getComponent();
+ if (componentName != null) {
+ packageName = componentName.getPackageName();
+ }
+ LinkedList<ResolveInfo> resolveInfo = new LinkedList<ResolveInfo>();
+ if (!TextUtils.isEmpty(packageName)) {
+ if ((TextUtils.isEmpty(packageName) || packageName.equals(DEF_PKG)) &&
+ useDefaultDialer) {
+ resolveInfo.add(getDefResolveInfo(includeExternalCalls));
+ }
+
+ if ((TextUtils.isEmpty(packageName) || packageName.equals(SYS_PKG)) &&
+ useSystemDialer) {
+ resolveInfo.add(getSysResolveinfo());
+ }
+ }
+ return resolveInfo;
+ }
+ }).when(mMockPackageManager).queryIntentServicesAsUser(
+ any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
index 12e7280..2663356 100644
--- a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
@@ -43,6 +43,7 @@
import com.android.server.telecom.Constants;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
import com.android.server.telecom.TelecomBroadcastIntentProcessor;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.components.TelecomBroadcastReceiver;
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index a7d98db..54613d4 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -38,6 +38,7 @@
import com.android.server.telecom.NewOutgoingCallIntentBroadcaster;
import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
+import com.android.server.telecom.TelecomSystem;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -77,6 +78,7 @@
mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
mPhoneNumberUtilsAdapterSpy = spy(new PhoneNumberUtilsAdapterImpl());
when(mCall.getInitiatingUser()).thenReturn(UserHandle.CURRENT);
+ when(mCallsManager.getLock()).thenReturn(new TelecomSystem.SyncRoot() { });
}
@SmallTest
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index e50fe10..7b5b836 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -171,8 +171,7 @@
public void testAccounts() throws Exception {
int i = 0;
- mComponentContextFixture.addConnectionService(
- makeQuickConnectionServiceComponentName(),
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
Mockito.mock(IConnectionService.class));
registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
@@ -205,8 +204,7 @@
@MediumTest
public void testDefaultOutgoing() throws Exception {
- mComponentContextFixture.addConnectionService(
- makeQuickConnectionServiceComponentName(),
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
Mockito.mock(IConnectionService.class));
// By default, there is no default outgoing account (nothing has been registered)
@@ -253,6 +251,229 @@
}
@MediumTest
+ public void testReplacePhoneAccountByGroup() throws Exception {
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+
+ // By default, there is no default outgoing account (nothing has been registered)
+ assertNull(
+ mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
+
+ // Register one tel: account
+ PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
+ PhoneAccountHandle defaultAccount =
+ mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
+ assertEquals(telAccount1, defaultAccount);
+
+ // Add call capable SIP account, make sure tel: doesn't change
+ PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct");
+ registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .build());
+ defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
+ PhoneAccount.SCHEME_TEL);
+ assertEquals(telAccount1, defaultAccount);
+
+ // Replace tel: account with another in the same Group
+ PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
+ PhoneAccount.SCHEME_TEL);
+ assertEquals(telAccount2, defaultAccount);
+ assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
+ }
+
+ @MediumTest
+ public void testAddSameDefault() throws Exception {
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+
+ // By default, there is no default outgoing account (nothing has been registered)
+ assertNull(
+ mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
+
+ // Register one tel: account
+ PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
+ PhoneAccountHandle defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertEquals(telAccount1, defaultAccount);
+ mRegistrar.unregisterPhoneAccount(telAccount1);
+
+ // Register Emergency Account and unregister
+ PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct");
+ registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .build());
+ defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertNull(defaultAccount);
+ mRegistrar.unregisterPhoneAccount(emerAccount);
+
+ // Re-register the same account and make sure the default is in place
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertEquals(telAccount1, defaultAccount);
+ }
+
+ @MediumTest
+ public void testAddSameGroup() throws Exception {
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+
+ // By default, there is no default outgoing account (nothing has been registered)
+ assertNull(
+ mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
+
+ // Register one tel: account
+ PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
+ PhoneAccountHandle defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertEquals(telAccount1, defaultAccount);
+ mRegistrar.unregisterPhoneAccount(telAccount1);
+
+ // Register Emergency Account and unregister
+ PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct");
+ registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .build());
+ defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertNull(defaultAccount);
+ mRegistrar.unregisterPhoneAccount(emerAccount);
+
+ // Re-register a new account with the same group
+ PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertEquals(telAccount2, defaultAccount);
+ }
+
+ @MediumTest
+ public void testAddSameGroupButDifferentComponent() throws Exception {
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+
+ // By default, there is no default outgoing account (nothing has been registered)
+ assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
+ PhoneAccount.SCHEME_TEL));
+
+ // Register one tel: account
+ PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
+ PhoneAccountHandle defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertEquals(telAccount1, defaultAccount);
+ assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
+
+ // Register a new account with the same group, but different Component, so don't replace
+ // Default
+ PhoneAccountHandle telAccount2 = makeQuickAccountHandle(
+ new ComponentName("other1", "other2"), "tel_acct2");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount2));
+
+ defaultAccount =
+ mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
+ assertEquals(telAccount1, defaultAccount);
+ }
+
+ @MediumTest
+ public void testAddSameGroupButDifferentComponent2() throws Exception {
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+
+ // By default, there is no default outgoing account (nothing has been registered)
+ assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
+ PhoneAccount.SCHEME_TEL));
+
+ // Register first tel: account
+ PhoneAccountHandle telAccount1 = makeQuickAccountHandle(
+ new ComponentName("other1", "other2"), "tel_acct1");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+ assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
+ mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
+
+ // Register second account with the same group, but a second Component, so don't replace
+ // Default
+ PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+
+ PhoneAccountHandle defaultAccount =
+ mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
+ assertEquals(telAccount1, defaultAccount);
+
+ // Register third account with the second component name, but same group id
+ PhoneAccountHandle telAccount3 = makeQuickAccountHandle("tel_acct3");
+ registerAndEnableAccount(new PhoneAccount.Builder(telAccount3, "tel_acct3")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setGroupId("testGroup")
+ .build());
+
+ // Make sure that the default account is still the original PhoneAccount and that the
+ // second PhoneAccount with the second ComponentName was replaced by the third PhoneAccount
+ defaultAccount =
+ mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
+ assertEquals(telAccount1, defaultAccount);
+
+ assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
+ assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount2));
+ assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount3));
+ }
+
+ @MediumTest
public void testPhoneAccountParceling() throws Exception {
PhoneAccountHandle handle = makeQuickAccountHandle("foo");
roundTripPhoneAccount(new PhoneAccount.Builder(handle, null).build());
@@ -268,6 +489,7 @@
.setShortDescription("short description")
.setSubscriptionAddress(Uri.parse("tel:2345678"))
.setSupportedUriSchemes(Arrays.asList("tel", "sip"))
+ .setGroupId("testGroup")
.build());
roundTripPhoneAccount(
new PhoneAccount.Builder(handle, "foo")
@@ -281,6 +503,7 @@
.setShortDescription("short description")
.setSubscriptionAddress(Uri.parse("tel:2345678"))
.setSupportedUriSchemes(Arrays.asList("tel", "sip"))
+ .setGroupId("testGroup")
.build());
}
@@ -291,10 +514,11 @@
}
private static PhoneAccountHandle makeQuickAccountHandle(String id) {
- return new PhoneAccountHandle(
- makeQuickConnectionServiceComponentName(),
- id,
- Process.myUserHandle());
+ return makeQuickAccountHandle(makeQuickConnectionServiceComponentName(), id);
+ }
+
+ private static PhoneAccountHandle makeQuickAccountHandle(ComponentName name, String id) {
+ return new PhoneAccountHandle(name, id, Process.myUserHandle());
}
private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
@@ -457,7 +681,8 @@
new ComponentName("pkg0", "cls0"), "id0");
UserHandle userHandle = phoneAccountHandle.getUserHandle();
s.defaultOutgoingAccountHandles
- .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle));
+ .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle,
+ "testGroup"));
return s;
}
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index d4fd8e3..af7f0b5 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -61,6 +62,8 @@
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioRouteStateMachine;
+import com.android.server.telecom.CallerInfoAsyncQueryFactory;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.CallsManagerListenerBase;
@@ -68,6 +71,7 @@
import com.android.server.telecom.HeadsetMediaButtonFactory;
import com.android.server.telecom.InCallWakeLockController;
import com.android.server.telecom.InCallWakeLockControllerFactory;
+import com.android.server.telecom.InterruptionFilterProxy;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.PhoneNumberUtilsAdapter;
@@ -76,6 +80,7 @@
import com.android.server.telecom.ProximitySensorManagerFactory;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
+import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
@@ -88,6 +93,8 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Implements mocks and functionality required to implement telecom system tests.
@@ -161,11 +168,25 @@
}
}
PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter = new EmergencyNumberUtilsAdapter();
+
+ public static class MockInterruptionFilterProxy implements InterruptionFilterProxy {
+ private int mInterruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALL;
+ @Override
+ public void setInterruptionFilter(int interruptionFilter) {
+ mInterruptionFilter = interruptionFilter;
+ }
+
+ @Override
+ public int getCurrentInterruptionFilter() {
+ return mInterruptionFilter;
+ }
+ }
@Mock HeadsetMediaButton mHeadsetMediaButton;
@Mock ProximitySensorManager mProximitySensorManager;
@Mock InCallWakeLockController mInCallWakeLockController;
@Mock BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
@Mock AsyncRingtonePlayer mAsyncRingtonePlayer;
+ @Mock InterruptionFilterProxy mInterruptionFilterProxy;
final ComponentName mInCallServiceComponentNameX =
new ComponentName(
@@ -209,7 +230,8 @@
.addSupportedUriScheme("tel")
.setCapabilities(
PhoneAccount.CAPABILITY_CALL_PROVIDER |
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+ PhoneAccount.CAPABILITY_VIDEO_CALLING)
.build();
final PhoneAccount mPhoneAccountB0 =
PhoneAccount.builder(
@@ -220,7 +242,8 @@
.addSupportedUriScheme("tel")
.setCapabilities(
PhoneAccount.CAPABILITY_CALL_PROVIDER |
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+ PhoneAccount.CAPABILITY_VIDEO_CALLING)
.build();
final PhoneAccount mPhoneAccountE0 =
PhoneAccount.builder(
@@ -374,7 +397,8 @@
},
mTimeoutsAdapter,
mAsyncRingtonePlayer,
- mPhoneNumberUtilsAdapter);
+ mPhoneNumberUtilsAdapter,
+ mInterruptionFilterProxy);
mComponentContextFixture.setTelecomManager(new TelecomManager(
mComponentContextFixture.getTestDouble(),
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index adef66b..4764e92 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -21,6 +21,7 @@
import android.os.RemoteException;
import android.telecom.CallAudioState;
import android.telecom.VideoProfile;
+import android.test.suitebuilder.annotation.MediumTest;
import com.android.server.telecom.CallAudioModeStateMachine;
import com.android.server.telecom.CallAudioRouteStateMachine;
@@ -41,6 +42,7 @@
* Tests to ensure an incoming video-call is automatically routed to the speakerphone when
* the call is answered and neither a wired headset nor bluetooth headset are connected.
*/
+ @MediumTest
public void testAutoSpeakerphoneIncomingBidirectional() throws Exception {
// Start an incoming video call.
IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
@@ -56,6 +58,7 @@
* always answer incoming video calls as bi-directional. It is, however, possible for a third
* party dialer to answer an incoming video call a a one-way video call.
*/
+ @MediumTest
public void testAutoSpeakerphoneIncomingReceiveOnly() throws Exception {
// Start an incoming video call.
IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
@@ -69,6 +72,7 @@
* Tests audio routing for an outgoing video call made with bidirectional video. Expect to be
* in speaker mode.
*/
+ @MediumTest
public void testAutoSpeakerphoneOutgoingBidirectional() throws Exception {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
@@ -83,6 +87,7 @@
* in speaker mode. Note: The default UI does not support making one-way video calls, but the
* APIs do and a third party incall UI could choose to support that.
*/
+ @MediumTest
public void testAutoSpeakerphoneOutgoingTransmitOnly() throws Exception {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
@@ -97,6 +102,7 @@
* in speaker mode. Note: The default UI does not support making one-way video calls, but the
* APIs do and a third party incall UI could choose to support that.
*/
+ @MediumTest
public void testNoAutoSpeakerphoneOnOutgoing() throws Exception {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
@@ -109,6 +115,7 @@
/**
* Tests to ensure an incoming audio-only call is routed to the earpiece.
*/
+ @MediumTest
public void testNoAutoSpeakerphoneOnIncoming() throws Exception {
// Start an incoming video call.
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
index 44cdae0..cca6446 100644
--- a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
@@ -33,6 +33,7 @@
import android.telecom.VideoCallImpl;
import android.telecom.VideoProfile;
import android.telecom.VideoProfile.CameraCapabilities;
+import android.test.suitebuilder.annotation.MediumTest;
import android.view.Surface;
import com.google.common.base.Predicate;
@@ -114,6 +115,7 @@
* and {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)}
* APIS.
*/
+ @MediumTest
public void testCameraChange() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)
@@ -147,6 +149,7 @@
* Tests the {@link VideoCall#setPreviewSurface(Surface)} and
* {@link VideoProvider#onSetPreviewSurface(Surface)} APIs.
*/
+ @MediumTest
public void testSetPreviewSurface() throws Exception {
final Surface surface = new Surface(new SurfaceTexture(1));
mVideoCall.setPreviewSurface(surface);
@@ -172,6 +175,7 @@
* Tests the {@link VideoCall#setDisplaySurface(Surface)} and
* {@link VideoProvider#onSetDisplaySurface(Surface)} APIs.
*/
+ @MediumTest
public void testSetDisplaySurface() throws Exception {
final Surface surface = new Surface(new SurfaceTexture(1));
mVideoCall.setDisplaySurface(surface);
@@ -197,6 +201,7 @@
* Tests the {@link VideoCall#setDeviceOrientation(int)} and
* {@link VideoProvider#onSetDeviceOrientation(int)} APIs.
*/
+ @MediumTest
public void testSetDeviceOrientation() throws Exception {
mVideoCall.setDeviceOrientation(ORIENTATION_0);
@@ -220,6 +225,7 @@
/**
* Tests the {@link VideoCall#setZoom(float)} and {@link VideoProvider#onSetZoom(float)} APIs.
*/
+ @MediumTest
public void testSetZoom() throws Exception {
mVideoCall.setZoom(ZOOM_LEVEL);
@@ -241,6 +247,7 @@
* Emulates a scenario where an InCallService sends a request to upgrade to video, which the
* peer accepts as-is.
*/
+ @MediumTest
public void testSessionModifyRequest() throws Exception {
VideoProfile requestProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL);
@@ -278,6 +285,7 @@
* Tests the {@link VideoCall#sendSessionModifyResponse(VideoProfile)},
* and {@link VideoProvider#onSendSessionModifyResponse(VideoProfile)} APIs.
*/
+ @MediumTest
public void testSessionModifyResponse() throws Exception {
VideoProfile sessionModifyResponse = new VideoProfile(VideoProfile.STATE_TX_ENABLED);
@@ -298,6 +306,7 @@
* {@link VideoProvider#onRequestCameraCapabilities()} ()}, and
* {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} APIs.
*/
+ @MediumTest
public void testRequestCameraCapabilities() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)
@@ -315,6 +324,7 @@
* Tests the {@link VideoCall#setPauseImage(Uri)}, and
* {@link VideoProvider#onSetPauseImage(Uri)} APIs.
*/
+ @MediumTest
public void testSetPauseImage() throws Exception {
final Uri testUri = Uri.fromParts("file", "test.jpg", null);
mVideoCall.setPauseImage(testUri);
@@ -333,6 +343,7 @@
* {@link VideoProvider#onRequestConnectionDataUsage()}, and
* {@link VideoCall.Callback#onCallDataUsageChanged(long)} APIs.
*/
+ @MediumTest
public void testRequestDataUsage() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)
@@ -350,6 +361,7 @@
* Tests the {@link VideoProvider#receiveSessionModifyRequest(VideoProfile)},
* {@link VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} APIs.
*/
+ @MediumTest
public void testReceiveSessionModifyRequest() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)
@@ -372,6 +384,7 @@
* Tests the {@link VideoProvider#handleCallSessionEvent(int)}, and
* {@link VideoCall.Callback#onCallSessionEvent(int)} APIs.
*/
+ @MediumTest
public void testSessionEvent() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)
@@ -390,6 +403,7 @@
* Tests the {@link VideoProvider#changePeerDimensions(int, int)} and
* {@link VideoCall.Callback#onPeerDimensionsChanged(int, int)} APIs.
*/
+ @MediumTest
public void testPeerDimensionChange() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)
@@ -409,6 +423,7 @@
* Tests the {@link VideoProvider#changeVideoQuality(int)} and
* {@link VideoCall.Callback#onVideoQualityChanged(int)} APIs.
*/
+ @MediumTest
public void testVideoQualityChange() throws Exception {
// Wait until the callback has been received before performing verification.
doAnswer(mVerification).when(mVideoCallCallback)