summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Pasanen <dan.pasanen@gmail.com>2017-04-05 08:59:17 -0500
committerDan Pasanen <dan.pasanen@gmail.com>2017-04-05 13:20:35 -0500
commit7099d766dc334ddbe9317e6d3c4395fe37e421d6 (patch)
tree533f40d3d389f4dd462488c92be4966b98bc5b17
parent1d870ae06b0bef6ed7ee7e459e270dee22b2371a (diff)
parentad18dc9e336c73922192e1693a836781cff6c929 (diff)
downloadandroid_packages_services_Telecomm-staging/cm-14.1_android-7.1.2_r2.tar.gz
android_packages_services_Telecomm-staging/cm-14.1_android-7.1.2_r2.tar.bz2
android_packages_services_Telecomm-staging/cm-14.1_android-7.1.2_r2.zip
Merge tag 'android-7.1.2_r2' into cm-14.1staging/cm-14.1_android-7.1.2_r2
Android 7.1.2 Release 2 (N2G47E) Change-Id: I7d921a147376e4c7b065c538023e4d9a43cbbdb2
-rw-r--r--res/values-bs-rBA/strings.xml10
-rw-r--r--res/values-eu-rES/strings.xml2
-rw-r--r--res/values-hi/strings.xml2
-rw-r--r--res/values-hy-rAM/strings.xml2
-rw-r--r--res/values-it/strings.xml6
-rw-r--r--res/values-km-rKH/strings.xml2
-rw-r--r--res/values-kn-rIN/strings.xml4
-rw-r--r--res/values-ne-rNP/strings.xml2
-rw-r--r--res/values-pa-rIN/strings.xml2
-rw-r--r--res/values-ru/strings.xml2
-rw-r--r--res/values-si-rLK/strings.xml2
-rw-r--r--res/values-sk/strings.xml4
-rw-r--r--res/values/config.xml9
-rw-r--r--src/com/android/server/telecom/Analytics.java9
-rw-r--r--src/com/android/server/telecom/BluetoothPhoneServiceImpl.java5
-rw-r--r--src/com/android/server/telecom/Call.java39
-rw-r--r--src/com/android/server/telecom/CallAudioManager.java6
-rw-r--r--src/com/android/server/telecom/CallAudioRouteStateMachine.java104
-rw-r--r--src/com/android/server/telecom/CallsManager.java46
-rw-r--r--src/com/android/server/telecom/InterruptionFilterProxy.java1
-rw-r--r--src/com/android/server/telecom/Log.java3
-rw-r--r--src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java22
-rw-r--r--src/com/android/server/telecom/ParcelableCallUtils.java5
-rw-r--r--src/com/android/server/telecom/PhoneAccountRegistrar.java14
-rw-r--r--src/com/android/server/telecom/Ringer.java34
-rw-r--r--src/com/android/server/telecom/Timeouts.java11
-rw-r--r--src/com/android/server/telecom/components/TelecomService.java10
-rw-r--r--src/com/android/server/telecom/ui/MissedCallNotifierImpl.java64
-rw-r--r--tests/src/com/android/server/telecom/tests/AnalyticsTests.java21
-rw-r--r--tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java66
-rw-r--r--tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java47
-rw-r--r--tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java2
-rw-r--r--tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java25
-rw-r--r--tests/src/com/android/server/telecom/tests/TelecomSystemTest.java5
34 files changed, 467 insertions, 121 deletions
diff --git a/res/values-bs-rBA/strings.xml b/res/values-bs-rBA/strings.xml
index fd5beff6..e1571b33 100644
--- a/res/values-bs-rBA/strings.xml
+++ b/res/values-bs-rBA/strings.xml
@@ -52,18 +52,18 @@
<string name="blocked_numbers" msgid="2751843139572970579">"Blokirani brojevi"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Nećete primati pozive i poruke od blokiranih brojeva."</string>
<string name="block_number" msgid="1101252256321306179">"Dodaj broj"</string>
- <string name="unblock_dialog_body" msgid="1614238499771862793">"Odblokirati <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
- <string name="unblock_button" msgid="3078048901972674170">"Odblokiraj"</string>
+ <string name="unblock_dialog_body" msgid="1614238499771862793">"Deblokirati <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
+ <string name="unblock_button" msgid="3078048901972674170">"Deblokiraj"</string>
<string name="add_blocked_dialog_body" msgid="9030243212265516828">"Blokiraj pozive i tekstualne poruke od"</string>
- <string name="add_blocked_number_hint" msgid="6847675097085433553">"Telefonski broj"</string>
+ <string name="add_blocked_number_hint" msgid="6847675097085433553">"Broj telefona"</string>
<string name="block_button" msgid="8822290682524373357">"Blokiraj"</string>
<string name="non_primary_user" msgid="5180129233352533459">"Samo vlasnik uređaja može pregledati i upravljati blokiranim brojevima."</string>
- <string name="delete_icon_description" msgid="8903995728252556724">"Odblokiraj"</string>
+ <string name="delete_icon_description" msgid="8903995728252556724">"Deblokiraj"</string>
<string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"Blokiranje je privremeno isključeno"</string>
<string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Nakon što pozovete ili pošaljete poruku na broj za hitne slučajeve, blokiranje se isključuje da bi vas hitna služba mogla kontaktirati."</string>
<string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Ponovo omogući sada"</string>
<string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> je blokiran"</string>
- <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> je odblokiran"</string>
+ <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> je deblokiran"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Nije moguće blokirati broj za hitne slučajeve."</string>
<string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> je već blokiran."</string>
<string name="toast_personal_call_msg" msgid="5115361633476779723">"Za upućivanje poziva koristi se lična brojčana tastatura"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 7f2ef593..1dd4963f 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -19,7 +19,7 @@
<string name="telecommAppLabel" product="default" msgid="382363169988504520">"Deien kudeaketa"</string>
<string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Telefonoa"</string>
<string name="unknown" msgid="6878797917991465859">"Ezezaguna"</string>
- <string name="notification_missedCallTitle" msgid="7554385905572364535">"Dei galdua"</string>
+ <string name="notification_missedCallTitle" msgid="7554385905572364535">"Galdutako deia"</string>
<string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"Laneko dei bat galdu duzu"</string>
<string name="notification_missedCallsTitle" msgid="1361677948941502522">"Dei galduak"</string>
<string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> dei galdu"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 874712d8..2aafb5f9 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -54,7 +54,7 @@
<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-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 7c6d12b2..94696a74 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -50,7 +50,7 @@
<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="blocked_numbers_msg" msgid="1045015186124965643">"Արգելափակված համարներից զանգեր և SMS-ներ չեք ստանա:"</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>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 716f765c..8139609b 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -19,10 +19,10 @@
<string name="telecommAppLabel" product="default" msgid="382363169988504520">"Gestione chiamate"</string>
<string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Telefono"</string>
<string name="unknown" msgid="6878797917991465859">"Sconosciuto"</string>
- <string name="notification_missedCallTitle" msgid="7554385905572364535">"Chiamata senza risposta"</string>
+ <string name="notification_missedCallTitle" msgid="7554385905572364535">"Chiamata persa"</string>
<string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"Chiamata di lavoro persa"</string>
- <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Chiamate senza risposta"</string>
- <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> chiamate senza risposta"</string>
+ <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Chiamate perse"</string>
+ <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> chiamate perse"</string>
<string name="notification_missedCallTicker" msgid="504686252427747209">"Chiamata senza risposta da <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
<string name="notification_missedCall_call_back" msgid="2684890353590890187">"Richiama"</string>
<string name="notification_missedCall_message" msgid="3049928912736917988">"Messaggio"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index f3fa21b1..fa81963c 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -50,7 +50,7 @@
<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="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>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 7ae3a29e..86834d90 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>
@@ -47,7 +47,7 @@
<string name="add_vm_number_str" msgid="4676479471644687453">"ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ"</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_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>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 7ed47f4d..d1b89bce 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -62,7 +62,7 @@
<string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"रोक लगाउने काम अस्थायी रूपमा निष्क्रिय छ"</string>
<string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"तपाईँले आपतकालीन नम्बरमा डायल गरेपछि वा पाठ सन्देश पठाएपछि आपतकालीन सेवाहरूले तपाईँलाई सम्पर्क गर्न सकून् भन्ने कुरा सुनिश्चित गर्न कलमाथिको अवरोध निष्क्रिय गरिन्छ।"</string>
<string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"अब पुन:-सक्रिय गर्नुहोस्"</string>
- <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> लाई रोकियो"</string>
+ <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> माथि रोक लगाइयो"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> माथिको रोक हटाइयो"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"आपतकालीन नम्बरमाथि रोक लगाउन सकिएन।"</string>
<string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> लाई पहिले नै रोकिएको छ।"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 73800d96..1f4cb3ed 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -55,7 +55,7 @@
<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_number_hint" msgid="6847675097085433553">"ਫੋਨ ਨੰਬਰ"</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>
<string name="delete_icon_description" msgid="8903995728252556724">"ਅਨਬਲੌਕ ਕਰੋ"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index b7b9edf8..d6623cde 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -54,7 +54,7 @@
<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 6a445bb3..caf3eddc 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -50,7 +50,7 @@
<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="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>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 9dbb2326..28227a86 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -62,8 +62,8 @@
<string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"Blokovanie je dočasne vypnuté"</string>
<string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Keď vytočíte číslo tiesňového volania alebo naň odošlete textovú správu, blokovanie bude vypnuté, aby vás mohli pohotovostné služby kontaktovať."</string>
<string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Znova zapnúť"</string>
- <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"Číslo <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> je zablokované"</string>
- <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"Číslo je <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> odblokované"</string>
+ <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"Číslo <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> je blokované"</string>
+ <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"Číslo <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> je odblokované"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Číslo tiesňového volania sa nedá zablokovať."</string>
<string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"Číslo <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> je už zablokované."</string>
<string name="toast_personal_call_msg" msgid="5115361633476779723">"Na volanie sa používa osobné vytáčanie"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index 11fd6199..e50e1c81 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -39,13 +39,14 @@
<!-- Flag indicating if the tty is enabled -->
<bool name="tty_enabled">true</bool>
- <!-- Component name for the notification handler. The presence of this value will disable
- MissedCallNotifierImpl's presentation of missed call/voice notifications [DO NOT TRANSLATE] -->
- <string name="notification_component" translatable="false"></string>
-
<!-- Flag indicating whether audio should be routed to speaker when docked -->
<bool name="use_speaker_when_docked">true</bool>
+ <!-- Flag indicating whether allow (silence rather than reject) the incoming call if it has a
+ different source (connection service) from the existing ringing call when reaching
+ maximum ringing calls. -->
+ <bool name="silence_incoming_when_different_service_and_maximum_ringing">false</bool>
+
<!-- DTMF key to be used for LCH hold tone -->
<string name="lch_dtmf_key" translatable="false">D</string>
</resources>
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index 44567343..2b6ace55 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -33,6 +33,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.PriorityQueue;
import java.util.stream.Collectors;
import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent;
@@ -521,8 +522,11 @@ public class Analytics {
public static final long MILLIS_IN_1_SECOND = ParcelableCallAnalytics.MILLIS_IN_1_SECOND;
+ public static final int MAX_NUM_CALLS_TO_STORE = 100;
+
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 LinkedList<String> sActiveCallIds = new LinkedList<>();
private static final List<SessionTiming> sSessionTimings = new LinkedList<>();
public static void addSessionTiming(String sessionName, long time) {
@@ -538,7 +542,12 @@ public class Analytics {
Log.d(TAG, "Starting analytics for call " + callId);
CallInfoImpl callInfo = new CallInfoImpl(callId, direction);
synchronized (sLock) {
+ while (sActiveCallIds.size() >= MAX_NUM_CALLS_TO_STORE) {
+ String callToRemove = sActiveCallIds.remove();
+ sCallIdToInfo.remove(callToRemove);
+ }
sCallIdToInfo.put(callId, callInfo);
+ sActiveCallIds.add(callId);
}
return callInfo;
}
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index 3d0a9aea..ed69d207 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -761,7 +761,12 @@ public class BluetoothPhoneServiceImpl {
} else {
addressUri = call.getHandle();
}
+
String address = addressUri == null ? null : addressUri.getSchemeSpecificPart();
+ if (address != null) {
+ address = PhoneNumberUtils.stripSeparators(address);
+ }
+
int addressType = address == null ? -1 : PhoneNumberUtils.toaFromString(address);
if (shouldLog) {
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 1fcf69c1..899f148b 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -26,6 +26,7 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.Trace;
import android.provider.ContactsContract.Contacts;
+import android.telecom.CallAudioState;
import android.telecom.Conference;
import android.telecom.DisconnectCause;
import android.telecom.Connection;
@@ -109,7 +110,7 @@ public class Call implements CreateConnectionResponse {
void onConnectionManagerPhoneAccountChanged(Call call);
void onPhoneAccountChanged(Call call);
void onConferenceableCallsChanged(Call call);
- boolean onCanceledViaNewOutgoingCallBroadcast(Call call);
+ boolean onCanceledViaNewOutgoingCallBroadcast(Call call, long disconnectionTimeout);
void onHoldToneRequested(Call call);
void onConnectionEvent(Call call, String event, Bundle extras);
void onExternalCallChanged(Call call, boolean isExternalCall);
@@ -171,7 +172,7 @@ public class Call implements CreateConnectionResponse {
@Override
public void onConferenceableCallsChanged(Call call) {}
@Override
- public boolean onCanceledViaNewOutgoingCallBroadcast(Call call) {
+ public boolean onCanceledViaNewOutgoingCallBroadcast(Call call, long disconnectionTimeout) {
return false;
}
@@ -321,6 +322,8 @@ public class Call implements CreateConnectionResponse {
private int mConnectionProperties;
+ private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
+
private boolean mIsConference = false;
private final boolean mShouldAttachToExistingConnection;
@@ -1084,6 +1087,16 @@ public class Call implements CreateConnectionResponse {
}
}
+ public int getSupportedAudioRoutes() {
+ return mSupportedAudioRoutes;
+ }
+
+ void setSupportedAudioRoutes(int audioRoutes) {
+ if (mSupportedAudioRoutes != audioRoutes) {
+ mSupportedAudioRoutes = audioRoutes;
+ }
+ }
+
@VisibleForTesting
public Call getParentCall() {
return mParentCall;
@@ -1221,6 +1234,7 @@ public class Call implements CreateConnectionResponse {
setConnectionCapabilities(connection.getConnectionCapabilities());
setConnectionProperties(connection.getConnectionProperties());
+ setSupportedAudioRoutes(connection.getSupportedAudioRoutes());
setVideoProvider(connection.getVideoProvider());
setVideoState(connection.getVideoState());
setRingbackRequested(connection.isRingbackRequested());
@@ -1322,14 +1336,14 @@ public class Call implements CreateConnectionResponse {
@VisibleForTesting
public void disconnect() {
- disconnect(false);
+ disconnect(0);
}
/**
* Attempts to disconnect the call through the connection service.
*/
@VisibleForTesting
- public void disconnect(boolean wasViaNewOutgoingCallBroadcaster) {
+ public void disconnect(long disconnectionTimeout) {
Log.event(this, Log.Events.REQUEST_DISCONNECT);
// Track that the call is now locally disconnecting.
@@ -1339,7 +1353,7 @@ public class Call implements CreateConnectionResponse {
if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT ||
mState == CallState.CONNECTING) {
Log.v(this, "Aborting call %s", this);
- abort(wasViaNewOutgoingCallBroadcaster);
+ abort(disconnectionTimeout);
} else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) {
if (mConnectionService == null) {
Log.e(this, new Exception(), "disconnect() request on a call without a"
@@ -1355,22 +1369,25 @@ public class Call implements CreateConnectionResponse {
}
}
- void abort(boolean wasViaNewOutgoingCallBroadcaster) {
+ void abort(long disconnectionTimeout) {
if (mCreateConnectionProcessor != null &&
!mCreateConnectionProcessor.isProcessingComplete()) {
mCreateConnectionProcessor.abort();
} else if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT
|| mState == CallState.CONNECTING) {
- if (wasViaNewOutgoingCallBroadcaster) {
- // If the cancelation was from NEW_OUTGOING_CALL, then we do not automatically
- // destroy the call. Instead, we announce the cancelation and CallsManager handles
+ if (disconnectionTimeout > 0) {
+ // If the cancelation was from NEW_OUTGOING_CALL with a timeout of > 0
+ // milliseconds, do not destroy the call.
+ // Instead, we announce the cancellation and CallsManager handles
// it through a timer. Since apps often cancel calls through NEW_OUTGOING_CALL and
// then re-dial them quickly using a gateway, allowing the first call to end
// causes jank. This timeout allows CallsManager to transition the first call into
// the second call so that in-call only ever sees a single call...eliminating the
- // jank altogether.
+ // jank altogether. The app will also be able to set the timeout via an extra on
+ // the ordered broadcast.
for (Listener listener : mListeners) {
- if (listener.onCanceledViaNewOutgoingCallBroadcast(this)) {
+ if (listener.onCanceledViaNewOutgoingCallBroadcast(
+ this, disconnectionTimeout)) {
// The first listener to handle this wins. A return value of true means that
// the listener will handle the disconnection process later and so we
// should not continue it here.
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 78a92eb4..8d64f181 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -229,6 +229,9 @@ public class CallAudioManager extends CallsManagerListenerBase {
makeArgsForModeStateMachine());
}
+ // Turn off mute when a new incoming call is answered.
+ mute(false /* shouldMute */);
+
maybeStopRingingAndCallWaitingForAnsweredOrRejectedCall(call);
}
@@ -360,7 +363,8 @@ public class CallAudioManager extends CallsManagerListenerBase {
CallAudioRouteStateMachine.TOGGLE_MUTE);
}
- void mute(boolean shouldMute) {
+ @VisibleForTesting
+ public void mute(boolean shouldMute) {
Log.v(this, "mute, shouldMute: %b", shouldMute);
// Don't mute if there are any emergency calls.
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 7b6c2b5f..7f6b82b0 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -62,6 +62,9 @@ import java.util.HashMap;
* mIsMuted: a boolean indicating whether the audio is muted
*/
public class CallAudioRouteStateMachine extends StateMachine {
+ private static final String TELECOM_PACKAGE =
+ CallAudioRouteStateMachine.class.getPackage().getName();
+
/** Direct the audio stream through the device's earpiece. */
public static final int ROUTE_EARPIECE = CallAudioState.ROUTE_EARPIECE;
@@ -164,6 +167,19 @@ public class CallAudioRouteStateMachine extends StateMachine {
String action = intent.getAction();
if (action.equals(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)) {
+ // We get an this broadcast any time the notification filter is changed, even if
+ // we are the initiator of the change.
+ // So, we'll look at who the initiator of the manual zen rule is in the
+ // notification manager. If its us, then we can just exit now.
+ String initiator =
+ mInterruptionFilterProxy.getInterruptionModeInitiator();
+
+ if (TELECOM_PACKAGE.equals(initiator)) {
+ // We are the initiator of this change, so ignore it.
+ Log.i(this, "interruptionFilterChanged - ignoring own change");
+ return;
+ }
+
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
@@ -171,6 +187,8 @@ public class CallAudioRouteStateMachine extends StateMachine {
mAreNotificationSuppressed =
mInterruptionFilterProxy.getCurrentInterruptionFilter()
== NotificationManager.INTERRUPTION_FILTER_ALARMS;
+ Log.i(this, "interruptionFilterChanged - changing to %b",
+ mAreNotificationSuppressed);
}
}
} finally {
@@ -222,31 +240,34 @@ public class CallAudioRouteStateMachine extends StateMachine {
@Override
public boolean processMessage(Message msg) {
+ int addedRoutes = 0;
+ int removedRoutes = 0;
+
switch (msg.what) {
case CONNECT_WIRED_HEADSET:
Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
"Wired headset connected");
- mAvailableRoutes &= ~ROUTE_EARPIECE;
- mAvailableRoutes |= ROUTE_WIRED_HEADSET;
- return NOT_HANDLED;
+ removedRoutes |= ROUTE_EARPIECE;
+ addedRoutes |= ROUTE_WIRED_HEADSET;
+ break;
case CONNECT_BLUETOOTH:
Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
"Bluetooth connected");
- mAvailableRoutes |= ROUTE_BLUETOOTH;
- return NOT_HANDLED;
+ addedRoutes |= ROUTE_BLUETOOTH;
+ break;
case DISCONNECT_WIRED_HEADSET:
Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
"Wired headset disconnected");
- mAvailableRoutes &= ~ROUTE_WIRED_HEADSET;
+ removedRoutes |= ROUTE_WIRED_HEADSET;
if (mDoesDeviceSupportEarpieceRoute) {
- mAvailableRoutes |= ROUTE_EARPIECE;
+ addedRoutes |= ROUTE_EARPIECE;
}
- return NOT_HANDLED;
+ break;
case DISCONNECT_BLUETOOTH:
Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
"Bluetooth disconnected");
- mAvailableRoutes &= ~ROUTE_BLUETOOTH;
- return NOT_HANDLED;
+ removedRoutes |= ROUTE_BLUETOOTH;
+ break;
case SWITCH_BASELINE_ROUTE:
sendInternalMessage(calculateBaselineRouteMessage(false));
return HANDLED;
@@ -259,6 +280,14 @@ public class CallAudioRouteStateMachine extends StateMachine {
default:
return NOT_HANDLED;
}
+
+ if (addedRoutes != 0 || removedRoutes != 0) {
+ mAvailableRoutes = modifyRoutes(mAvailableRoutes, removedRoutes, addedRoutes, true);
+ mDeviceSupportedRoutes = modifyRoutes(mDeviceSupportedRoutes, removedRoutes,
+ addedRoutes, false);
+ }
+
+ return NOT_HANDLED;
}
// Behavior will depend on whether the state is an active one or a quiescent one.
@@ -1112,6 +1141,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
* A few pieces of hidden state. Used to avoid exponential explosion of number of explicit
* states
*/
+ private int mDeviceSupportedRoutes;
private int mAvailableRoutes;
private int mAudioFocusType;
private boolean mWasOnSpeaker;
@@ -1201,9 +1231,15 @@ public class CallAudioRouteStateMachine extends StateMachine {
}
public void initialize(CallAudioState initState) {
+ if ((initState.getRoute() & getCurrentCallSupportedRoutes()) == 0) {
+ Log.e(this, new IllegalArgumentException(), "Route %d specified when supported call" +
+ " routes are: %d", initState.getRoute(), getCurrentCallSupportedRoutes());
+ }
+
mCurrentCallAudioState = initState;
mLastKnownCallAudioState = initState;
- mAvailableRoutes = initState.getSupportedRouteMask();
+ mDeviceSupportedRoutes = initState.getSupportedRouteMask();
+ mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes();
mIsMuted = initState.isMuted();
mWasOnSpeaker = false;
@@ -1261,6 +1297,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
}
return;
case UPDATE_SYSTEM_AUDIO_ROUTE:
+ updateRouteForForegroundCall();
resendSystemAudioState();
return;
case RUN_RUNNABLE:
@@ -1460,7 +1497,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
}
private CallAudioState getInitialAudioState() {
- int supportedRouteMask = calculateSupportedRoutes();
+ int supportedRouteMask = calculateSupportedRoutes() & getCurrentCallSupportedRoutes();
final int route;
if ((supportedRouteMask & ROUTE_BLUETOOTH) != 0) {
@@ -1513,19 +1550,15 @@ public class CallAudioRouteStateMachine extends StateMachine {
return isExplicitUserRequest ? USER_SWITCH_EARPIECE : SWITCH_EARPIECE;
} else if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
return isExplicitUserRequest ? USER_SWITCH_HEADSET : SWITCH_HEADSET;
- } else if (!mDoesDeviceSupportEarpieceRoute) {
- return isExplicitUserRequest ? USER_SWITCH_SPEAKER : SWITCH_SPEAKER;
} else {
- Log.e(this, new IllegalStateException(),
- "Neither headset nor earpiece are available, but there is an " +
- "earpiece on the device. Defaulting to earpiece.");
- return isExplicitUserRequest ? USER_SWITCH_EARPIECE : SWITCH_EARPIECE;
+ return isExplicitUserRequest ? USER_SWITCH_SPEAKER : SWITCH_SPEAKER;
}
}
private void reinitialize() {
CallAudioState initState = getInitialAudioState();
- mAvailableRoutes = initState.getSupportedRouteMask();
+ mDeviceSupportedRoutes = initState.getSupportedRouteMask();
+ mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes();
mIsMuted = initState.isMuted();
setMuteOn(mIsMuted);
mWasOnSpeaker = false;
@@ -1533,4 +1566,37 @@ public class CallAudioRouteStateMachine extends StateMachine {
mLastKnownCallAudioState = initState;
transitionTo(mRouteCodeToQuiescentState.get(initState.getRoute()));
}
+
+ private void updateRouteForForegroundCall() {
+ mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes();
+
+ CallAudioState currentState = getCurrentCallAudioState();
+
+ // Move to baseline route in the case the current route is no longer available.
+ if ((mAvailableRoutes & currentState.getRoute()) == 0) {
+ sendInternalMessage(calculateBaselineRouteMessage(false));
+ }
+ }
+
+ private int getCurrentCallSupportedRoutes() {
+ int supportedRoutes = CallAudioState.ROUTE_ALL;
+
+ if (mCallsManager.getForegroundCall() != null) {
+ supportedRoutes &= mCallsManager.getForegroundCall().getSupportedAudioRoutes();
+ }
+
+ return supportedRoutes;
+ }
+
+ private int modifyRoutes(int base, int remove, int add, boolean considerCurrentCall) {
+ base &= ~remove;
+
+ if (considerCurrentCall) {
+ add &= getCurrentCallSupportedRoutes();
+ }
+
+ base |= add;
+
+ return base;
+ }
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 461501db..fb2129e6 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -437,9 +437,13 @@ public class CallsManager extends Call.ListenerBase
if (result.shouldAllowCall) {
if (hasMaximumRingingCalls(incomingCall.getTargetPhoneAccount().getId())) {
- Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " +
- "ringing calls.");
- rejectCallAndLog(incomingCall);
+ if (shouldSilenceInsteadOfReject(incomingCall)) {
+ incomingCall.silence();
+ } else {
+ Log.i(this, "onCallFilteringCompleted: Call rejected! " +
+ "Exceeds maximum number of ringing calls.");
+ rejectCallAndLog(incomingCall);
+ }
} else if (hasMaximumDialingCalls()) {
Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " +
"dialing calls.");
@@ -502,6 +506,37 @@ public class CallsManager extends Call.ListenerBase
return (state == CallState.RINGING);
}
+ /**
+ * Whether allow (silence rather than reject) the incoming call if it has a different source
+ * (connection service) from the existing ringing call when reaching maximum ringing calls.
+ */
+ private boolean shouldSilenceInsteadOfReject(Call incomingCall) {
+ if (!mContext.getResources().getBoolean(
+ R.bool.silence_incoming_when_different_service_and_maximum_ringing)) {
+ return false;
+ }
+
+ Call ringingCall = null;
+
+ for (Call call : mCalls) {
+ // Only operate on top-level calls
+ if (call.getParentCall() != null) {
+ continue;
+ }
+
+ if (call.isExternalCall()) {
+ continue;
+ }
+
+ if (CallState.RINGING == call.getState() &&
+ call.getConnectionService() == incomingCall.getConnectionService()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
@Override
public void onFailedIncomingCall(Call call) {
setCallState(call, CallState.DISCONNECTED, "failed incoming call");
@@ -603,7 +638,8 @@ public class CallsManager extends Call.ListenerBase
}
@Override
- public boolean onCanceledViaNewOutgoingCallBroadcast(final Call call) {
+ public boolean onCanceledViaNewOutgoingCallBroadcast(final Call call,
+ long disconnectionTimeout) {
mPendingCallsToDisconnect.add(call);
mHandler.postDelayed(new Runnable("CM.oCVNOCB", mLock) {
@Override
@@ -613,7 +649,7 @@ public class CallsManager extends Call.ListenerBase
call.disconnect();
}
}
- }.prepare(), Timeouts.getNewOutgoingCallCancelMillis(mContext.getContentResolver()));
+ }.prepare(), disconnectionTimeout);
return true;
}
diff --git a/src/com/android/server/telecom/InterruptionFilterProxy.java b/src/com/android/server/telecom/InterruptionFilterProxy.java
index 434c3413..b659de8f 100644
--- a/src/com/android/server/telecom/InterruptionFilterProxy.java
+++ b/src/com/android/server/telecom/InterruptionFilterProxy.java
@@ -24,4 +24,5 @@ package com.android.server.telecom;
public interface InterruptionFilterProxy {
void setInterruptionFilter(int interruptionFilter);
int getCurrentInterruptionFilter();
+ String getInterruptionModeInitiator();
}
diff --git a/src/com/android/server/telecom/Log.java b/src/com/android/server/telecom/Log.java
index 2282ff01..9903eecf 100644
--- a/src/com/android/server/telecom/Log.java
+++ b/src/com/android/server/telecom/Log.java
@@ -125,6 +125,9 @@ public class Log {
public static final String STOP_DTMF = "STOP_DTMF";
public static final String START_RINGER = "START_RINGER";
public static final String STOP_RINGER = "STOP_RINGER";
+ public static final String START_VIBRATOR = "START_VIBRATOR";
+ public static final String STOP_VIBRATOR = "STOP_VIBRATOR";
+ public static final String SKIP_VIBRATION = "SKIP_VIBRATION";
public static final String SKIP_RINGING = "SKIP_RINGING";
public static final String START_CALL_WAITING_TONE = "START_CALL_WAITING_TONE";
public static final String STOP_CALL_WAITING_TONE = "STOP_CALL_WAITING_TONE";
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 94b52203..bb747258 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Trace;
import android.os.UserHandle;
import android.telecom.GatewayInfo;
@@ -114,19 +115,24 @@ public class NewOutgoingCallIntentBroadcaster {
Log.pii(resultNumber));
boolean endEarly = false;
+ long disconnectTimeout =
+ Timeouts.getNewOutgoingCallCancelMillis(mContext.getContentResolver());
if (resultNumber == null) {
Log.v(this, "Call cancelled (null number), returning...");
+ disconnectTimeout = getDisconnectTimeoutFromApp(
+ getResultExtras(false), disconnectTimeout);
endEarly = true;
} else if (TelephonyUtil.isPotentialLocalEmergencyNumber(
mPhoneNumberUtilsAdapter, mContext, resultNumber)) {
Log.w(this, "Cannot modify outgoing call to emergency number %s.",
resultNumber);
+ disconnectTimeout = 0;
endEarly = true;
}
if (endEarly) {
if (mCall != null) {
- mCall.disconnect(true /* wasViaNewOutgoingCall */);
+ mCall.disconnect(disconnectTimeout);
}
return;
}
@@ -471,4 +477,18 @@ public class NewOutgoingCallIntentBroadcaster {
intent.setAction(action);
}
}
+
+ private long getDisconnectTimeoutFromApp(Bundle resultExtras, long defaultTimeout) {
+ if (resultExtras != null) {
+ long disconnectTimeout = resultExtras.getLong(
+ TelecomManager.EXTRA_NEW_OUTGOING_CALL_CANCEL_TIMEOUT, defaultTimeout);
+ if (disconnectTimeout < 0) {
+ disconnectTimeout = 0;
+ }
+ return Math.min(disconnectTimeout,
+ Timeouts.getMaxNewOutgoingCallCancelMillis(mContext.getContentResolver()));
+ } else {
+ return defaultTimeout;
+ }
+ }
}
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 288f48cf..2880aa11 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -88,6 +88,8 @@ public class ParcelableCallUtils {
}
int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities());
int properties = convertConnectionToCallProperties(call.getConnectionProperties());
+ int supportedAudioRoutes = call.getSupportedAudioRoutes();
+
if (call.isConference()) {
properties |= android.telecom.Call.Details.PROPERTY_CONFERENCE;
}
@@ -154,8 +156,9 @@ public class ParcelableCallUtils {
call.getCannedSmsResponses(),
capabilities,
properties,
- connectTimeMillis,
call.getCreationTimeMillis(),
+ supportedAudioRoutes,
+ connectTimeMillis,
handle,
call.getHandlePresentation(),
callerDisplayName,
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index da0b023b..122036bb 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -35,6 +35,7 @@ import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.telecom.CallAudioState;
import android.telecom.ConnectionService;
import android.telecom.DefaultDialerManager;
import android.telecom.PhoneAccount;
@@ -1562,6 +1563,7 @@ public class PhoneAccountRegistrar {
private static final String ADDRESS = "handle";
private static final String SUBSCRIPTION_ADDRESS = "subscription_number";
private static final String CAPABILITIES = "capabilities";
+ private static final String SUPPORTED_AUDIO_ROUTES = "supported_audio_routes";
private static final String ICON_RES_ID = "icon_res_id";
private static final String ICON_PACKAGE_NAME = "icon_package_name";
private static final String ICON_BITMAP = "icon_bitmap";
@@ -1597,6 +1599,8 @@ public class PhoneAccountRegistrar {
writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer);
writeBundle(EXTRAS, o.getExtras(), serializer);
writeTextIfNonNull(ENABLED, o.isEnabled() ? "true" : "false" , serializer);
+ writeTextIfNonNull(SUPPORTED_AUDIO_ROUTES, Integer.toString(
+ o.getSupportedAudioRoutes()), serializer);
serializer.endTag(null, CLASS_PHONE_ACCOUNT);
}
@@ -1610,6 +1614,7 @@ public class PhoneAccountRegistrar {
Uri address = null;
Uri subscriptionAddress = null;
int capabilities = 0;
+ int supportedAudioRoutes = 0;
int iconResId = PhoneAccount.NO_RESOURCE_ID;
String iconPackageName = null;
Bitmap iconBitmap = null;
@@ -1668,6 +1673,9 @@ public class PhoneAccountRegistrar {
enabled = "true".equalsIgnoreCase(parser.getText());
} else if (parser.getName().equals(EXTRAS)) {
extras = readBundle(parser);
+ } else if (parser.getName().equals(SUPPORTED_AUDIO_ROUTES)) {
+ parser.next();
+ supportedAudioRoutes = Integer.parseInt(parser.getText());
}
}
@@ -1726,10 +1734,16 @@ public class PhoneAccountRegistrar {
}
}
+ if (version < 9) {
+ // Set supported audio routes to all by default
+ supportedAudioRoutes = CallAudioState.ROUTE_ALL;
+ }
+
PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, label)
.setAddress(address)
.setSubscriptionAddress(subscriptionAddress)
.setCapabilities(capabilities)
+ .setSupportedAudioRoutes(supportedAudioRoutes)
.setShortDescription(shortDescription)
.setSupportedUriSchemes(supportedUriSchemes)
.setHighlightColor(highlightColor)
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index f53f212c..4bb43ae4 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -64,9 +64,11 @@ public class Ringer {
private RingtoneFactory mRingtoneFactory;
/**
- * Call objects that are ringing or call-waiting. These are used only for logging purposes.
+ * Call objects that are ringing, vibrating or call-waiting. These are used only for logging
+ * purposes.
*/
private Call mRingingCall;
+ private Call mVibratingCall;
private Call mCallWaitingCall;
/**
@@ -146,10 +148,13 @@ public class Ringer {
Log.i(this, "startRingingOrCallWaiting, skipping because volume is 0");
}
- if (vibrationAllowed && shouldVibrate(mContext) && !mIsVibrating) {
+ if (vibrationAllowed && shouldVibrate(mContext, foregroundCall) && !mIsVibrating) {
+ mVibratingCall = foregroundCall;
mVibrator.vibrate(VIBRATION_PATTERN, VIBRATION_PATTERN_REPEAT,
VIBRATION_ATTRIBUTES);
mIsVibrating = true;
+ } else if (mIsVibrating) {
+ Log.event(foregroundCall, Log.Events.SKIP_VIBRATION, "already vibrating");
}
return isRingerAudible;
@@ -187,8 +192,10 @@ public class Ringer {
mRingtonePlayer.stop();
if (mIsVibrating) {
+ Log.event(mVibratingCall, Log.Events.STOP_VIBRATOR);
mVibrator.cancel();
mIsVibrating = false;
+ mVibratingCall = null;
}
}
@@ -215,14 +222,31 @@ public class Ringer {
return manager.matchesCallFilter(extras);
}
- private boolean shouldVibrate(Context context) {
+ private boolean shouldVibrate(Context context, Call call) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int ringerMode = audioManager.getRingerModeInternal();
+ boolean shouldVibrate;
if (getVibrateWhenRinging(context)) {
- return ringerMode != AudioManager.RINGER_MODE_SILENT;
+ shouldVibrate = ringerMode != AudioManager.RINGER_MODE_SILENT;
} else {
- return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+ shouldVibrate = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
}
+
+ // Technically this should be in the calling method, but it seemed a little odd to pass
+ // around a whole bunch of state just for logging purposes.
+ if (shouldVibrate) {
+ Log.event(call, Log.Events.START_VIBRATOR,
+ "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
+ mVibrator.hasVibrator(), mSystemSettingsUtil.canVibrateWhenRinging(context),
+ ringerMode, mIsVibrating);
+ } else {
+ Log.event(call, Log.Events.SKIP_VIBRATION,
+ "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
+ mVibrator.hasVibrator(), mSystemSettingsUtil.canVibrateWhenRinging(context),
+ ringerMode, mIsVibrating);
+ }
+
+ return shouldVibrate;
}
private boolean getVibrateWhenRinging(Context context) {
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index 7be59c3a..b2f4b6dd 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -63,7 +63,16 @@ public final class Timeouts {
* in-call UI.
*/
public static long getNewOutgoingCallCancelMillis(ContentResolver contentResolver) {
- return get(contentResolver, "new_outgoing_call_cancel_ms", 100000L);
+ return get(contentResolver, "new_outgoing_call_cancel_ms", 500L);
+ }
+
+ /**
+ * Returns the maximum amount of time to wait before disconnecting a call that was canceled via
+ * NEW_OUTGOING_CALL broadcast. This prevents malicious or poorly configured apps from
+ * forever tying up the Telecom stack.
+ */
+ public static long getMaxNewOutgoingCallCancelMillis(ContentResolver contentResolver) {
+ return get(contentResolver, "max_new_outgoing_call_cancel_ms", 10000L);
}
/**
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index ef5bf96e..f6080f84 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -26,6 +26,7 @@ import android.media.IAudioService;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.ServiceManager;
+import android.service.notification.ZenModeConfig;
import com.android.internal.telephony.CallerInfoAsyncQuery;
import com.android.server.telecom.AsyncRingtonePlayer;
@@ -179,6 +180,15 @@ public class TelecomService extends Service implements TelecomSystem.Component {
public int getCurrentInterruptionFilter() {
return notificationManager.getCurrentInterruptionFilter();
}
+
+ @Override
+ public String getInterruptionModeInitiator() {
+ ZenModeConfig config = notificationManager.getZenModeConfig();
+ if (config.manualRule != null) {
+ return config.manualRule.enabler;
+ }
+ return null;
+ }
}
));
}
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index b9cc2510..38074ced 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -142,7 +142,6 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
private final PhoneAccountRegistrar mPhoneAccountRegistrar;
private final NotificationManager mNotificationManager;
private final NotificationBuilderFactory mNotificationBuilderFactory;
- private final ComponentName mNotificationComponent;
private final PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
private UserHandle mCurrentUserHandle;
@@ -164,11 +163,8 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- final String notificationComponent = context.getString(R.string.notification_component);
mNotificationBuilderFactory = notificationBuilderFactory;
- mNotificationComponent = notificationComponent != null
- ? ComponentName.unflattenFromString(notificationComponent) : null;
mMissedCallCounts = new ConcurrentHashMap<>();
}
@@ -210,44 +206,6 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
}
/**
- * Broadcasts missed call notification to custom component if set.
- * Currently the component is set in phone capable android wear device.
- * @param userHandle The user that has the missed call(s).
- * @return {@code true} if the broadcast was sent. {@code false} otherwise.
- */
- private boolean sendNotificationCustomComponent(Call call, UserHandle userHandle) {
- if (mNotificationComponent != null) {
- int count = mMissedCallCounts.get(userHandle).get();
- Intent intent = new Intent();
- intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- intent.setComponent(mNotificationComponent);
- intent.setAction(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION);
- intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count);
- intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER,
- call != null ? call.getPhoneNumber() : null);
- intent.putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT,
- createClearMissedCallsPendingIntent(userHandle));
-
-
- if (count == 1 && call != null) {
- final Uri handleUri = call.getHandle();
- String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart();
-
- if (!TextUtils.isEmpty(handle) && !TextUtils.equals(handle,
- mContext.getString(R.string.handle_restricted))) {
- intent.putExtra(TelecomManager.EXTRA_CALL_BACK_INTENT,
- createCallBackPendingIntent(handleUri, userHandle));
- }
- }
-
- mContext.sendBroadcast(intent);
- return true;
- }
-
- return false;
- }
-
- /**
* Returns the missed-call notificatino intent to send to the default dialer for the given user. * Note, the passed in userHandle is always the non-managed user for SIM calls (multi-user
* calls). In this case we return the default dialer for the logged in user. This is never the
* managed (work profile) dialer.
@@ -281,10 +239,24 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
int count = mMissedCallCounts.get(userHandle).get();
Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle)
.setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT,
+ createClearMissedCallsPendingIntent(userHandle))
.putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count)
.putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER,
call != null ? call.getPhoneNumber() : null);
+ if (count == 1 && call != null) {
+ final Uri handleUri = call.getHandle();
+ String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart();
+
+ if (!TextUtils.isEmpty(handle) && !TextUtils.equals(handle,
+ mContext.getString(R.string.handle_restricted))) {
+ intent.putExtra(TelecomManager.EXTRA_CALL_BACK_INTENT,
+ createCallBackPendingIntent(handleUri, userHandle));
+ }
+ }
+
+
Log.w(this, "Showing missed calls through default dialer.");
mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE);
}
@@ -313,10 +285,6 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0));
int missCallCounts = mMissedCallCounts.get(userHandle).incrementAndGet();
- if (sendNotificationCustomComponent(call, userHandle)) {
- return;
- }
-
if (shouldManageNotificationThroughDefaultDialer(userHandle)) {
sendNotificationThroughDefaultDialer(call, userHandle);
return;
@@ -429,10 +397,6 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0));
mMissedCallCounts.get(userHandle).set(0);
- if (sendNotificationCustomComponent(null, userHandle)) {
- return;
- }
-
if (shouldManageNotificationThroughDefaultDialer(userHandle)) {
sendNotificationThroughDefaultDialer(null, userHandle);
return;
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
index 81d4aa5b..021ce82f 100644
--- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -36,6 +36,7 @@ import com.android.server.telecom.TelecomLogClass;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -337,6 +338,26 @@ public class AnalyticsTests extends TelecomSystemTest {
analyticsProto.callLogs[0].getConnectionProperties() & expectedProperties);
}
+ @SmallTest
+ public void testAnalyticsMaxSize() throws Exception {
+ Analytics.reset();
+ for (int i = 0; i < Analytics.MAX_NUM_CALLS_TO_STORE * 2; i++) {
+ Analytics.initiateCallAnalytics(String.valueOf(i), Analytics.INCOMING_DIRECTION)
+ .addCallTechnology(i);
+ }
+
+ 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(Analytics.MAX_NUM_CALLS_TO_STORE, analyticsProto.callLogs.length);
+ assertEquals(Arrays.stream(analyticsProto.callLogs)
+ .filter(x -> x.getCallTechnologies() < 100)
+ .count(), 0);
+ }
+
private void assertIsRoundedToOneSigFig(long x) {
assertEquals(x, Analytics.roundToOneSigFig(x));
}
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
index 34325f0a..488ac296 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
@@ -36,10 +36,13 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.stream.Collectors;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -79,6 +82,69 @@ public class CallAudioManagerTest extends TelecomTestCase {
}
@MediumTest
+ public void testUnmuteOfSecondIncomingCall() {
+ // Start with a single incoming call.
+ Call call = createIncomingCall();
+ when(call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO))
+ .thenReturn(false);
+ when(call.getId()).thenReturn("1");
+
+ ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor =
+ ArgumentCaptor.forClass(CallAudioModeStateMachine.MessageArgs.class);
+ // Answer the incoming call
+ mCallAudioManager.onIncomingCallAnswered(call);
+ when(call.getState()).thenReturn(CallState.ACTIVE);
+ mCallAudioManager.onCallStateChanged(call, CallState.RINGING, CallState.ACTIVE);
+ verify(mCallAudioModeStateMachine).sendMessageWithArgs(
+ eq(CallAudioModeStateMachine.NO_MORE_RINGING_CALLS), captor.capture());
+ CallAudioModeStateMachine.MessageArgs correctArgs =
+ new CallAudioModeStateMachine.MessageArgs(
+ true, // hasActiveOrDialingCalls
+ false, // hasRingingCalls
+ false, // hasHoldingCalls
+ false, // isTonePlaying
+ false, // foregroundCallIsVoip
+ null // session
+ );
+ assertMessageArgEquality(correctArgs, captor.getValue());
+ verify(mCallAudioModeStateMachine).sendMessageWithArgs(
+ eq(CallAudioModeStateMachine.NEW_ACTIVE_OR_DIALING_CALL), captor.capture());
+ assertMessageArgEquality(correctArgs, captor.getValue());
+
+ // Mute the current ongoing call.
+ mCallAudioManager.mute(true);
+
+ // Create a second incoming call.
+ Call call2 = mock(Call.class);
+ when(call2.getState()).thenReturn(CallState.RINGING);
+ when(call2.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO))
+ .thenReturn(false);
+ when(call2.getId()).thenReturn("2");
+ mCallAudioManager.onCallAdded(call2);
+
+ // Answer the incoming call
+ mCallAudioManager.onIncomingCallAnswered(call);
+
+ // Capture the calls to sendMessageWithSessionInfo; we want to look for mute on and off
+ // messages and make sure that there was a mute on before the mute off.
+ ArgumentCaptor<Integer> muteCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mCallAudioRouteStateMachine, atLeastOnce())
+ .sendMessageWithSessionInfo(muteCaptor.capture());
+ List<Integer> values = muteCaptor.getAllValues();
+ values = values.stream()
+ .filter(value -> value == CallAudioRouteStateMachine.MUTE_ON ||
+ value == CallAudioRouteStateMachine.MUTE_OFF)
+ .collect(Collectors.toList());
+
+ // Make sure we got a mute on and a mute off.
+ assertTrue(values.contains(CallAudioRouteStateMachine.MUTE_ON));
+ assertTrue(values.contains(CallAudioRouteStateMachine.MUTE_OFF));
+ // And that the mute on happened before the off.
+ assertTrue(values.indexOf(CallAudioRouteStateMachine.MUTE_ON) < values
+ .lastIndexOf(CallAudioRouteStateMachine.MUTE_OFF));
+ }
+
+ @MediumTest
public void testSingleIncomingCallFlowWithoutMTSpeedUp() {
Call call = createIncomingCall();
when(call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO))
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index dddf9e69..0766b722 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -86,6 +86,8 @@ public class CallAudioRouteStateMachineTest
public boolean doesDeviceSupportEarpiece; // set to false in the case of Wear devices
public boolean shouldRunWithFocus;
+ public int callSupportedRoutes = CallAudioState.ROUTE_ALL;
+
public RoutingTestParameters(String name, int initialRoute,
int initialNotificationFilter, int availableRoutes, int speakerInteraction,
int bluetoothInteraction, int action, int expectedRoute,
@@ -107,6 +109,11 @@ public class CallAudioRouteStateMachineTest
this.shouldRunWithFocus = shouldRunWithFocus;
}
+ public RoutingTestParameters setCallSupportedRoutes(int routes) {
+ callSupportedRoutes = routes;
+ return this;
+ }
+
@Override
public String toString() {
return "RoutingTestParameters{" +
@@ -159,6 +166,7 @@ public class CallAudioRouteStateMachineTest
when(mockCallsManager.getLock()).thenReturn(mLock);
when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
when(fakeCall.isAlive()).thenReturn(true);
+ when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
setupInterruptionFilterMocks();
doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
@@ -878,6 +886,38 @@ public class CallAudioRouteStateMachineTest
shouldRunWithFocus
));
+ params.add(new RoutingTestParameters(
+ "Disconnect wired headset when call doesn't 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
+ true, // doesDeviceSupportEarpiece
+ shouldRunWithFocus
+ ).setCallSupportedRoutes(CallAudioState.ROUTE_ALL & ~CallAudioState.ROUTE_EARPIECE));
+
+ params.add(new RoutingTestParameters(
+ "Disconnect bluetooth when call does not support earpiece", // name
+ CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter
+ CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
+ ON, // speakerInteraction
+ OFF, // bluetoothInteraction
+ CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ CallAudioState.ROUTE_SPEAKER, // expectedRoute
+ CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes
+ NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter
+ false, // isNotificationChangeExpected
+ true, // doesDeviceSupportEarpiece
+ shouldRunWithFocus
+ ).setCallSupportedRoutes(CallAudioState.ROUTE_ALL & ~CallAudioState.ROUTE_EARPIECE));
+
return params;
}
@@ -916,6 +956,7 @@ public class CallAudioRouteStateMachineTest
|| (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
doReturn(params.initialRoute == CallAudioState.ROUTE_SPEAKER).when(mockAudioManager).
isSpeakerphoneOn();
+ when(fakeCall.getSupportedAudioRoutes()).thenReturn(params.callSupportedRoutes);
// Set the initial CallAudioState object
final CallAudioState initState = new CallAudioState(false,
@@ -999,6 +1040,7 @@ public class CallAudioRouteStateMachineTest
|| (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
when(mockAudioManager.isSpeakerphoneOn()).thenReturn(
params.initialRoute == CallAudioState.ROUTE_SPEAKER);
+ when(fakeCall.getSupportedAudioRoutes()).thenReturn(params.callSupportedRoutes);
// Set the initial CallAudioState object
CallAudioState initState = new CallAudioState(false,
@@ -1051,10 +1093,13 @@ public class CallAudioRouteStateMachineTest
private void resetMocks() {
reset(mockAudioManager, mockBluetoothManager, mockCallsManager,
- mockConnectionServiceWrapper, mMockInterruptionFilterProxy);
+ mockConnectionServiceWrapper, mMockInterruptionFilterProxy, fakeCall);
mMockInterruptionFilterProxy = mock(InterruptionFilterProxy.class);
setupInterruptionFilterMocks();
when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
+ when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
+ when(fakeCall.isAlive()).thenReturn(true);
+ when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
when(mockCallsManager.getLock()).thenReturn(mLock);
doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
any(CallAudioState.class));
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 65e0d7f7..698da266 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -336,6 +336,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
int addressPresentation;
int capabilities;
int properties;
+ int supportedAudioRoutes;
StatusHints statusHints;
DisconnectCause disconnectCause;
String conferenceId;
@@ -597,6 +598,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
c.state,
c.capabilities,
c.properties,
+ c.supportedAudioRoutes,
c.request.getAddress(),
c.addressPresentation,
c.callerDisplayName,
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index 54613d47..9b7dc375 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -313,7 +313,28 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase {
result.receiver.onReceive(mContext, result.intent);
verifyNoCallPlaced();
- verify(mCall).disconnect(true);
+ ArgumentCaptor<Long> timeoutCaptor = ArgumentCaptor.forClass(Long.class);
+ verify(mCall).disconnect(timeoutCaptor.capture());
+ assertTrue(timeoutCaptor.getValue() > 0);
+ }
+
+ @SmallTest
+ public void testCallNumberModifiedToNullWithLongCustomTimeout() {
+ Uri handle = Uri.parse("tel:6505551234");
+ Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null);
+ ReceiverIntentPair result = regularCallTestHelper(callIntent, null);
+
+ long customTimeout = 100000000;
+ Bundle bundle = new Bundle();
+ bundle.putLong(TelecomManager.EXTRA_NEW_OUTGOING_CALL_CANCEL_TIMEOUT, customTimeout);
+ result.receiver.setResultData(null);
+ result.receiver.setResultExtras(bundle);
+
+ result.receiver.onReceive(mContext, result.intent);
+ verifyNoCallPlaced();
+ ArgumentCaptor<Long> timeoutCaptor = ArgumentCaptor.forClass(Long.class);
+ verify(mCall).disconnect(timeoutCaptor.capture());
+ assertTrue(timeoutCaptor.getValue() < customTimeout);
}
@SmallTest
@@ -328,7 +349,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase {
doReturn(true).when(mPhoneNumberUtilsAdapterSpy).isPotentialLocalEmergencyNumber(
any(Context.class), eq(newEmergencyNumber));
result.receiver.onReceive(mContext, result.intent);
- verify(mCall).disconnect(true);
+ verify(mCall).disconnect(eq(0L));
}
private ReceiverIntentPair regularCallTestHelper(Intent intent,
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index fab45405..cf17b5c1 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -182,6 +182,11 @@ public class TelecomSystemTest extends TelecomTestCase {
public int getCurrentInterruptionFilter() {
return mInterruptionFilter;
}
+
+ @Override
+ public String getInterruptionModeInitiator() {
+ return "com.android.server.telecom";
+ }
}
@Mock HeadsetMediaButton mHeadsetMediaButton;