donut snapshot
Jean-Baptiste Queru [Fri, 24 Jul 2009 19:23:40 +0000 (12:23 -0700)]
53 files changed:
AndroidManifest.xml
res/drawable/picture_emergency.png [new file with mode: 0644]
res/layout/call_card_person_info.xml
res/layout/ecbm_layout.xml [new file with mode: 0644]
res/layout/eri_text_layout.xml [new file with mode: 0644]
res/layout/incall_screen.xml
res/layout/onscreen_answer_ui.xml [new file with mode: 0644]
res/values-cs/strings.xml
res/values-de/strings.xml
res/values-es-rUS/strings.xml
res/values-es/strings.xml
res/values-fr/strings.xml
res/values-it/strings.xml
res/values-ja/strings.xml
res/values-ko/strings.xml
res/values-nb/strings.xml
res/values-nl/strings.xml
res/values-pl/strings.xml
res/values-pt/strings.xml [new file with mode: 0644]
res/values-ru/strings.xml
res/values-zh-rCN/strings.xml
res/values-zh-rTW/strings.xml
res/values/ids.xml [changed mode: 0644->0755]
res/values/strings.xml [changed mode: 0644->0755]
res/values/styles.xml
res/xml/call_feature_setting.xml
res/xml/cdma_call_feature_setting.xml [new file with mode: 0755]
res/xml/eri_text_appwidget.xml [new file with mode: 0644]
res/xml/gsm_umts_options.xml
res/xml/network_setting_cdma.xml [new file with mode: 0644]
src/com/android/phone/BluetoothAtPhonebook.java
src/com/android/phone/BluetoothHandsfree.java
src/com/android/phone/BluetoothHeadsetService.java
src/com/android/phone/CallCard.java [changed mode: 0644->0755]
src/com/android/phone/CallFeaturesSetting.java [changed mode: 0644->0755]
src/com/android/phone/CallNotifier.java [changed mode: 0644->0755]
src/com/android/phone/CdmaDisplayInfo.java [new file with mode: 0755]
src/com/android/phone/CdmaOptions.java
src/com/android/phone/CdmaPhoneCallState.java [new file with mode: 0755]
src/com/android/phone/CellBroadcastSms.java
src/com/android/phone/DTMFTwelveKeyDialer.java [changed mode: 0644->0755]
src/com/android/phone/DTMFTwelveKeyDialerView.java
src/com/android/phone/EmergencyCallbackMode.java [new file with mode: 0644]
src/com/android/phone/EmergencyDialer.java
src/com/android/phone/EriTextWidgetProvider.java [new file with mode: 0644]
src/com/android/phone/InCallMenu.java [changed mode: 0644->0755]
src/com/android/phone/InCallScreen.java [changed mode: 0644->0755]
src/com/android/phone/NotificationMgr.java
src/com/android/phone/OutgoingCallBroadcaster.java
src/com/android/phone/PhoneApp.java [changed mode: 0644->0755]
src/com/android/phone/PhoneInterfaceManager.java
src/com/android/phone/PhoneUtils.java [changed mode: 0644->0755]
src/com/android/phone/Settings.java

index eb5537b..cd4b30e 100644 (file)
                       android:readPermission="android.permission.READ_CONTACTS"
                       android:writePermission="android.permission.WRITE_CONTACTS" />
 
-        <!-- A virtual emergency 12 key dialer -->
+        <!-- Dialer UI that only allows emergency calls -->
         <activity android:name="EmergencyDialer"
-            android:label="@string/emergencyDialerIconLabel">
+            android:label="@string/emergencyDialerIconLabel"
+            android:screenOrientation="nosensor">
             <intent-filter>
                 <action android:name="com.android.phone.EmergencyDialer.DIAL" />
                 <category android:name="android.intent.category.DEFAULT" />
         <activity android:name="NetworkSetting" android:label="@string/networks">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-                <action android:name="android.settings.NETWORK_OPERATOR_SETTINGS" />
+                <action android:name="android.settings.NETWORK_OPERATOR_" />
             </intent-filter>
         </activity>
 
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
         </activity>
+        
+        <!-- Emergency Callback Mode screen -->
+        <activity android:name="EmergencyCallbackMode" 
+                android:label="Emergency Call Back"
+                android:theme="@style/EmergencyCallBack"
+                android:launchMode="singleTask"
+                android:taskAffinity=":EmergencyCallbackMode">
+        </activity>
 
         <!-- call feature setting -->
         <activity android:name="CallFeaturesSetting" android:label="@string/call_settings">
                 <action android:name="android.bluetooth.IBluetoothHeadset" />
             </intent-filter>
         </service>
+
+        <!-- Broadcast Receiver that will process cdma ERI text updates -->    
+        <receiver android:name="EriTextWidgetProvider" android:label="@string/eri_text_label">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data android:name="android.appwidget.provider" android:resource="@xml/eri_text_appwidget" />
+        </receiver>
     </application>
 </manifest>
 
diff --git a/res/drawable/picture_emergency.png b/res/drawable/picture_emergency.png
new file mode 100644 (file)
index 0000000..3690b07
Binary files /dev/null and b/res/drawable/picture_emergency.png differ
index 981666e..69b0a8b 100644 (file)
@@ -57,7 +57,7 @@
               android:singleLine="true"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
-              android:layout_marginBottom="4dip"
+              android:layout_marginBottom="6dip"
               android:paddingLeft="4dip"
               android:paddingRight="4dip"
               />
@@ -87,5 +87,4 @@
                   />
     </LinearLayout>
 
-
 </LinearLayout>
diff --git a/res/layout/ecbm_layout.xml b/res/layout/ecbm_layout.xml
new file mode 100644 (file)
index 0000000..436a0ff
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent" 
+            android:layout_height="fill_parent" 
+            android:orientation="vertical" >
+    <TextView android:id="@+id/text_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dip"
+            android:minHeight="50sp"
+            android:layout_gravity="center_vertical|center_horizontal"
+            android:text="@string/ecbm_mode_text" />
+    <ImageButton android:id="@+id/button_dial"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="80dip"
+            android:layout_gravity="center"
+            android:src="@drawable/picture_emergency" />  
+    <TextView android:id="@+id/text_instruction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="10sp"
+            android:layout_gravity="center_horizontal"
+            android:text="@string/ecbm_instruction_text" />
+            
+    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent" 
+            android:layout_height="fill_parent" 
+            android:orientation="horizontal" >
+
+            <Button android:id="@+id/button_ok"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginBottom="10dip"
+                    android:layout_marginLeft="70dip"
+                    android:layout_gravity="left|bottom"
+                    android:text="@string/ecbm_ok_text" />
+            <Button android:id="@+id/button_exit"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginBottom="10dip"
+                    android:layout_marginLeft="70dip"
+                    android:layout_gravity="left|bottom"
+                    android:text="@string/ecbm_exit_text" />
+    </LinearLayout>        
+</LinearLayout>
+
+    
\ No newline at end of file
diff --git a/res/layout/eri_text_layout.xml b/res/layout/eri_text_layout.xml
new file mode 100644 (file)
index 0000000..5ad2e0d
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/widget"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/message"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="12dip"
+        android:padding="10dip"
+        android:gravity="center"
+        style="@style/TextAppearance.EriWidget" />
+
+</LinearLayout>
index 81f5cc1..0ef1bed 100644 (file)
@@ -28,7 +28,6 @@
     <FrameLayout android:id="@+id/mainFrame"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
-        android:layout_weight="1"
         android:paddingTop="10dip"
         android:paddingLeft="6dip"
         android:paddingRight="6dip"
             />
     </RelativeLayout>
 
+    <!-- Onscreen "answer" UI, used on devices with no hardware CALL
+         button while an incoming call is ringing. -->
+    <ViewStub android:id="@+id/onscreenAnswerUiStub"
+        android:inflatedId="@+id/onscreenAnswerUiContainer"
+        android:layout="@layout/onscreen_answer_ui"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        />
+
 </FrameLayout>
diff --git a/res/layout/onscreen_answer_ui.xml b/res/layout/onscreen_answer_ui.xml
new file mode 100644 (file)
index 0000000..25578b2
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Onscreen "answer" UI: Used while an incoming call is ringing, on devices
+     with no hardware CALL button.
+
+     This view hiererarchy appears as a ViewStub in the InCallScreen's layout,
+     and is inflated only on devices where it's needed.
+
+     TODO: This UI is a TEMPORARY HACK until we have a final
+     design and assets from the UI team. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical"
+    android:visibility="gone"
+    >
+
+    <!-- Blank space on the top 2/3 of the screen -->
+    <View
+        android:layout_width="fill_parent"
+        android:layout_height="1dip"
+        android:layout_weight="2"
+        android:visibility="invisible"
+        />
+
+    <!-- The button, on the lower 1/3 of the screen -->
+    <!-- TODO: Need a new asset for the background; this
+         one is just a temporary placeholder. -->
+    <TextView android:id="@+id/onscreenAnswerButton"
+        android:layout_width="fill_parent"
+        android:layout_height="1dip"
+        android:layout_weight="1"
+        android:gravity="center"
+        android:layout_centerHorizontal="true"
+        android:layout_marginLeft="50dip"
+        android:layout_marginRight="50dip"
+        android:layout_marginBottom="20dip"
+        android:text="@string/onscreenAnswerText"
+        android:textAppearance="?android:attr/textAppearanceLargeInverse"
+        android:background="@*android:drawable/btn_default_normal"
+        />
+
+</LinearLayout>
index b88ebb1..d3d4f1b 100644 (file)
@@ -64,8 +64,6 @@
     <string name="wait_prompt_str">"Odeslat následující tóny?"\n</string>
     <string name="send_button">"Odeslat"</string>
     <string name="wild_prompt_str">"Nahradit zástupný znak znakem"</string>
-    <string name="bluetooth_headset_connected">"Náhlavní souprava s rozhraním Bluetooth byla připojena."</string>
-    <string name="bluetooth_headset_disconnected">"Náhlavní souprava s rozhraním Bluetooth byla odpojena."</string>
     <string name="no_vm_number">"Chybí číslo hlasové schránky"</string>
     <string name="no_vm_number_msg">"Na kartě SIM není uloženo žádné číslo hlasové schránky."</string>
     <string name="add_vm_number_str">"Přidat číslo"</string>
index b0e76ab..038b8a2 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"Folgende Töne senden?"\n</string>
     <string name="send_button">"Senden"</string>
     <string name="wild_prompt_str">"Platzhalter ersetzen durch"</string>
-    <string name="bluetooth_headset_connected">"Bluetooth-Headset verbunden."</string>
-    <string name="bluetooth_headset_disconnected">"Bluetooth-Headset nicht verbunden."</string>
     <string name="no_vm_number">"Fehlende Mailboxnummer"</string>
     <string name="no_vm_number_msg">"Auf der SIM-Karte ist keine Mailboxnummer gespeichert."</string>
     <string name="add_vm_number_str">"Nummer hinzufügen"</string>
index 0723054..1fee55b 100644 (file)
@@ -64,8 +64,6 @@
     <string name="wait_prompt_str">"¿Deseas enviar los siguientes tonos?"\n</string>
     <string name="send_button">"Enviar"</string>
     <string name="wild_prompt_str">"Reemplazar el caracter comodín con"</string>
-    <string name="bluetooth_headset_connected">"Auricular Bluetooth conectado."</string>
-    <string name="bluetooth_headset_disconnected">"Auriculares Bluetooth desconectados."</string>
     <string name="no_vm_number">"Falta el número de correo de voz"</string>
     <string name="no_vm_number_msg">"No hay un número de correo de voz almacenado en la tarjeta SIM."</string>
     <string name="add_vm_number_str">"Agregar número"</string>
index 5adfe34..06e867d 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"¿Deseas enviar los siguientes tonos?"\n</string>
     <string name="send_button">"Enviar"</string>
     <string name="wild_prompt_str">"Sustituir el carácter comodín por"</string>
-    <string name="bluetooth_headset_connected">"Móvil Bluetooth conectado"</string>
-    <string name="bluetooth_headset_disconnected">"Los auriculares Bluetooth están desconectados."</string>
     <string name="no_vm_number">"Falta el número del buzón de voz."</string>
     <string name="no_vm_number_msg">"No se ha almacenado ningún número de buzón de voz en la tarjeta SIM."</string>
     <string name="add_vm_number_str">"Añadir número"</string>
index 1e58464..c8ed6aa 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"Envoyer les tonalités suivantes ?"\n</string>
     <string name="send_button">"Envoyer"</string>
     <string name="wild_prompt_str">"Remplacer le caractère générique par"</string>
-    <string name="bluetooth_headset_connected">"Le casque Bluetooth est connecté."</string>
-    <string name="bluetooth_headset_disconnected">"Le casque Bluetooth a été déconnecté."</string>
     <string name="no_vm_number">"Numéro de messagerie vocale manquant"</string>
     <string name="no_vm_number_msg">"Aucun numéro de messagerie vocale n\'est enregistré sur la carte SIM."</string>
     <string name="add_vm_number_str">"Ajouter un numéro"</string>
index e499bcf..15b16c3 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"Inviare i numeri successivi?"\n</string>
     <string name="send_button">"Invia"</string>
     <string name="wild_prompt_str">"Sostituisci carattere jolly con"</string>
-    <string name="bluetooth_headset_connected">"Auricolare Bluetooth collegato."</string>
-    <string name="bluetooth_headset_disconnected">"Auricolare Bluetooth scollegato."</string>
     <string name="no_vm_number">"Numero segreteria mancante"</string>
     <string name="no_vm_number_msg">"Nessun numero di segreteria presente nella SIM."</string>
     <string name="add_vm_number_str">"Aggiungi numero"</string>
index 4d744fd..a50930c 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"次の番号を送信しますか?"\n</string>
     <string name="send_button">"送信"</string>
     <string name="wild_prompt_str">"ワイルド文字と入れ替える文字"</string>
-    <string name="bluetooth_headset_connected">"Bluetoothヘッドセットが接続されました。"</string>
-    <string name="bluetooth_headset_disconnected">"Bluetoothヘッドセットの接続が切断されました。"</string>
     <string name="no_vm_number">"ボイスメール番号がありません"</string>
     <string name="no_vm_number_msg">"SIMカードにボイスメールの番号がありません。"</string>
     <string name="add_vm_number_str">"番号を追加"</string>
index 297988a..58377f5 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"다음 톤을 보내시겠습니까?"\n</string>
     <string name="send_button">"보내기"</string>
     <string name="wild_prompt_str">"와일드 문자를 다음으로 바꾸기"</string>
-    <string name="bluetooth_headset_connected">"Bluetooth 헤드셋이 연결되었습니다."</string>
-    <string name="bluetooth_headset_disconnected">"Bluetooth 헤드셋 연결이 끊어졌습니다."</string>
     <string name="no_vm_number">"음성메일 번호 없음"</string>
     <string name="no_vm_number_msg">"SIM 카드에 저장된 음성메일 번호가 없습니다."</string>
     <string name="add_vm_number_str">"번호 추가"</string>
index de037a7..339f1d1 100644 (file)
@@ -64,8 +64,6 @@
     <string name="wait_prompt_str">"Send disse tonene?"\n</string>
     <string name="send_button">"Send"</string>
     <string name="wild_prompt_str">"Erstatt jokertegnet med"</string>
-    <string name="bluetooth_headset_connected">"Bluetooth-høretelefoner tilkoblet."</string>
-    <string name="bluetooth_headset_disconnected">"Bluetooth-høretelefoner frakoblet."</string>
     <string name="no_vm_number">"Mangler nummer til telefonsvarer"</string>
     <string name="no_vm_number_msg">"Det er ikke lagret noe telefonsvarernummer på SIM-kortet."</string>
     <string name="add_vm_number_str">"Legg til nummer"</string>
index 6fcd499..258494b 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"De volgende tonen verzenden?"\n</string>
     <string name="send_button">"Verzenden"</string>
     <string name="wild_prompt_str">"Het jokerteken vervangen door"</string>
-    <string name="bluetooth_headset_connected">"Bluetooth-headset aangesloten."</string>
-    <string name="bluetooth_headset_disconnected">"Bluetooth-headset losgekoppeld."</string>
     <string name="no_vm_number">"Voicemailnummer ontbreekt"</string>
     <string name="no_vm_number_msg">"Er is geen voicemailnummer op de SIM-kaart opgeslagen."</string>
     <string name="add_vm_number_str">"Nummer toevoegen"</string>
index a8e07b9..573dd48 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"Wysłać następujące dzwonki?"\n</string>
     <string name="send_button">"Wyślij"</string>
     <string name="wild_prompt_str">"Zastąp symbol wieloznaczny"</string>
-    <string name="bluetooth_headset_connected">"Zestaw słuchawkowy Bluetooth jest podłączony."</string>
-    <string name="bluetooth_headset_disconnected">"Zestaw słuchawkowy Bluetooth jest odłączony."</string>
     <string name="no_vm_number">"Brakuje numeru poczty głosowej"</string>
     <string name="no_vm_number_msg">"Na karcie SIM nie ma zapisanego numeru poczty głosowej."</string>
     <string name="add_vm_number_str">"Dodaj numer"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
new file mode 100644 (file)
index 0000000..387bd82
--- /dev/null
@@ -0,0 +1,572 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="contactsIconLabel">"Contatos"</string>
+    <string name="contactsFavoritesLabel">"Favoritos"</string>
+    <string name="dialerIconLabel">"Discador"</string>
+    <string name="emergencyDialerIconLabel">"Discador de emergência"</string>
+    <string name="phoneIconLabel">"Telefone"</string>
+    <string name="recentCallsIconLabel">"Registro de chamadas"</string>
+    <string name="fdnListLabel">"Lista FDN"</string>
+    <string name="unknown">"Desconhecido"</string>
+    <string name="private_num">"Número particular"</string>
+    <!-- no translation found for payphone (1931775086311769314) -->
+    <skip />
+    <string name="onHold">"Em espera"</string>
+    <string name="ongoing">"Chamada atual"</string>
+    <string name="callFailed_userBusy">"Linha ocupada"</string>
+    <string name="callFailed_congestion">"Rede ocupada"</string>
+    <string name="callFailed_noSignal">"Sem sinal"</string>
+    <string name="callFailed_limitExceeded">"Limite de ACM excedido"</string>
+    <string name="callFailed_powerOff">"Rádio desligado"</string>
+    <string name="callFailed_simError">"Não há SIM ou erro no SIM"</string>
+    <string name="callFailed_outOfService">"Área fora de serviço"</string>
+    <string name="callFailed_fdn_only">"Chamadas realizadas restritas pelo FDN."</string>
+    <string name="callFailed_cb_enabled">"Não é possível fazer chamadas enquanto o bloqueio de chamadas estiver ativada."</string>
+    <!-- no translation found for callFailed_dsac_restricted (2180223622768522345) -->
+    <skip />
+    <!-- no translation found for callFailed_dsac_restricted_emergency (4353654268813314466) -->
+    <skip />
+    <!-- no translation found for callFailed_dsac_restricted_normal (2680774510252408620) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_lockedUntilPowerCycle (775483211928061084) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_drop (6030084920001082496) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_intercept (8402269373120277330) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_reorder (5605791471418711552) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_SO_reject (8969174256492763555) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_retryOrder (5848488692485148804) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_accessFailure (2844306027616452215) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_preempted (1097095321180029879) -->
+    <skip />
+    <!-- no translation found for callFailed_cdma_notEmergency (2347377816822720761) -->
+    <skip />
+    <string name="confCall">"Chamada de conferência"</string>
+    <string name="mmiStarted">"Código MMI iniciado"</string>
+    <string name="ussdRunning">"Código USSD em execução…"</string>
+    <string name="mmiCancelled">"Código MMI cancelado"</string>
+    <string name="cancel">"Cancelar"</string>
+    <!-- no translation found for ecbm_mode_text (6485648046794782672) -->
+    <skip />
+    <!-- no translation found for ecbm_exit_text (622759135506401127) -->
+    <skip />
+    <!-- no translation found for ecbm_ok_text (1373363960570351032) -->
+    <skip />
+    <!-- no translation found for ecbm_emergency_number (4131632362330756509) -->
+    <skip />
+    <!-- no translation found for ecbm_instruction_text (5039940054364946169) -->
+    <skip />
+    <string name="menu_speaker">"Alto-falante"</string>
+    <string name="menu_bluetooth">"Bluetooth"</string>
+    <string name="menu_mute">"Mudo"</string>
+    <string name="menu_hold">"Espera"</string>
+    <string name="menu_endCall">"Finalizar chamada"</string>
+    <string name="menu_swapCalls">"Trocar chamadas"</string>
+    <string name="menu_mergeCalls">"Unir chamadas"</string>
+    <string name="menu_addCall">"Adicionar chamada"</string>
+    <string name="menu_manageConference">"Gerenciar chamada de conferência"</string>
+    <string name="menu_showDialpad">"Mostrar teclado"</string>
+    <string name="menu_hideDialpad">"Ocultar teclado"</string>
+    <string name="menu_answerAndHold">"Colocar a chamada atual em espera "\n"e atender"</string>
+    <string name="menu_answerAndEnd">"Finalizar a chamada atual"\n"e atender"</string>
+    <string name="ok">"OK"</string>
+    <string name="menuButtonHint">"Pressione Menu para ver as opções de chamada."</string>
+    <string name="menuButtonKeyboardDialHint">"Pressione Menu para ver as opções de chamada  •  Use o teclado para digitar"</string>
+    <string name="wait_prompt_str">"Enviar os seguintes tons?"\n</string>
+    <string name="send_button">"Enviar"</string>
+    <string name="wild_prompt_str">"Substituir o caractere curinga por"</string>
+    <string name="no_vm_number">"Número de correio de voz ausente"</string>
+    <string name="no_vm_number_msg">"Nenhum número de correio de voz está armazenado no cartão SIM."</string>
+    <string name="add_vm_number_str">"Adicionar número"</string>
+    <string name="dialer_emptyListWorking">"Carregando…"</string>
+    <string name="enterPin">"Digite o código PIN para desbloquear o cartão SIM."</string>
+    <string name="pinUnlocked">"SIM desbloqueado"</string>
+    <string name="enterNewPin">"Código PIN do novo SIM"</string>
+    <string name="verifyNewPin">"Digite novamente o código PIN do novo SIM para confirmar"</string>
+    <string name="verifyFailed">"Os PINs do SIM digitados não correspondem. Tente novamente."</string>
+    <string name="enterPuk">"Digite o código PUK para desbloquear o cartão SIM"</string>
+    <string name="badPuk">"Código PUK incorreto!"</string>
+    <string name="buttonTxtContinue">"Continuar"</string>
+    <string name="puk_unlocked">"Seu cartão SIM foi desbloqueado. Seu telefone está sendo desbloqueado…"</string>
+    <string name="label_ndp">"PIN de desbloqueio da rede SIM"</string>
+    <string name="sim_ndp_unlock_text">"Desbloquear"</string>
+    <string name="sim_ndp_dismiss_text">"Rejeitar"</string>
+    <string name="requesting_unlock">"Solicitando desbloqueio de rede…"</string>
+    <string name="unlock_failed">"Falha na solicitação de desbloqueio da rede."</string>
+    <string name="unlock_success">"Rede desbloqueada com êxito."</string>
+    <string name="imei">"IMEI"</string>
+    <!-- no translation found for labelGSMMore (5930842194056092106) -->
+    <skip />
+    <!-- no translation found for labelCDMAMore (1630676740428229339) -->
+    <skip />
+    <string name="apn_settings">"Nomes de ponto de acesso"</string>
+    <string name="settings_label">"Configurações de rede"</string>
+    <string name="voicemail">"Correio de voz"</string>
+    <string name="voicemail_abbreviated">"VM:"</string>
+    <string name="networks">"Operadoras de rede"</string>
+    <string name="call_settings">"Configurações da chamada"</string>
+    <!-- no translation found for additional_gsm_call_settings (6472260354879794056) -->
+    <skip />
+    <!-- no translation found for sum_gsm_call_settings (4076647190996778012) -->
+    <skip />
+    <!-- no translation found for additional_cdma_call_settings (8628958775721886909) -->
+    <skip />
+    <!-- no translation found for sum_cdma_call_settings (284753265979035549) -->
+    <skip />
+    <!-- no translation found for labelNwService (4699970172021870983) -->
+    <skip />
+    <string name="labelCallerId">"ID do chamador"</string>
+    <string name="sum_hide_caller_id">"Número oculto em chamadas realizadas"</string>
+    <string name="sum_show_caller_id">"Número exibido em chamadas realizadas"</string>
+    <string name="sum_default_caller_id">"Usar configurações de operador padrão para exibir meu número nas chamadas realizadas"</string>
+    <string name="labelCW">"Chamada em espera"</string>
+    <string name="sum_cw_enabled">"Durante uma chamada, notificar-me sobre chamadas recebidas"</string>
+    <string name="sum_cw_disabled">"Durante uma chamada, notificar-me sobre chamadas recebidas"</string>
+    <string name="call_forwarding_settings">"Configurações de transferência de chamada"</string>
+    <string name="labelCF">"Transferência de chamada"</string>
+    <string name="labelCFU">"Sempre transferir"</string>
+    <string name="messageCFU">"sempre use este número"</string>
+    <string name="sum_cfu_enabled_indicator">"Transferindo todas as chamadas"</string>
+    <string name="sum_cfu_enabled">"Transferindo todas as chamadas para {0}"</string>
+    <string name="sum_cfu_disabled">"Desativado"</string>
+    <string name="labelCFB">"Transferir quando ocupado"</string>
+    <string name="messageCFB">"Número quando ocupado"</string>
+    <string name="sum_cfb_enabled">"Transferindo para \\\\{0\\\\}"</string>
+    <string name="sum_cfb_disabled">"Desativado"</string>
+    <string name="labelCFNRy">"Transferir quando não houver resposta"</string>
+    <string name="messageCFNRy">"Número quando não houver resposta"</string>
+    <string name="sum_cfnry_enabled">"Transferir para \\\\{0\\\\}"</string>
+    <string name="sum_cfnry_disabled">"Desativado"</string>
+    <string name="labelCFNRc">"Transferir quando estiver fora de alcance"</string>
+    <string name="messageCFNRc">"Número quando não estiver disponível"</string>
+    <string name="sum_cfnrc_enabled">"Transferindo para \\\\{0\\\\}"</string>
+    <string name="sum_cfnrc_disabled">"Desativado"</string>
+    <string name="updating_title">"Configurações da chamada"</string>
+    <string name="error_updating_title">"Erro de configuração da chamada"</string>
+    <string name="reading_settings">"Lendo configurações…"</string>
+    <string name="updating_settings">"Atualizando configurações…"</string>
+    <!-- no translation found for response_error (6674110501330139405) -->
+    <skip />
+    <string name="exception_error">"Erro de rede ou do cartão SIM."</string>
+    <string name="radio_off_error">"Ligue o rádio antes de exibir essas configurações."</string>
+    <string name="close_dialog">"OK"</string>
+    <string name="enable">"Ativar"</string>
+    <string name="disable">"Desativar"</string>
+    <string name="change_num">"Atualizar"</string>
+  <string-array name="clir_display_values">
+    <item>"Padrão de rede"</item>
+    <item>"Ocultar número"</item>
+    <item>"Mostrar número"</item>
+  </string-array>
+    <string name="vm_save_number">"Salvar número do correio de voz"</string>
+    <string name="vm_changed">"Número de correio de voz alterado."</string>
+    <string name="vm_change_failed">"Falha na alteração do número de correio de voz."</string>
+    <string name="no_change">"Nenhuma alteração foi feita."</string>
+    <string name="sum_voicemail">"Definir número do correio de voz"</string>
+    <string name="mobile_networks">"Configurações de rede móvel"</string>
+    <string name="label_available">"Redes disponíveis"</string>
+    <string name="load_networks_progress">"Procurando…"</string>
+    <string name="empty_networks_list">"Nenhuma rede encontrada."</string>
+    <string name="search_networks">"Procurar redes"</string>
+    <string name="network_query_error">"Erro ao procurar por redes."</string>
+    <string name="register_on_network">"Registrando no <xliff:g id="NETWORK">%s</xliff:g>…"</string>
+    <string name="not_allowed">"Seu cartão SIM não permite uma conexão com esta rede."</string>
+    <string name="registration_done">"Registrado na rede."</string>
+    <string name="sum_carrier_select">"Selecione um operador de rede"</string>
+    <string name="sum_search_networks">"Procurar todas as redes disponíveis"</string>
+    <string name="select_automatically">"Selecionar automaticamente"</string>
+    <string name="sum_select_automatically">"Selecionar automaticamente a rede preferida"</string>
+    <!-- no translation found for register_automatically (6272031189219101172) -->
+    <skip />
+    <!-- no translation found for preferred_network_mode_title (8873246565334559308) -->
+    <skip />
+    <!-- no translation found for preferred_network_mode_summary (1434820673166126609) -->
+    <skip />
+    <!-- no translation found for preferred_network_mode_dialogtitle (8176355237105593793) -->
+    <skip />
+    <!-- no translation found for preferred_network_mode_choices:0 (2987674222882365152) -->
+    <!-- no translation found for preferred_network_mode_choices:1 (3273348576277144124) -->
+    <!-- no translation found for preferred_network_mode_choices:2 (454610224530856274) -->
+    <!-- no translation found for preferred_network_mode_choices:3 (8928247118825616081) -->
+    <!-- no translation found for preferred_network_mode_choices:4 (8595462903294812666) -->
+    <!-- no translation found for preferred_network_mode_choices:5 (5189164180446264504) -->
+    <!-- no translation found for preferred_network_mode_choices:6 (5714714953966979187) -->
+    <!-- no translation found for preferred_network_mode_choices:7 (4775796025725908913) -->
+    <!-- no translation found for preferred_network_mode_values:0 (7164534877603905916) -->
+    <!-- no translation found for preferred_network_mode_values:1 (2520921432080278213) -->
+    <!-- no translation found for preferred_network_mode_values:2 (4978887990900575049) -->
+    <!-- no translation found for preferred_network_mode_values:3 (6891436459357445885) -->
+    <!-- no translation found for preferred_network_mode_values:4 (339825043192186272) -->
+    <!-- no translation found for preferred_network_mode_values:5 (3062641619893382241) -->
+    <!-- no translation found for preferred_network_mode_values:6 (2494009747968041784) -->
+    <!-- no translation found for preferred_network_mode_values:7 (2568449734331711605) -->
+    <string name="roaming">"Roaming de dados"</string>
+    <string name="roaming_enable">"Conectar aos serviços de dados quando estiver em roaming"</string>
+    <string name="roaming_disable">"Conectar aos serviços de dados quando estiver em roaming"</string>
+    <string name="roaming_reenable_message">"Você perdeu a conectividade dos dados, pois saiu da sua rede doméstica com o roaming de dados desativado."</string>
+    <string name="roaming_warning">"Permitir roaming de dados? Você pode receber cobranças significativas pelo roaming!"</string>
+    <!-- no translation found for gsm_umts_options (6538311689850981686) -->
+    <skip />
+    <!-- no translation found for cdma_options (4016822858172249884) -->
+    <skip />
+    <!-- no translation found for cdma_cell_broadcast_sms (7898475142527341808) -->
+    <skip />
+    <!-- no translation found for cell_broadcast_sms (5584192824053625842) -->
+    <skip />
+    <!-- no translation found for enable_disable_cell_bc_sms (4851147873691392255) -->
+    <skip />
+    <!-- no translation found for cell_bc_sms_enable (6441688565738921084) -->
+    <skip />
+    <!-- no translation found for cell_bc_sms_disable (3398365088309408749) -->
+    <skip />
+    <!-- no translation found for cb_sms_settings (651715019785107312) -->
+    <skip />
+    <!-- no translation found for enable_disable_emergency_broadcast (2157014609041245335) -->
+    <skip />
+    <!-- no translation found for emergency_broadcast_enable (2645980025414010211) -->
+    <skip />
+    <!-- no translation found for emergency_broadcast_disable (3665199821267569426) -->
+    <skip />
+    <!-- no translation found for enable_disable_administrative (6501582322182059412) -->
+    <skip />
+    <!-- no translation found for administrative_enable (1750086122962032235) -->
+    <skip />
+    <!-- no translation found for administrative_disable (8433273857248698539) -->
+    <skip />
+    <!-- no translation found for enable_disable_maintenance (1819693083025106678) -->
+    <skip />
+    <!-- no translation found for maintenance_enable (8566636458770971189) -->
+    <skip />
+    <!-- no translation found for maintenance_disable (7340189100885066077) -->
+    <skip />
+    <!-- no translation found for general_news_settings (4968779723948432978) -->
+    <skip />
+    <!-- no translation found for bf_news_settings (3935593091894685267) -->
+    <skip />
+    <!-- no translation found for sports_news_settings (7649399631270052835) -->
+    <skip />
+    <!-- no translation found for entertainment_news_settings (5051153952959405035) -->
+    <skip />
+    <!-- no translation found for enable_disable_local (7890281063123416120) -->
+    <skip />
+    <!-- no translation found for local_enable (6370463247609136359) -->
+    <skip />
+    <!-- no translation found for local_disable (4405691986943795798) -->
+    <skip />
+    <!-- no translation found for enable_disable_regional (4905652414535565872) -->
+    <skip />
+    <!-- no translation found for regional_enable (4434680415437834759) -->
+    <skip />
+    <!-- no translation found for regional_disable (5359325527213850077) -->
+    <skip />
+    <!-- no translation found for enable_disable_national (236278090206880734) -->
+    <skip />
+    <!-- no translation found for national_enable (1172443648912246952) -->
+    <skip />
+    <!-- no translation found for national_disable (326018148178601166) -->
+    <skip />
+    <!-- no translation found for enable_disable_international (7535348799604565592) -->
+    <skip />
+    <!-- no translation found for international_enable (5855356769925044927) -->
+    <skip />
+    <!-- no translation found for international_disable (2850648591041088931) -->
+    <skip />
+    <!-- no translation found for list_language_title (2841683501919760043) -->
+    <skip />
+    <!-- no translation found for list_language_summary (8109546531071241601) -->
+    <skip />
+    <!-- no translation found for list_language_entries:0 (6137851079727305485) -->
+    <!-- no translation found for list_language_entries:1 (1151988412809572526) -->
+    <!-- no translation found for list_language_entries:2 (577840534704312665) -->
+    <!-- no translation found for list_language_entries:3 (8385712091143148180) -->
+    <!-- no translation found for list_language_entries:4 (1858401628368130638) -->
+    <!-- no translation found for list_language_entries:5 (1933212028684529632) -->
+    <!-- no translation found for list_language_entries:6 (1908428006803639064) -->
+    <!-- no translation found for list_language_values:0 (1804908636436467150) -->
+    <!-- no translation found for list_language_values:1 (289708030346890334) -->
+    <!-- no translation found for list_language_values:2 (1121469729692402684) -->
+    <!-- no translation found for list_language_values:3 (2614093115912897722) -->
+    <!-- no translation found for list_language_values:4 (2411164639857960614) -->
+    <!-- no translation found for list_language_values:5 (5884448729274543324) -->
+    <!-- no translation found for list_language_values:6 (5511864807618312598) -->
+    <!-- no translation found for list_language_dtitle (5442908726538951934) -->
+    <skip />
+    <!-- no translation found for enable_disable_local_weather (986967454867219114) -->
+    <skip />
+    <!-- no translation found for local_weather_enable (6199315114382448922) -->
+    <skip />
+    <!-- no translation found for local_weather_disable (2510158089142626480) -->
+    <skip />
+    <!-- no translation found for enable_disable_atr (8339572391278872343) -->
+    <skip />
+    <!-- no translation found for atr_enable (5541757457789181799) -->
+    <skip />
+    <!-- no translation found for atr_disable (7085558154727596455) -->
+    <skip />
+    <!-- no translation found for enable_disable_lafs (668189073721277199) -->
+    <skip />
+    <!-- no translation found for lafs_enable (2791978667205137052) -->
+    <skip />
+    <!-- no translation found for lafs_disable (2391212397725495350) -->
+    <skip />
+    <!-- no translation found for enable_disable_restaurants (6240381945336814024) -->
+    <skip />
+    <!-- no translation found for restaurants_enable (5137657479469118847) -->
+    <skip />
+    <!-- no translation found for restaurants_disable (3678480270938424092) -->
+    <skip />
+    <!-- no translation found for enable_disable_lodgings (1822029172658551202) -->
+    <skip />
+    <!-- no translation found for lodgings_enable (3230042508992850322) -->
+    <skip />
+    <!-- no translation found for lodgings_disable (3387879742320682391) -->
+    <skip />
+    <!-- no translation found for enable_disable_retail_directory (1357809784475660303) -->
+    <skip />
+    <!-- no translation found for retail_directory_enable (3280626290436111496) -->
+    <skip />
+    <!-- no translation found for retail_directory_disable (6479739816662879027) -->
+    <skip />
+    <!-- no translation found for enable_disable_advertisements (5999495926176182128) -->
+    <skip />
+    <!-- no translation found for advertisements_enable (2050305021264683786) -->
+    <skip />
+    <!-- no translation found for advertisements_disable (8350985908788707935) -->
+    <skip />
+    <!-- no translation found for enable_disable_stock_quotes (6397810445293533603) -->
+    <skip />
+    <!-- no translation found for stock_quotes_enable (4384802470887170543) -->
+    <skip />
+    <!-- no translation found for stock_quotes_disable (4781450084565594998) -->
+    <skip />
+    <!-- no translation found for enable_disable_eo (4863043263443942494) -->
+    <skip />
+    <!-- no translation found for eo_enable (8623559062015685813) -->
+    <skip />
+    <!-- no translation found for eo_disable (3863812478090907609) -->
+    <skip />
+    <!-- no translation found for enable_disable_mhh (5698783743098373681) -->
+    <skip />
+    <!-- no translation found for mhh_enable (3949276822735205799) -->
+    <skip />
+    <!-- no translation found for mhh_disable (4834280270664925123) -->
+    <skip />
+    <!-- no translation found for enable_disable_technology_news (3517184627114999149) -->
+    <skip />
+    <!-- no translation found for technology_news_enable (7995209394210455181) -->
+    <skip />
+    <!-- no translation found for technology_news_disable (5483490380561851946) -->
+    <skip />
+    <!-- no translation found for enable_disable_multi_category (626771003122899280) -->
+    <skip />
+    <!-- no translation found for multi_category_enable (1179299804641721768) -->
+    <skip />
+    <!-- no translation found for multi_category_disable (880104702904139505) -->
+    <skip />
+    <!-- no translation found for gsm_umts_network_preferences_title (4834419333547382436) -->
+    <skip />
+    <!-- no translation found for gsm_umts_network_preferneces_summary (1905018644156819521) -->
+    <skip />
+    <!-- no translation found for gsm_umts_network_preferences_dialogtitle (6356332580813229898) -->
+    <skip />
+    <!-- no translation found for gsm_umts_network_preferences_choices:0 (935612021902787683) -->
+    <!-- no translation found for gsm_umts_network_preferences_choices:1 (8912042051809329533) -->
+    <!-- no translation found for gsm_umts_network_preferences_choices:2 (8776934131146642662) -->
+    <!-- no translation found for gsm_umts_network_preferences_choices:3 (4684679567848300935) -->
+    <!-- no translation found for gsm_umts_network_preferences_values:0 (117293148930527265) -->
+    <!-- no translation found for gsm_umts_network_preferences_values:1 (2264578612775462302) -->
+    <!-- no translation found for gsm_umts_network_preferences_values:2 (1268081943590316978) -->
+    <!-- no translation found for gsm_umts_network_preferences_values:3 (4469871047641902607) -->
+    <!-- no translation found for cdma_roaming_mode_title (6366737033053855198) -->
+    <skip />
+    <!-- no translation found for cdma_roaming_mode_summary (8604713111805562261) -->
+    <skip />
+    <!-- no translation found for cdma_roaming_mode_dialogtitle (1802896889172094947) -->
+    <skip />
+    <!-- no translation found for cdma_roaming_mode_choices:0 (6024072766548865002) -->
+    <!-- no translation found for cdma_roaming_mode_choices:1 (8174642753290624634) -->
+    <!-- no translation found for cdma_roaming_mode_choices:2 (2241951431403168661) -->
+    <!-- no translation found for cdma_roaming_mode_values:0 (2549203161367380954) -->
+    <!-- no translation found for cdma_roaming_mode_values:1 (6007798728227141997) -->
+    <!-- no translation found for cdma_roaming_mode_values:2 (4039511109802141047) -->
+    <!-- no translation found for cdma_network_preferences_title (41193174429510391) -->
+    <skip />
+    <!-- no translation found for cdma_network_preferneces_summary (3524451924935793338) -->
+    <skip />
+    <!-- no translation found for cdma_network_preferences_dialogtitle (4548860809290455653) -->
+    <skip />
+    <!-- no translation found for cdma_network_preferences_choices:0 (3711054371631487248) -->
+    <!-- no translation found for cdma_network_preferences_choices:1 (6143696847467859795) -->
+    <!-- no translation found for cdma_network_preferences_choices:2 (2683555124647197574) -->
+    <!-- no translation found for cdma_network_preferences_values:0 (5584048199290030331) -->
+    <!-- no translation found for cdma_network_preferences_values:1 (5741268642513143762) -->
+    <!-- no translation found for cdma_network_preferences_values:2 (419525200910932450) -->
+    <!-- no translation found for subscription_title (5813493350326486) -->
+    <skip />
+    <!-- no translation found for subscription_summary (8435941016743418124) -->
+    <skip />
+    <!-- no translation found for subscription_dialogtitle (531571450448009255) -->
+    <skip />
+    <!-- no translation found for subscription_choices:0 (6540107472553796600) -->
+    <!-- no translation found for subscription_choices:1 (1433427108940308332) -->
+    <!-- no translation found for subscription_values:0 (4377788417250295786) -->
+    <!-- no translation found for subscription_values:1 (1193066664940329729) -->
+    <string name="fdn">"Números de discagem fixa"</string>
+    <string name="manage_fdn_list">"Lista FDN"</string>
+    <string name="fdn_activation">"Ativação FDN"</string>
+    <string name="fdn_enabled">"Os números de discagem fixos estão ativados"</string>
+    <string name="fdn_disabled">"Os números de discagem fixos estão desativados"</string>
+    <string name="enable_fdn">"Ativar FDN"</string>
+    <string name="disable_fdn">"Desativar FDN"</string>
+    <string name="change_pin2">"Alterar PIN2"</string>
+    <string name="enable_fdn_ok">"Desativar FDN"</string>
+    <string name="disable_fdn_ok">"Ativar FDN"</string>
+    <string name="sum_fdn">"Gerenciar números de discagem fixa"</string>
+    <string name="sum_fdn_change_pin">"Altere o PIN para acesso FDN"</string>
+    <string name="sum_fdn_manage_list">"Gerenciar lista de número de telefones"</string>
+    <!-- no translation found for voice_privacy (7803023024169078619) -->
+    <skip />
+    <!-- no translation found for voice_privacy_summary (3159383389833516214) -->
+    <skip />
+    <!-- no translation found for tty_mode_title (3171521903490559138) -->
+    <skip />
+    <!-- no translation found for tty_mode_summary (5057244302665817977) -->
+    <skip />
+    <!-- no translation found for tty_mode_option_title (9033098925144434669) -->
+    <skip />
+    <!-- no translation found for tty_mode_option_summary (1073835131534808732) -->
+    <skip />
+    <string name="menu_add">"Adicionar contato"</string>
+    <string name="menu_edit">"Editar contato"</string>
+    <string name="menu_delete">"Excluir contato"</string>
+    <string name="get_pin2">"Digitar PIN2"</string>
+    <string name="name">"Nome"</string>
+    <string name="number">"Número"</string>
+    <string name="save">"Salvar"</string>
+    <string name="add_fdn_contact">"Adicionar contato de discagem fixo"</string>
+    <string name="adding_fdn_contact">"Adicionando contato de discagem fixa…"</string>
+    <string name="fdn_contact_added">"Contato de discagem fixa adicionado."</string>
+    <string name="edit_fdn_contact">"Editar contato de discagem fixo"</string>
+    <string name="updating_fdn_contact">"Atualizando contato de discagem fixa…"</string>
+    <string name="fdn_contact_updated">"Contato de discagem fixa atualizado."</string>
+    <string name="delete_fdn_contact">"Excluir contato de discagem fixo"</string>
+    <string name="deleting_fdn_contact">"Excluindo contato de discagem fixa…"</string>
+    <string name="fdn_contact_deleted">"Contato de discagem fixa excluído."</string>
+    <string name="pin2_invalid">"PIN2 inválido!"</string>
+    <string name="fdn_invalid_number">"O número não pode exceder 20 dígitos."</string>
+    <string name="simContacts_emptyLoading">"Lendo o cartão SIM…"</string>
+    <string name="simContacts_empty">"Não há contatos no seu cartão SIM."</string>
+    <string name="simContacts_title">"Selecionar contatos para importar"</string>
+    <string name="enable_pin">"Ativar/desativar PIN do SIM"</string>
+    <string name="change_pin">"Alterar PIN do SIM"</string>
+    <string name="enter_pin_text">"PIN do SIM:"</string>
+    <string name="oldPinLabel">"PIN antigo"</string>
+    <string name="newPinLabel">"Novo PIN"</string>
+    <string name="confirmPinLabel">"Confirmar novo PIN"</string>
+    <string name="badPin">"O PIN antigo digitado não está correto. Tente novamente."</string>
+    <string name="mismatchPin">"Os PINs digitados não correspondem. Tente novamente."</string>
+    <string name="invalidPin">"Digite um PIN com 4 a 8 números."</string>
+    <string name="disable_sim_pin">"Desativar PIN do SIM"</string>
+    <string name="enable_sim_pin">"Ativar PIN do SIM"</string>
+    <string name="enable_in_progress">"Aguarde…"</string>
+    <string name="enable_pin_ok">"PIN do SIM ativado"</string>
+    <string name="disable_pin_ok">"PIN do SIM desativado"</string>
+    <string name="pin_failed">"O PIN digitado estava incorreto"</string>
+    <string name="pin_changed">"PIN do SIM alterado com êxito"</string>
+    <string name="puk_requested">"Senha incorreta, SIM bloqueado! PUK2 solicitado."</string>
+    <string name="enter_pin2_text">"PIN2"</string>
+    <string name="oldPin2Label">"PIN2 antigo"</string>
+    <string name="newPin2Label">"Novo PIN2"</string>
+    <string name="confirmPin2Label">"Confirmar novo PIN2"</string>
+    <string name="badPuk2">"O PUK2 antigo digitado não está correto. Tente novamente."</string>
+    <string name="badPin2">"O PIN2 antigo digitado não está correto. Tente novamente."</string>
+    <string name="mismatchPin2">"Os PIN2s digitados não correspondem. Tente novamente."</string>
+    <string name="invalidPin2">"Digite um PIN2 de 4 a 8 números."</string>
+    <string name="invalidPuk2">"Digite um PUK2 com 8 números."</string>
+    <string name="pin2_changed">"PIN2 alterado com êxito"</string>
+    <string name="label_puk2_code">"Digite o código PUK2"</string>
+    <string name="fdn_enable_puk2_requested">"Senha incorreta, altere o PIN2 e tente novamente!"</string>
+    <string name="puk2_requested">"Senha incorreta, SIM bloqueado! PUK2 solicitado."</string>
+    <string name="doneButton">"Concluído"</string>
+    <string name="caller_manage_header">"Chamada de conferência <xliff:g id="CONF_CALL_TIME">%s</xliff:g>"</string>
+    <string name="caller_manage_manage_done_text">"Voltar à chamada"</string>
+    <string name="sim_missing_continueView_text">"Continuar sem cartão SIM"</string>
+    <string name="sim_missing_msg_text">"Nenhum cartão SIM encontrado. Insira um cartão SIM no telefone."</string>
+    <string name="sim_unlock_dismiss_text">"Rejeitar"</string>
+    <string name="sim_unlock_unlock_text">"Desbloquear"</string>
+    <string name="sim_unlock_status_text">"Autenticando o PIN…"</string>
+    <string name="voicemail_settings_number_label">"Número do correio de voz"</string>
+    <string name="card_title_dialing">"Discando"</string>
+    <string name="card_title_in_progress">"Chamada atual"</string>
+    <string name="card_title_conf_call">"Chamada de conferência"</string>
+    <string name="card_title_incoming_call">"Chamada recebida"</string>
+    <!-- no translation found for card_title_cdma_call_waiting (4532445524811272644) -->
+    <skip />
+    <string name="card_title_call_ended">"Chamada finalizada"</string>
+    <string name="card_title_on_hold">"Em espera"</string>
+    <string name="card_title_hanging_up">"Encerrando"</string>
+    <string name="notification_missedCallTitle">"Chamada perdida"</string>
+    <string name="notification_missedCallsTitle">"Chamadas perdidas"</string>
+    <string name="notification_missedCallsMsg">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> chamadas perdidas"</string>
+    <string name="notification_missedCallTicker">"Chamada perdida de <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
+    <string name="notification_ongoing_call_format">"Chamada atual (<xliff:g id="DURATION">%s</xliff:g>)"</string>
+    <string name="notification_on_hold">"Em espera"</string>
+    <string name="notification_voicemail_title">"Novo correio de voz"</string>
+    <string name="notification_voicemail_text_format">"Discar <xliff:g id="VOICEMAIL_NUMBER">%s</xliff:g>"</string>
+    <string name="notification_voicemail_no_vm_number">"Número do correio de voz desconhecido"</string>
+    <string name="incall_error_power_off">"Para fazer uma chamada, primeiro desative o modo Avião."</string>
+    <string name="incall_error_emergency_only">"Não registrado na rede."</string>
+    <string name="incall_error_no_phone_number_supplied">"Chamada não enviada, nenhum número válido foi digitado."</string>
+    <string name="incall_error_call_failed">"Chamada não enviada."</string>
+    <string name="incall_status_dialed_mmi">"Iniciando seqüência MMI…"</string>
+    <!-- no translation found for incall_status_dialed_fc (1632879988662225263) -->
+    <skip />
+    <string name="incall_error_supp_service_unknown">"Serviço não suportado."</string>
+    <string name="incall_error_supp_service_switch">"Não é possível alternar chamadas."</string>
+    <string name="incall_error_supp_service_separate">"Não é possível separar chamadas."</string>
+    <string name="incall_error_supp_service_transfer">"Não é possível transferir chamadas."</string>
+    <string name="incall_error_supp_service_conference">"Não é possível fazer chamadas de conferência."</string>
+    <string name="incall_error_supp_service_reject">"Não é possível rejeitar chamada."</string>
+    <string name="incall_error_supp_service_hangup">"Não é possível liberar a(s) chamada(s)."</string>
+    <string name="emergency_enable_radio_dialog_title">"Chamada de emergência"</string>
+    <string name="emergency_enable_radio_dialog_message">"Ativando rádio..."</string>
+    <string name="emergency_enable_radio_dialog_retry">"Área fora de serviço, tentando novamente..."</string>
+    <string name="dial_emergency_error">"Chamada não enviada, <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> não é um número de emergência!"</string>
+    <string name="dial_emergency_empty_error">"Chamada não enviada, disque um número de emergência!"</string>
+    <string name="dialerKeyboardHintText">"Use o teclado para discar"</string>
+    <string name="dtmfDialpadHintText">"Teclado multifreqüencial"</string>
+    <!-- no translation found for dtmfDialpadHandleLabel (6077872154488117962) -->
+    <skip />
+    <!-- no translation found for touchLockText (8742463586429019112) -->
+    <skip />
+    <string name="importSimEntry">"Importar"</string>
+    <string name="importAllSimEntries">"Importar tudo"</string>
+    <string name="importingSimContacts">"Importar contatos do SIM"</string>
+    <string name="importToFDNfromContacts">"Importar dos contatos"</string>
+    <!-- no translation found for tty_mode_entries:0 (512950011423868021) -->
+    <!-- no translation found for tty_mode_entries:1 (4781215771530681384) -->
+    <!-- no translation found for tty_mode_entries:2 (5659212685488676933) -->
+    <!-- no translation found for tty_mode_entries:3 (1113703196326500239) -->
+    <!-- no translation found for eri_text_label (4326942349915331461) -->
+    <skip />
+</resources>
index 0a01608..d115d68 100644 (file)
@@ -63,8 +63,6 @@
     <string name="wait_prompt_str">"Набрать следующие цифры?"\n</string>
     <string name="send_button">"Отправить"</string>
     <string name="wild_prompt_str">"Заменить подстановочный символ"</string>
-    <string name="bluetooth_headset_connected">"Гарнитура Bluetooth подключена."</string>
-    <string name="bluetooth_headset_disconnected">"Гарнитура Bluetooth отключена."</string>
     <string name="no_vm_number">"Номер голосовой почты отсутствует"</string>
     <string name="no_vm_number_msg">"Номер голосовой почты не сохранен на SIM-карте."</string>
     <string name="add_vm_number_str">"Добавить номер"</string>
index 20982d4..b7e39a2 100644 (file)
@@ -64,8 +64,6 @@
     <string name="wait_prompt_str">"是否发送以下音调?"\n</string>
     <string name="send_button">"发送"</string>
     <string name="wild_prompt_str">"用以下内容替换通配符"</string>
-    <string name="bluetooth_headset_connected">"蓝牙耳机已连接。"</string>
-    <string name="bluetooth_headset_disconnected">"蓝牙耳机已断开连接。"</string>
     <string name="no_vm_number">"错过语音信箱号码"</string>
     <string name="no_vm_number_msg">"SIM 卡上没有存储语音信箱号码。"</string>
     <string name="add_vm_number_str">"添加号码"</string>
index 9585df0..d479f48 100644 (file)
@@ -64,8 +64,6 @@
     <string name="wait_prompt_str">"傳送此鈴聲?"\n</string>
     <string name="send_button">"傳送"</string>
     <string name="wild_prompt_str">"取代萬用字元為"</string>
-    <string name="bluetooth_headset_connected">"藍牙耳機已連線。"</string>
-    <string name="bluetooth_headset_disconnected">"藍牙耳機已中斷連線。"</string>
     <string name="no_vm_number">"遺失語音信箱號碼"</string>
     <string name="no_vm_number_msg">"SIM 卡中未儲存語音信箱號碼。"</string>
     <string name="add_vm_number_str">"新增號碼"</string>
old mode 100644 (file)
new mode 100755 (executable)
index 1286a9a..03f59a5
@@ -28,4 +28,6 @@
     <item type="id" name="menuHold" />
     <item type="id" name="menuAnswerAndHold" />
     <item type="id" name="menuAnswerAndEnd" />
+    <item type="id" name="menuAnswer" />
+    <item type="id" name="menuIgnore" />
 </resources>
old mode 100644 (file)
new mode 100755 (executable)
index 3076a43..c57c9f9
     <string name="callFailed_dsac_restricted_emergency">Emergency calls are restricted by access control.</string>
     <!-- In-call screen: call failure reason (Normal call denied because domain specific access control is on)-->
     <string name="callFailed_dsac_restricted_normal">Normal calls are restricted by access control.</string>
+    <!-- In-call screen: call failure reason (Phone is locked until next power cycle)-->
+    <string name="callFailed_cdma_lockedUntilPowerCycle">CDMA: Phone locked until power cycle.</string>
+    <!-- In-call screen: call failure reason (CDMA: call dropped)-->
+    <string name="callFailed_cdma_drop">CDMA: Call dropped.</string>
+    <!-- In-call screen: call failure reason (CDMA: call intercepted)-->
+    <string name="callFailed_cdma_intercept">CDMA: Call intercepted.</string>
+    <!-- In-call screen: call failure reason (CDMA reorder)-->
+    <string name="callFailed_cdma_reorder">CDMA: reorder.</string>
+    <!-- In-call screen: call failure reason (CDMA: Service Option Reject)-->
+    <string name="callFailed_cdma_SO_reject">CDMA: Service Option Reject.</string>
+    <!-- In-call screen: call failure reason (CDMA: retry order)-->
+    <string name="callFailed_cdma_retryOrder">CDMA: retry order.</string>
+    <!-- In-call screen: call failure reason (CDMA: Access failure)-->
+    <string name="callFailed_cdma_accessFailure">CDMA: Access failure.</string>
+    <!-- In-call screen: call failure reason (CDMA: Preempted)-->
+    <string name="callFailed_cdma_preempted">CDMA: Preempted.</string>
+    <!-- In-call screen: call failure reason (Only Emergency calls are possible)-->
+    <string name="callFailed_cdma_notEmergency">Only Emergency calls are possible.</string>
     <!-- In-call screen: status label for a conference call -->
     <string name="confCall">Conference call</string>
 
     <!-- Label for "cancel" button on the MMI dialog -->
     <string name="cancel">Cancel</string>
 
+    <!-- ECBM strings -->
+    <string name="ecbm_mode_text">Emergency Call Back</string>
+    <string name="ecbm_exit_text">EXIT</string>
+    <string name="ecbm_ok_text">  OK  </string>
+    <string name="ecbm_emergency_number">Dial 911</string>
+    <string name="ecbm_instruction_text">Press button for emergency call</string>
+
     <!-- In-call menu item labels -->
     <!-- Regular in-call menu items: -->
     <!-- In-call menu: Label for "speakerphone" menu item -->
     <string name="menuButtonHint">Press Menu for call options.</string>
     <!-- In-call screen, message just under call window when keyboard is revealed -->
     <string name="menuButtonKeyboardDialHint">"Press Menu for call options  \u2022  Use keyboard to dial"</string>
+    <!-- Incoming call menu: Label for "Answer" menu item -->
+    <string name="menu_answer">Answer</string>
+    <!-- Incoming call menu: Label for "Ignore" menu item -->
+    <string name="menu_ignore">Ignore</string>
 
     <!-- post dial -->
     <!-- In-call screen: body text of the dialog that appears when we encounter
          replace the "wild" character. -->
     <string name="wild_prompt_str">Replace the wild character with</string>
 
-    <!-- bluetooth -->
-    <!-- Text displayed in a popup message (toast) when a bluetooth headset is connected -->
-    <string name="bluetooth_headset_connected">Bluetooth headset connected.</string>
-    <!-- Text displayed in a popup message (toast) when a bluetooth headset is disconnected -->
-    <string name="bluetooth_headset_disconnected">Bluetooth headset disconnected.</string>
-
     <!-- missing voicemail number -->
     <!-- Title of the "Missing voicemail number" dialog -->
     <string name="no_vm_number">Missing voicemail number</string>
         <item>"2"</item>
         <item>"3"</item>
     </string-array>
+
+    <!-- CDMA System select strings -->
+    <!-- Mobile network settings screen, setting option name -->
+    <string name="cdma_system_select_title">System select</string>
+    <!-- Mobile network settings screen, setting summary text -->
+    <string name="cdma_system_select_summary">Change the cdma roaming mode</string>
+    <!-- System select settings screen title -->
+    <string name="cdma_system_select_dialogtitle">System select</string>
+    <string-array name="cdma_system_select_choices">
+        <!-- System select dialog screen, setting option name -->
+        <item>Home only</item>
+        <!-- Remove the following option "Affiliated Networks" from the option list -->
+        <!-- <item>Affiliated Networks</item> -->
+        <!-- System select dialog screen, setting option name -->
+        <item>Automatic</item>
+    </string-array>
+    <string-array name="cdma_system_select_values">
+        <!-- Do not translate. -->
+        <item>"0"</item>
+        <!-- Remove the following value "1" which corresponds to "Affiliated Networks" above -->
+        <!-- <item>"1"</item>  -->
+        <!-- Do not translate. -->
+        <item>"2"</item>
+    </string-array>
+
     <!-- CDMA Options strings --> 
     <string name="cdma_roaming_mode_title">CDMA Roaming Mode</string>
     <string name="cdma_roaming_mode_summary">Change the cdma roaming mode</string>
     <string name="voice_privacy_summary">Enable enhanced privacy mode</string>
     <string name="tty_mode_title">TTY mode</string>
     <string name="tty_mode_summary">Enable TTY mode</string>
+    <string name="tty_mode_option_title">TTY mode</string>
+    <string name="tty_mode_option_summary">Set TTY mode</string>
 
     <!-- FDN list screen: menu item label -->
     <string name="menu_add">Add contact</string>
     <string name="card_title_conf_call">Conference call</string>
     <!-- In-call screen: status label for an incoming call -->
     <string name="card_title_incoming_call">Incoming call</string>
+    <!-- In-call screen: status label for an cdma call waiting -->
+    <string name="card_title_cdma_call_waiting">Cdma callwaiting </string>
     <!-- In-call screen: status label displayed briefly after a call ends -->
     <string name="card_title_call_ended">Call ended</string>
     <!-- In-call screen: status label for call that's on hold -->
     <string name="card_title_on_hold">On hold</string>
     <!-- In-call screen: status label for a call that's in the process of hanging up -->
     <string name="card_title_hanging_up">Hanging up</string>
+    <!-- In-call screen: status label for a call that's in CDMA flash mode -->
+    <string name="card_title_in_call">In call</string>
 
     <!-- Notification strings -->
     <!-- Missed call notification label, used when there's exactly one missed call -->
     <string name="notification_on_hold">On hold</string>
     <!-- Label for the "Voicemail" notification item, when expanded. -->
     <string name="notification_voicemail_title">New voicemail</string>
+    <!-- Label for the expanded "Voicemail" notification item,
+         including a count of messages. -->
+    <string name="notification_voicemail_title_count">New voicemail (<xliff:g id="count">%d</xliff:g>)</string>
     <!-- Message displayed in the "Voicemail" notification item, allowing the user
          to dial the indicated number. -->
     <string name="notification_voicemail_text_format">Dial <xliff:g id="voicemail_number">%s</xliff:g></string>
          screen. -->
     <string name="touchLockText">Tap twice\nto unlock</string>
 
+    <!-- Text for the onscreen "Answer" button, instructing the user that
+         they need to double-tap to answer the incoming call. -->
+    <string name="onscreenAnswerText">Tap twice\nto answer</string>
+
     <!-- Menu item label in SIM Contacts: Import a single contact entry from the SIM card -->
     <string name="importSimEntry">Import</string>
     <!-- Menu item label in SIM Contacts: Import all contact entries from the SIM card -->
     <!-- Import a single contact entry from contacts to the SIM card -->
     <string name="importToFDNfromContacts">Import from contacts</string>
 
+    <!-- Service option entries.  -->
+    <string-array name="tty_mode_entries">
+        <item>TTY Off</item>
+        <item>TTY HCO</item>
+        <item>TTY VCO</item>
+        <item>TTY Full</item>
+    </string-array>
+
+    <!-- Do not translate. -->
+    <string-array name="tty_mode_values">
+        <!-- Do not translate. -->
+        <item>0</item>"
+        <!-- Do not translate. -->
+        <item>2</item>
+        <!-- Do not translate. -->
+        <item>3</item>
+        <!-- Do not translate. -->
+        <item>1</item>
+    </string-array>
+
+    <!-- Label for ERI text widget, shown in list of all gadgets -->
+    <string name="eri_text_label">ERI text</string>
+
+    <!-- Dtmf tones settings -->
+    <!-- Title for the DTMF Tones options displayed in Call Settings -->
+    <string name="dtmf_tones_title">DTMF Tones</string>
+    <!-- Summary for the DTMF Tones options displayed in Call Settings -->
+    <string name="dtmf_tones_summary">Set the length of DTMF tones</string>
+    <!-- Options displayed as part of DTMF Tones in Call Settings -->
+    <string-array name="dtmf_tone_entries">
+      <item>Normal</item>
+      <item>Long</item>
+    </string-array>
+    <!-- Do not translate. -->
+    <string-array name="dtmf_tone_values">
+       <item>0</item>
+       <item>1</item>
+    </string-array>
+
+    <!-- Title for the dialog used to display CDMA DisplayInfo -->
+    <string name="network_message">Network Message</string>
+
 </resources>
 
 
index 7729c67..9ffa05f 100644 (file)
         <item name="changeNumButtonText">@string/change_num</item>
         <item name="confirmMode">activation</item>
     </style>
+
+    <!-- Preference Style for the emergency callback mode -->
+    <!-- This styles is currently not used and just prepared for further usage -->
+    <style name="EmergencyCallBack">
+        <item name="android:textSize">20sp</item>
+        <item name="android:textColor">#ffffff</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:colorForeground">#fff</item>
+    </style>
+
+    <!-- Preference Style for the ERI text -->
+    <style name="EriWidgetBackground">
+    </style>
+
+    <style name="TextAppearance.EriWidget">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColor">@android:color/black</item>
+    </style>
+
+
+
 </resources>
index 2bdb741..0b26b2e 100644 (file)
             android:persistent="false"
             android:summary="@string/voice_privacy_summary"/>
             
-        <CheckBoxPreference 
+<!--         <CheckBoxPreference 
             android:key="button_tty_mode_key"
             android:title="@string/tty_mode_title"
             android:persistent="true"
             android:summary="@string/tty_mode_summary"/>
-            
+-->            
+        <!-- CDMA TTY Options -->
+        <ListPreference
+            android:key="button_tty_mode_key"
+            android:title="@string/tty_mode_option_title"
+            android:summary="@string/tty_mode_option_summary"
+            android:persistent="false"
+            android:entries="@array/tty_mode_entries"
+            android:entryValues="@array/tty_mode_values" />
+
     </PreferenceScreen>
                     
 
diff --git a/res/xml/cdma_call_feature_setting.xml b/res/xml/cdma_call_feature_setting.xml
new file mode 100755 (executable)
index 0000000..98554ac
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:phone="http://schemas.android.com/apk/res/com.android.phone">
+
+    <PreferenceCategory
+        android:title="@string/call_settings"/>
+
+    <!-- Note for all com.android.phone.EditPhoneNumberPreference objects
+
+         The last several attributes are for use with the EditText field
+         in the dialog.  These attributes are forwarded to that field
+         when the edittext is created.  The attributes include:
+           1. android:singleLine
+           2. android:autoText
+           3. android:background -->
+
+    <!-- Rearranged to allow for lazy queries. -->
+
+    <com.android.phone.EditPhoneNumberPreference
+        android:key="button_voicemail_key"
+        android:title="@string/voicemail"
+        android:summary="@string/sum_voicemail"
+        android:persistent="false"
+        android:dialogTitle="@string/voicemail"
+        phone:confirmMode="confirm"
+        android:singleLine="true"
+        android:autoText="false"/>
+
+    <CheckBoxPreference
+        android:key="button_voice_privacy_key"
+        android:title="@string/voice_privacy"
+        android:persistent="false"
+        android:summary="@string/voice_privacy_summary"/>
+
+ <!-- <CheckBoxPreference
+            android:key="button_tty_mode_key"
+            android:title="@string/tty_mode_title"
+            android:persistent="true"
+            android:summary="@string/tty_mode_summary"/>
+-->
+    <!-- CDMA TTY Options -->
+    <ListPreference
+        android:key="button_tty_mode_key"
+        android:title="@string/tty_mode_option_title"
+        android:summary="@string/tty_mode_option_summary"
+        android:persistent="false"
+        android:entries="@array/tty_mode_entries"
+        android:entryValues="@array/tty_mode_values" />
+    <!-- CDMA DTMF Options -->
+    <ListPreference
+        android:key="dtmf_settings"
+        android:title="@string/dtmf_tones_title"
+        android:summary="@string/dtmf_tones_summary"
+        android:entries="@array/dtmf_tone_entries"
+        android:entryValues="@array/dtmf_tone_values" />
+
+
+</PreferenceScreen>
diff --git a/res/xml/eri_text_appwidget.xml b/res/xml/eri_text_appwidget.xml
new file mode 100644 (file)
index 0000000..82bc2c7
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+     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.
+-->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minWidth="146dip"
+    android:minHeight="72dip"
+    android:updatePeriodMillis="0"
+    android:initialLayout="@layout/eri_text_layout"
+    >
+</appwidget-provider>
index 7c854c6..d9fdd3f 100644 (file)
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:settings="http://schemas.android.com/apk/res/com.android.phone">
-        
-    <PreferenceCategory 
-        android:title="@string/gsm_umts_options" />          
 
     <PreferenceScreen 
         android:key="button_apn_key" 
         android:title="@string/apn_settings"
         android:persistent="false">
-        
+
         <intent android:action="android.intent.action.MAIN"
             android:targetPackage="com.android.settings"
             android:targetClass="com.android.settings.ApnSettings" />
-            
+
     </PreferenceScreen>
-           
+
     <PreferenceScreen 
         android:key="button_carrier_sel_key" 
         android:title="@string/networks"
         android:summary="@string/sum_carrier_select"
         android:persistent="false">
-        
+
         <intent android:action="android.intent.action.MAIN"
             android:targetPackage="com.android.phone"
             android:targetClass="com.android.phone.NetworkSetting" />
-        
+
     </PreferenceScreen>
 
 </PreferenceScreen>   
diff --git a/res/xml/network_setting_cdma.xml b/res/xml/network_setting_cdma.xml
new file mode 100644 (file)
index 0000000..f389bed
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:phone="http://schemas.android.com/apk/res/com.android.phone">
+
+    <PreferenceCategory
+        android:title="@string/mobile_networks"/>
+
+    <CheckBoxPreference
+        android:key="button_roaming_key"
+        android:title="@string/roaming"
+        android:persistent="false"
+        android:summaryOn="@string/roaming_enable"
+        android:summaryOff="@string/roaming_disable"/>
+
+    <!--
+    <ListPreference
+        android:key="preferred_network_mode_key"
+        android:title="@string/preferred_network_mode_title"
+        android:summary="@string/preferred_network_mode_summary"
+        android:entries="@array/preferred_network_mode_choices"
+        android:entryValues="@array/preferred_network_mode_values"
+        android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
+    -->
+
+    <ListPreference
+        android:key="cdma_system_select_key"
+        android:title="@string/cdma_system_select_title"
+        android:summary="@string/cdma_system_select_summary"
+        android:entries="@array/cdma_system_select_choices"
+        android:entryValues="@array/cdma_system_select_values"
+        android:dialogTitle="@string/cdma_system_select_dialogtitle" />
+
+    <!--
+    <PreferenceScreen
+        android:key="gsm_umts_options_key"
+        android:title="@string/gsm_umts_options"
+        android:persistent="false">
+
+        <intent android:action="android.intent.action.MAIN"
+            android:targetPackage="com.android.phone"
+            android:targetClass="com.android.phone.GsmUmtsOptions" />
+
+    </PreferenceScreen>
+
+    <PreferenceScreen
+        android:key="cdma_options_key"
+        android:title="@string/cdma_options"
+        android:persistent="false">
+
+        <intent android:action="android.intent.action.MAIN"
+            android:targetPackage="com.android.phone"
+            android:targetClass="com.android.phone.CdmaOptions" />
+
+    </PreferenceScreen>
+    -->
+</PreferenceScreen>
index 6e14a09..297ec89 100644 (file)
@@ -115,18 +115,21 @@ public class BluetoothAtPhonebook {
     
     public void register(AtParser parser) {
         // Select Character Set
-        // We support IRA and GSM (although we behave the same for both)
+        // Always send UTF-8, but pretend to support IRA and GSM for compatability
+        // TODO: Implement IRA and GSM encoding instead of faking it
         parser.register("+CSCS", new AtCommandHandler() {
             @Override
             public AtCommandResult handleReadCommand() {
-                return new AtCommandResult("+CSCS: \"IRA\"");
+                return new AtCommandResult("+CSCS: \"UTF-8\"");
             }
             @Override
             public AtCommandResult handleSetCommand(Object[] args) {
                 if (args.length < 1) {
                     return new AtCommandResult(AtCommandResult.ERROR);
                 }
-                if (((String)args[0]).equals("\"GSM\"") || ((String)args[0]).equals("\"IRA\"")) {
+                if (((String)args[0]).equals("\"GSM\"") || ((String)args[0]).equals("\"IRA\"") ||
+                        ((String)args[0]).equals("\"UTF-8\"") ||
+                        ((String)args[0]).equals("\"UTF8\"") ) {
                     return new AtCommandResult(AtCommandResult.OK);
                 } else {
                     return mHandsfree.reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED);
@@ -134,7 +137,7 @@ public class BluetoothAtPhonebook {
             }
             @Override
             public AtCommandResult handleTestCommand() {
-                return new AtCommandResult( "+CSCS: (\"IRA\",\"GSM\")");
+                return new AtCommandResult( "+CSCS: (\"UTF-8\",\"IRA\",\"GSM\")");
             }
         });
 
index 8267669..2a485fc 100644 (file)
@@ -40,6 +40,7 @@ import android.os.PowerManager.WakeLock;
 import android.os.SystemProperties;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.util.Log;
 
 import com.android.internal.telephony.Call;
@@ -93,7 +94,10 @@ public class BluetoothHandsfree {
     private boolean[] mClccUsed;     // Is this clcc index in use
     private boolean mWaitingForCallStart;
     private boolean mWaitingForVoiceRecognition;
-
+    // do not connect audio until service connection is established
+    // for 3-way supported devices, this is after AT+CHLD
+    // for non-3-way supported devices, this is after AT+CMER (see spec)
+    private boolean mServiceConnectionEstablished;
     private final BluetoothPhoneState mPhoneState;  // for CIND and CIEV updates
     private final BluetoothAtPhonebook mPhonebook;
 
@@ -257,6 +261,7 @@ public class BluetoothHandsfree {
     private void resetAtState() {
         mClip = false;
         mIndicatorsEnabled = false;
+        mServiceConnectionEstablished = false;
         mCmee = false;
         mClccTimestamps = new long[MAX_CONNECTIONS];
         mClccUsed = new boolean[MAX_CONNECTIONS];
@@ -355,7 +360,7 @@ public class BluetoothHandsfree {
             updatePhoneState(false, null);
             mBattchg = 5;  // There is currently no API to get battery level
                            // on demand, so set to 5 and wait for an update
-            mSignal = asuToSignal(mPhone.getSignalStrengthASU());
+            mSignal = asuToSignal(mPhone.getSignalStrength());
 
             // register for updates
             mPhone.registerForServiceStateChanged(mStateChangeHandler,
@@ -390,7 +395,7 @@ public class BluetoothHandsfree {
         /* convert [0,31] ASU signal strength to the [0,5] expected by
          * bluetooth devices. Scale is similar to status bar policy
          */
-        private int asuToSignal(int asu) {
+        private int gsmAsuToSignal(int asu) {
             if      (asu >= 16) return 5;
             else if (asu >= 8)  return 4;
             else if (asu >= 4)  return 3;
@@ -399,6 +404,28 @@ public class BluetoothHandsfree {
             else                return 0;
         }
 
+        /* convert cdma dBm signal strength to the [0,5] expected by
+         * bluetooth devices. Scale is similar to status bar policy
+         */
+        private int cdmaDbmToSignal(int cdmaDbm) {
+            if (cdmaDbm >= -75)       return 5;
+            else if (cdmaDbm >= -85)  return 4;
+            else if (cdmaDbm >= -95)  return 3;
+            else if (cdmaDbm >= -100) return 2;
+            else if (cdmaDbm >= -105) return 2;
+            else return 0;
+        }
+
+
+        private int asuToSignal(SignalStrength signalStrength) {
+            if (!signalStrength.isGsm()) {
+                return gsmAsuToSignal(signalStrength.getCdmaDbm());
+            } else {
+                return cdmaDbmToSignal(signalStrength.getGsmSignalStrength());
+            }
+        }
+
+
         /* convert [0,5] signal strength to a rssi signal strength for CSQ
          * which is [0,31]. Despite the same scale, this is not the same value
          * as ASU.
@@ -444,14 +471,22 @@ public class BluetoothHandsfree {
         }
 
         private synchronized void updateSignalState(Intent intent) {
+            // NOTE this function is called by the BroadcastReceiver mStateReceiver after intent
+            // ACTION_SIGNAL_STRENGTH_CHANGED and by the DebugThread mDebugThread
+            SignalStrength signalStrength = SignalStrength.newFromBundle(intent.getExtras());
             int signal;
-            signal = asuToSignal(intent.getIntExtra("asu", -1));
-            mRssi = signalToRssi(signal);  // no unsolicited CSQ
-            if (signal != mSignal) {
-                mSignal = signal;
-                if (sendUpdate()) {
-                    sendURC("+CIEV: 5," + mSignal);
+
+            if (signalStrength != null) {
+                signal = asuToSignal(signalStrength);
+                mRssi = signalToRssi(signal);  // no unsolicited CSQ
+                if (signal != mSignal) {
+                    mSignal = signal;
+                    if (sendUpdate()) {
+                        sendURC("+CIEV: 5," + mSignal);
+                    }
                 }
+            } else {
+                Log.e(TAG, "Signal Strength null");
             }
         }
 
@@ -783,6 +818,10 @@ public class BluetoothHandsfree {
             if (DBG) log("audioOn(): headset is not connected!");
             return false;
         }
+        if (mHeadsetType == TYPE_HANDSFREE && !mServiceConnectionEstablished) {
+            if (DBG) log("audioOn(): service connection not yet established!");
+            return false;
+        }
 
         if (mConnectedSco != null) {
             if (DBG) log("audioOn(): audio is already connected");
@@ -1182,17 +1221,29 @@ public class BluetoothHandsfree {
                     return new AtCommandResult(AtCommandResult.ERROR);
                 } else if (args[0].equals(3) && args[1].equals(0) &&
                            args[2].equals(0)) {
+                    boolean valid = false;
                     if (args[3].equals(0)) {
                         mIndicatorsEnabled = false;
-                        return new AtCommandResult(AtCommandResult.OK);
+                        valid = true;
                     } else if (args[3].equals(1)) {
                         mIndicatorsEnabled = true;
-                        return new AtCommandResult(AtCommandResult.OK);
+                        valid = true;
+                    }
+                    if (valid) {
+                        if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) == 0x0) {
+                            mServiceConnectionEstablished = true;
+                            sendURC("OK");  // send immediately, then initiate audio
+                            if (isIncallAudio()) {
+                                audioOn();
+                            }
+                            // only send OK once
+                            return new AtCommandResult(AtCommandResult.UNSOLICITED);
+                        } else {
+                            return new AtCommandResult(AtCommandResult.OK);
+                        }
                     }
-                    return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED);
-                } else {
-                    return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED);
                 }
+                return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED);
             }
             @Override
             public AtCommandResult handleTestCommand() {
@@ -1350,7 +1401,14 @@ public class BluetoothHandsfree {
             }
             @Override
             public AtCommandResult handleTestCommand() {
-                return new AtCommandResult("+CHLD: (0,1,2,3)");
+                mServiceConnectionEstablished = true;
+                sendURC("+CHLD: (0,1,2,3)");
+                sendURC("OK");  // send reply first, then connect audio
+                if (isIncallAudio()) {
+                    audioOn();
+                }
+                // already replied
+                return new AtCommandResult(AtCommandResult.UNSOLICITED);
             }
         });
 
@@ -1774,8 +1832,12 @@ public class BluetoothHandsfree {
 
                 int signalLevel = SystemProperties.getInt(DEBUG_HANDSFREE_SIGNAL, -1);
                 if (signalLevel >= 0 && signalLevel <= 31) {
+                    SignalStrength signalStrength = new SignalStrength(signalLevel, -1, -1, -1,
+                            -1, -1, -1, true);
                     Intent intent = new Intent();
-                    intent.putExtra("asu", signalLevel);
+                    Bundle data = new Bundle();
+                    signalStrength.fillInNotifierBundle(data);
+                    intent.putExtras(data);
                     mPhoneState.updateSignalState(intent);
                 }
 
index fec992c..ab298e0 100644 (file)
@@ -650,6 +650,11 @@ public class BluetoothHeadsetService extends Service {
             }
             return mHeadsetPriority.get(address.toUpperCase());
         }
+        public int getBatteryUsageHint() {
+            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+
+            return HeadsetBase.getAtInputCount();
+        }
     };
 
     @Override
old mode 100644 (file)
new mode 100755 (executable)
index 7480e13..418cf40
@@ -40,6 +40,8 @@ import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import java.util.List;
+
 /**
  * "Call card" UI element: the in-call screen contains a tiled layout of call
  * cards, each representing the state of a current "call" (ie. an active call,
@@ -58,6 +60,9 @@ public class CallCard extends FrameLayout
      */
     private InCallScreen mInCallScreen;
 
+    // Phone app instance
+    private PhoneApp mApplication;
+
     // Top-level subviews of the CallCard
     private ViewGroup mMainCallCard;
     private ViewGroup mOtherCallOngoingInfoArea;
@@ -120,6 +125,8 @@ public class CallCard extends FrameLayout
                 this,                // root
                 true);
 
+        mApplication = PhoneApp.getInstance();
+
         mCallTime = new CallTime(this);
 
         // create a new object to track the state for the photo.
@@ -130,14 +137,6 @@ public class CallCard extends FrameLayout
         mInCallScreen = inCallScreen;
     }
 
-    void reset() {
-        if (DBG) log("reset()...");
-
-        // default to show ACTIVE call style, with empty title and status text
-        showCallConnected();
-        setUpperTitle("");
-    }
-
     public void onTickForCallTimeElapsed(long timeElapsed) {
         // While a call is in progress, update the elapsed time shown
         // onscreen.
@@ -190,6 +189,10 @@ public class CallCard extends FrameLayout
         mMenuButtonHint = (TextView) findViewById(R.id.menuButtonHint);
     }
 
+    /**
+     * Updates the state of all UI elements on the CallCard, based on the
+     * current state of the phone.
+     */
     void updateState(Phone phone) {
         if (DBG) log("updateState(" + phone + ")...");
 
@@ -265,7 +268,38 @@ public class CallCard extends FrameLayout
         }
 
         displayMainCallStatus(phone, fgCall);
-        displayOnHoldCallStatus(phone, bgCall);
+
+        if (phone.getPhoneName().equals("CDMA")) {
+            if (mApplication.cdmaPhoneCallState.getCurrentCallState()
+                    == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
+                displayOnHoldCallStatus(phone, fgCall);
+            } else {
+                //This is required so that even if a background call is not present
+                // we need to clean up the background call area.
+                displayOnHoldCallStatus(phone, bgCall);
+            }
+        } else {
+            displayOnHoldCallStatus(phone, bgCall);
+        }
+
+        displayOngoingCallStatus(phone, null);
+    }
+
+    /**
+     * Updates the UI for the "generic call" state, where the phone is in
+     * use but we don't know any specific details about the state of the
+     * call (like who you're talking to, or how many lines are in use.)
+     */
+    private void updateGenericCall(Phone phone) {
+        if (DBG) log("updateForegroundCall()...");
+
+        Call fgCall = phone.getForegroundCall();
+
+        // Display the special "generic" state in the main call area:
+        displayMainCallGeneric(phone, fgCall);
+
+        // And hide the "other call" info areas:
+        displayOnHoldCallStatus(phone, null);
         displayOngoingCallStatus(phone, null);
     }
 
@@ -287,9 +321,7 @@ public class CallCard extends FrameLayout
 
     /**
      * Updates the UI for the state where the phone is not in use.
-
      * This is analogous to updateForegroundCall() and updateRingingCall(),
-
      * but for the (uncommon) case where the phone is
      * totally idle.  (See comments in updateState() above.)
      *
@@ -331,12 +363,10 @@ public class CallCard extends FrameLayout
         boolean landscapeMode = InCallScreen.ConfigurationHelper.isLandscape();
 
         // Background images are also different if Bluetooth is active.
-        final boolean bluetoothActive = PhoneApp.getInstance().showBluetoothIndication();
+        final boolean bluetoothActive = mApplication.showBluetoothIndication();
 
         switch (state) {
             case ACTIVE:
-                showCallConnected();
-
                 if (bluetoothActive) {
                     callCardBackgroundResid =
                             landscapeMode ? R.drawable.incall_frame_bluetooth_tall_land
@@ -347,7 +377,6 @@ public class CallCard extends FrameLayout
                             : R.drawable.incall_frame_connected_tall_port;
                 }
 
-
                 // update timer field
                 if (DBG) log("displayMainCallStatus: start periodicUpdateTimer");
                 mCallTime.setActiveCallMode(call);
@@ -357,8 +386,6 @@ public class CallCard extends FrameLayout
                 break;
 
             case HOLDING:
-                showCallOnhold();
-
                 callCardBackgroundResid =
                         landscapeMode ? R.drawable.incall_frame_hold_tall_land
                         : R.drawable.incall_frame_hold_tall_port;
@@ -369,9 +396,6 @@ public class CallCard extends FrameLayout
                 break;
 
             case DISCONNECTED:
-                reset();
-                showCallEnded();
-
                 callCardBackgroundResid =
                         landscapeMode ? R.drawable.incall_frame_ended_tall_land
                         : R.drawable.incall_frame_ended_tall_port;
@@ -383,8 +407,6 @@ public class CallCard extends FrameLayout
 
             case DIALING:
             case ALERTING:
-                showCallConnecting();
-
                 if (bluetoothActive) {
                     callCardBackgroundResid =
                             landscapeMode ? R.drawable.incall_frame_bluetooth_tall_land
@@ -402,8 +424,6 @@ public class CallCard extends FrameLayout
 
             case INCOMING:
             case WAITING:
-                showCallIncoming();
-
                 if (bluetoothActive) {
                     callCardBackgroundResid =
                             landscapeMode ? R.drawable.incall_frame_bluetooth_tall_land
@@ -439,6 +459,10 @@ public class CallCard extends FrameLayout
                 break;
         }
 
+        // Set the background frame color based on the state of the call.
+        setMainCallCardBackgroundResource(callCardBackgroundResid);
+        // (Text colors are set in updateCardTitleWidgets().)
+
         updateCardTitleWidgets(phone, call);
 
         if (PhoneUtils.isConferenceCall(call)) {
@@ -447,7 +471,12 @@ public class CallCard extends FrameLayout
         } else {
             // Update onscreen info for a regular call (which presumably
             // has only one connection.)
-            Connection conn = call.getEarliestConnection();
+            Connection conn = null;
+            if (phone.getPhoneName().equals("CDMA")) {
+                conn = call.getLatestConnection();
+            } else { // GSM.
+                conn = call.getEarliestConnection();
+            }
 
             if (conn == null) {
                 if (DBG) log("displayMainCallStatus: connection is null, using default values.");
@@ -484,10 +513,20 @@ public class CallCard extends FrameLayout
                     if (DBG) log("- displayMainCallStatus: using data we already have...");
                     if (o instanceof CallerInfo) {
                         CallerInfo ci = (CallerInfo) o;
+                        // Update CNAP information if Phone state change occurred
+                        ci.cnapName = conn.getCnapName();
+                        ci.numberPresentation = conn.getNumberPresentation();
+                        ci.namePresentation = conn.getCnapNamePresentation();
+                        if (DBG) log("- displayMainCallStatus: CNAP data from Connection: "
+                                + "CNAP name=" + ci.cnapName
+                                + ", Number/Name Presentation=" + ci.numberPresentation);
                         if (DBG) log("   ==> Got CallerInfo; updating display: ci = " + ci);
                         updateDisplayForPerson(ci, presentation, false, call);
                     } else if (o instanceof PhoneUtils.CallerInfoToken){
                         CallerInfo ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
+                        if (DBG) log("- displayMainCallStatus: CNAP data from Connection: "
+                                + "CNAP name=" + ci.cnapName
+                                + ", Number/Name Presentation=" + ci.numberPresentation);
                         if (DBG) log("   ==> Got CallerInfoToken; updating display: ci = " + ci);
                         updateDisplayForPerson(ci, presentation, true, call);
                     } else {
@@ -506,10 +545,54 @@ public class CallCard extends FrameLayout
         // indication of the current state, rather than displaying the
         // regular photo as set above.
         updatePhotoForCallState(call);
+    }
+
+    /**
+     * Version of displayMainCallStatus() that sets the main call area
+     * into the "generic" state.
+     * @see displayMainCallStatus
+     */
+    private void displayMainCallGeneric(Phone phone, Call call) {
+        if (DBG) log("displayMainCallGeneric(phone " + phone
+                     + ", call " + call + ")...");
+
+        mMainCallCard.setVisibility(View.VISIBLE);
+
+        // Background frame resources are different between portrait/landscape.
+        // TODO: Don't do this manually.  Instead let the resource system do
+        // it: just move the *_land assets over to the res/drawable-land
+        // directory (but with the same filename as the corresponding
+        // portrait asset.)
+        boolean landscapeMode = InCallScreen.ConfigurationHelper.isLandscape();
+
+        // Background images are also different if Bluetooth is active.
+        final boolean bluetoothActive = mApplication.showBluetoothIndication();
+
+        int callCardBackgroundResid = 0;
+        if (bluetoothActive) {
+            callCardBackgroundResid =
+                    landscapeMode ? R.drawable.incall_frame_bluetooth_tall_land
+                    : R.drawable.incall_frame_bluetooth_tall_port;
+        } else {
+            callCardBackgroundResid =
+                    landscapeMode ? R.drawable.incall_frame_connected_tall_land
+                    : R.drawable.incall_frame_connected_tall_port;
+        }
 
         // Set the background frame color based on the state of the call.
         setMainCallCardBackgroundResource(callCardBackgroundResid);
         // (Text colors are set in updateCardTitleWidgets().)
+
+        // Update timer field:
+        // TODO(CDMA): Need to confirm that we can trust the time info
+        // from the passed-in Call object, even though the call is "generic".
+        if (DBG) log("displayMainCallStatus: start periodicUpdateTimer");
+        mCallTime.setActiveCallMode(call);
+        mCallTime.reset();
+        mCallTime.periodicUpdateTimer();
+
+        updateCardTitleWidgets(phone, call);
+        updateDisplayForGenericCall();
     }
 
     /**
@@ -525,7 +608,20 @@ public class CallCard extends FrameLayout
             // If the object is a textview instead, we update it as we need to.
             if (DBG) log("callerinfo query complete, updating ui from displayMainCallStatus()");
             Call call = (Call) cookie;
-            updateDisplayForPerson(ci, Connection.PRESENTATION_ALLOWED, false, call);
+            Connection conn = call.getEarliestConnection();
+            PhoneUtils.CallerInfoToken cit =
+                   PhoneUtils.startGetCallerInfo(getContext(), conn, this, null);
+            int presentation = conn.getNumberPresentation();
+            if (DBG) log("- onQueryComplete: presentation=" + presentation
+                    + ", contactExists=" + ci.contactExists);
+            // Depending on whether there was a contact match or not, we want to pass in different
+            // CallerInfo (for CNAP). Therefore if ci.contactExists then use the ci passed in.
+            // Otherwise, regenerate the CIT from the Connection and use the CallerInfo from there.
+            if (ci.contactExists) {
+                updateDisplayForPerson(ci, Connection.PRESENTATION_ALLOWED, false, call);
+            } else {
+                updateDisplayForPerson(cit.currentInfo, presentation, false, call);
+            }
             updatePhotoForCallState(call);
 
         } else if (cookie instanceof TextView){
@@ -564,21 +660,38 @@ public class CallCard extends FrameLayout
 
         // We display *either* the "upper title" or the "lower title", but
         // never both.
-        if (state == Call.State.ACTIVE) {
-            // Use the "lower title" (in green).
-            mLowerTitleViewGroup.setVisibility(View.VISIBLE);
 
-            final boolean bluetoothActive = PhoneApp.getInstance().showBluetoothIndication();
+        if (state == Call.State.ACTIVE) {
+            final boolean bluetoothActive = mApplication.showBluetoothIndication();
             int ongoingCallIcon = bluetoothActive ? R.drawable.ic_incall_ongoing_bluetooth
                     : R.drawable.ic_incall_ongoing;
-            mLowerTitleIcon.setImageResource(ongoingCallIcon);
-
-            mLowerTitle.setText(cardTitle);
-
             int textColor = bluetoothActive ? mTextColorConnectedBluetooth : mTextColorConnected;
-            mLowerTitle.setTextColor(textColor);
-            mElapsedTime.setTextColor(textColor);
-            setUpperTitle("");
+
+            if (mApplication.phone.getPhoneName().equals("CDMA")) {
+               // Check if the "Dialing" 3Way call needs to be displayed
+               // as the Foreground Call state still remains ACTIVE
+               if (mApplication.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
+                    // Use the "upper title":
+                    mUpperTitle.setText(cardTitle);
+                    mLowerTitleViewGroup.setVisibility(View.INVISIBLE);
+               } else {
+                    // Use the "lower title" (in green).
+                    mLowerTitleViewGroup.setVisibility(View.VISIBLE);
+                    mLowerTitle.setText(cardTitle);
+                    mLowerTitleIcon.setImageResource(ongoingCallIcon);
+                    mLowerTitle.setTextColor(textColor);
+                    mElapsedTime.setTextColor(textColor);
+                    mUpperTitle.setText("");
+               }
+            } else { // GSM
+                // Use the "lower title" (in green).
+                mLowerTitleViewGroup.setVisibility(View.VISIBLE);
+                mLowerTitleIcon.setImageResource(ongoingCallIcon);
+                mLowerTitle.setText(cardTitle);
+                mLowerTitle.setTextColor(textColor);
+                mElapsedTime.setTextColor(textColor);
+                setUpperTitle("");
+            }
         } else if (state == Call.State.DISCONNECTED) {
             // Use the "lower title" (in red).
             // TODO: We may not *always* want to use the lower title for
@@ -647,7 +760,15 @@ public class CallCard extends FrameLayout
             case ACTIVE:
                 // Title is "Call in progress".  (Note this appears in the
                 // "lower title" area of the CallCard.)
-                retVal = context.getString(R.string.card_title_in_progress);
+                if (mApplication.phone.getPhoneName().equals("CDMA")) {
+                    if (mApplication.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
+                        retVal = context.getString(R.string.card_title_dialing);
+                    } else {
+                        retVal = context.getString(R.string.card_title_in_progress);
+                    }
+                } else { //GSM
+                    retVal = context.getString(R.string.card_title_in_progress);
+                }
                 break;
 
             case HOLDING:
@@ -689,12 +810,12 @@ public class CallCard extends FrameLayout
             return;
         }
 
+        String name = null;
         Call.State state = call.getState();
         switch (state) {
             case HOLDING:
                 // Ok, there actually is a background call on hold.
                 // Display the "on hold" box.
-                String name;
 
                 // First, see if we need to query.
                 if (PhoneUtils.isConferenceCall(call)) {
@@ -722,6 +843,40 @@ public class CallCard extends FrameLayout
 
                 break;
 
+            case ACTIVE:
+                // CDMA: This is because in CDMA when the user originates the second call,
+                // although the Foreground call state is still ACTIVE in reality the network
+                // put the first call on hold.
+                if (mApplication.phone.getPhoneName().equals("CDMA")) {
+                    List<Connection> connections = call.getConnections();
+                    if (connections.size() > 2) {
+                        // This means that current Mobile Originated call is the not the first 3-Way
+                        // call the user is making, which in turn tells the PhoneApp that we no
+                        // longer know which previous caller/party had dropped out before the user
+                        // made this call.
+                        name = getContext().getString(R.string.card_title_in_call);
+                    } else {
+                        // This means that the current Mobile Originated call IS the first 3-Way
+                        // and hence we display the first callers/party's info here.
+                        Connection conn = call.getEarliestConnection();
+                        PhoneUtils.CallerInfoToken info = PhoneUtils.startGetCallerInfo(
+                                getContext(), conn, this, mOtherCallOnHoldName);
+
+                        name = PhoneUtils.getCompactNameFromCallerInfo(info.currentInfo,
+                                getContext());
+                    }
+
+                    mOtherCallOnHoldName.setText(name);
+
+                    // The call here is either in Callwaiting or 3way, use the orange "hold" frame
+                    // and orange text color:
+                    setOnHoldInfoAreaBackgroundResource(R.drawable.incall_frame_hold_short);
+                    mOtherCallOnHoldName.setTextColor(mTextColorOnHold);
+                    mOtherCallOnHoldStatus.setTextColor(mTextColorOnHold);
+                    mOtherCallOnHoldInfoArea.setVisibility(View.VISIBLE);
+                }
+                break;
+
             default:
                 // There's actually no call on hold.  (Presumably this call's
                 // state is IDLE, since any other state is meaningless for the
@@ -755,7 +910,9 @@ public class CallCard extends FrameLayout
                 String name;
 
                 // First, see if we need to query.
-                if (PhoneUtils.isConferenceCall(call)) {
+                if (call.isGeneric()) {
+                    name = getContext().getString(R.string.card_title_in_call);
+                } else if (PhoneUtils.isConferenceCall(call)) {
                     name = getContext().getString(R.string.confCall);
                 } else {
                     // perform query and update the name temporarily
@@ -771,7 +928,7 @@ public class CallCard extends FrameLayout
                 // This is an "ongoing" call: we normally use the green
                 // background frame and text color, but we use blue
                 // instead if bluetooth is in use.
-                boolean bluetoothActive = PhoneApp.getInstance().showBluetoothIndication();
+                boolean bluetoothActive = mApplication.showBluetoothIndication();
 
                 int ongoingCallBackground =
                         bluetoothActive ? R.drawable.incall_frame_bluetooth_short
@@ -855,36 +1012,15 @@ public class CallCard extends FrameLayout
         return getContext().getString(resID);
     }
 
-    private void showCallConnecting() {
-        if (DBG) log("showCallConnecting()...");
-        // TODO: remove if truly unused
-    }
-
-    private void showCallIncoming() {
-        if (DBG) log("showCallIncoming()...");
-        // TODO: remove if truly unused
-    }
-
-    private void showCallConnected() {
-        if (DBG) log("showCallConnected()...");
-        // TODO: remove if truly unused
-    }
-
-    private void showCallEnded() {
-        if (DBG) log("showCallEnded()...");
-        // TODO: remove if truly unused
-    }
-    private void showCallOnhold() {
-        if (DBG) log("showCallOnhold()...");
-        // TODO: remove if truly unused
-    }
-
     /**
      * Updates the name / photo / number / label fields on the CallCard
      * based on the specified CallerInfo.
      *
      * If the current call is a conference call, use
      * updateDisplayForConference() instead.
+     *
+     * If the phone is in the "generic call" state, use
+     * updateDisplayForGenericCall() instead.
      */
     private void updateDisplayForPerson(CallerInfo info,
                                         int presentation,
@@ -918,19 +1054,40 @@ public class CallCard extends FrameLayout
             if (TextUtils.isEmpty(info.name)) {
                 if (TextUtils.isEmpty(info.phoneNumber)) {
                     name =  getPresentationString(presentation);
+                } else if (presentation != Connection.PRESENTATION_ALLOWED) {
+                    // This case should never happen since the network should never send a phone #
+                    // AND a restricted presentation. However we leave it here in case of weird
+                    // network behavior
+                    name = getPresentationString(presentation);
+                } else if (!TextUtils.isEmpty(info.cnapName)) {
+                    name = info.cnapName;
+                    info.name = info.cnapName;
+                    displayNumber = info.phoneNumber;
                 } else {
                     name = info.phoneNumber;
                 }
             } else {
-                name = info.name;
-                displayNumber = info.phoneNumber;
-                label = info.phoneLabel;
+                if (presentation != Connection.PRESENTATION_ALLOWED) {
+                    // This case should never happen since the network should never send a name
+                    // AND a restricted presentation. However we leave it here in case of weird
+                    // network behavior
+                    name = getPresentationString(presentation);
+                } else {
+                    name = info.name;
+                    displayNumber = info.phoneNumber;
+                    label = info.phoneLabel;
+                }
             }
             personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.person_id);
         } else {
             name =  getPresentationString(presentation);
         }
-        mName.setText(name);
+
+        if (call.isGeneric()) {
+            mName.setText(R.string.card_title_in_call);
+        } else {
+            mName.setText(name);
+        }
         mName.setVisibility(View.VISIBLE);
 
         // Update mPhoto
@@ -953,7 +1110,7 @@ public class CallCard extends FrameLayout
             ContactsAsyncHelper.updateImageViewWithContactPhotoAsync(info, 0, this, call,
                     getContext(), mPhoto, personUri, -1);
         }
-        if (displayNumber != null) {
+        if (displayNumber != null && !call.isGeneric()) {
             mPhoneNumber.setText(displayNumber);
             mPhoneNumber.setVisibility(View.VISIBLE);
         } else {
@@ -989,12 +1146,20 @@ public class CallCard extends FrameLayout
     private void updateDisplayForConference() {
         if (DBG) log("updateDisplayForConference()...");
 
-        // Display the "conference call" image in the photo slot,
-        // with no other information.
-
-        showImage(mPhoto, R.drawable.picture_conference);
+        if (mApplication.phone.getPhoneName().equals("CDMA")) {
+            // This state corresponds to both 3-Way merged call and
+            // Call Waiting accepted call.
+            // Display only the "dialing" icon and no caller information cause in CDMA
+            // as in this state the user does not really know which caller party he is talking to.
+            showImage(mPhoto, R.drawable.picture_dialing);
+            mName.setText(R.string.card_title_in_call);
+        } else {
+            // Display the "conference call" image in the photo slot,
+            // with no other information.
+            showImage(mPhoto, R.drawable.picture_conference);
+            mName.setText(R.string.card_title_conf_call);
+        }
 
-        mName.setText(R.string.card_title_conf_call);
         mName.setVisibility(View.VISIBLE);
 
         // TODO: For a conference call, the "phone number" slot is specced
@@ -1016,6 +1181,25 @@ public class CallCard extends FrameLayout
     }
 
     /**
+     * Updates the name / photo / number / label fields
+     * for the special "generic call" state.
+     * @see updateDisplayForPerson
+     * @see updateDisplayForConference
+     */
+    private void updateDisplayForGenericCall() {
+        if (DBG) log("updateDisplayForGenericCall()...");
+
+        // Display a generic "in-call" image in the photo slot, with no
+        // other information.
+
+        showImage(mPhoto, R.drawable.picture_dialing);
+
+        mName.setVisibility(View.GONE);
+        mPhoneNumber.setVisibility(View.GONE);
+        mLabel.setVisibility(View.GONE);
+    }
+
+    /**
      * Updates the CallCard "photo" IFF the specified Call is in a state
      * that needs a special photo (like "busy" or "dialing".)
      *
@@ -1077,7 +1261,13 @@ public class CallCard extends FrameLayout
                 // look for the photoResource if it is available.
                 CallerInfo ci = null;
                 {
-                    Connection conn = call.getEarliestConnection();
+                    Connection conn = null;
+                    if (mApplication.phone.getPhoneName().equals("CDMA")) {
+                        conn = call.getLatestConnection();
+                    } else { // GSM.
+                        conn = call.getEarliestConnection();
+                    }
+
                     if (conn != null) {
                         Object o = conn.getUserData();
                         if (o instanceof CallerInfo) {
@@ -1257,7 +1447,7 @@ public class CallCard extends FrameLayout
 
         int bluetoothIconId = 0;
         if (((state == Call.State.INCOMING) || (state == Call.State.WAITING))
-                && PhoneApp.getInstance().showBluetoothIndication()) {
+                && mApplication.showBluetoothIndication()) {
             // Display the special bluetooth icon also, if this is an incoming
             // call and the audio will be routed to bluetooth.
             bluetoothIconId = R.drawable.ic_incoming_call_bluetooth;
old mode 100644 (file)
new mode 100755 (executable)
index b5754ed..8b69671
@@ -57,7 +57,7 @@ public class CallFeaturesSetting extends PreferenceActivity
         "com.android.phone.CallFeaturesSetting.ADD_VOICEMAIL";
 
     // debug data
-    private static final String LOG_TAG = "call features settings";
+    private static final String LOG_TAG = "CallFeaturesSetting";
     private static final boolean DBG = false;
 
     // string contants
@@ -89,6 +89,7 @@ public class CallFeaturesSetting extends PreferenceActivity
 
     private static final String BUTTON_TTY_KEY = "button_tty_mode_key";
     private static final String BUTTON_VP_KEY = "button_voice_privacy_key";
+    private static final String BUTTON_DS_KEY = "dtmf_settings";
 
     private Intent mContactListIntent;
     private Intent mFDNSettingIntent;
@@ -104,18 +105,29 @@ public class CallFeaturesSetting extends PreferenceActivity
     private static final int EVENT_INITAL_QUERY_CANCELED = 600;
     /** Event for TTY mode change */
     private static final int EVENT_TTY_EXECUTED          = 700;
+    private static final int EVENT_TTY_MODE_SET          = 800;
     private static final int EVENT_ENHANCED_VP_EXECUTED  = 1000;
-    
+
     // preferred TTY mode
     // 0 = disabled
-    // 1 = enabled
-    static final int preferredTTYMode = 0;
+    // 1 = full mode
+    // 2 = HCO mode
+    // 3 = VCO mode
+    static final int preferredTtyMode = 0;
 
     // preferred VoicePrivacy mode
     // 0 = disabled
     // 1 = enabled
     static final int preferredVPMode = 1;
 
+    // Dtmf tone types
+    static final int DTMF_TONE_TYPE_NORMAL = 0;
+    static final int DTMF_TONE_TYPE_LONG   = 1;
+
+    // preferred DTMF Tones mode
+    static final int preferredDtmfMode = DTMF_TONE_TYPE_NORMAL;
+
+
     /** Handle to voicemail pref */
     private static final int VOICEMAIL_PREF_ID = CommandsInterface.CF_REASON_NOT_REACHABLE + 1;
 
@@ -183,7 +195,8 @@ public class CallFeaturesSetting extends PreferenceActivity
     private PreferenceScreen mButtonGSMMoreExpand;
     private PreferenceScreen mButtonCDMAMoreExpand;
     private CheckBoxPreference mButtonVoicePrivacy;
-    private CheckBoxPreference mButtonTTY;
+    private ListPreference mButtonTTY;
+    private ListPreference mButtonDS;
 
     // cf number strings
     private String mDialingNumCFU;
@@ -240,7 +253,16 @@ public class CallFeaturesSetting extends PreferenceActivity
         } else if (preference == mButtonVoicePrivacy) {
             handleVoicePrivacyClickRequest(mButtonVoicePrivacy.isChecked());
         } else if (preference == mButtonTTY) {
-            handleTTYClickRequest(mButtonTTY.isChecked());
+            //displays the value taken from the Settings.System
+            int settingsTtyMode = android.provider.Settings.Secure.getInt(
+                    mPhone.getContext().getContentResolver(),
+                    android.provider.Settings.Secure.PREFERRED_TTY_MODE ,
+                    preferredTtyMode);
+            mButtonTTY.setValue(Integer.toString(settingsTtyMode));
+            return true;
+        } else if (preference == mButtonDS) {
+            // Let the normal listpreference UI take care of this
+            return false;
         }
 
         if (nextState != AppState.INPUT_READY) {
@@ -264,8 +286,14 @@ public class CallFeaturesSetting extends PreferenceActivity
             // send the command and update state.
             handleCLIRClickRequest(mButtonCLIR.findIndexOfValue((String) objValue));
             setAppState(AppState.BUSY_NETWORK_CONNECT);
+        } else if (preference == mButtonTTY) {
+            // send the command and update state.
+            handleTTYClickRequest(preference, objValue);
+        } else if (preference == mButtonDS) {
+            int index = mButtonDS.findIndexOfValue((String) objValue);
+            Settings.System.putInt(mPhone.getContext().getContentResolver(),
+                    Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, index);
         }
-
         // always let the preference setting proceed.
         return true;
     }
@@ -783,11 +811,11 @@ public class CallFeaturesSetting extends PreferenceActivity
      * Helper function to set both the value and the summary of the CLIR preference.
      */
     private void setButtonCLIRValue (int value) {
-        
+
         if (mButtonCLIR == null) {
             return;
         }
-        
+
         // first, set the value.
         mButtonCLIR.setValueIndex(value);
 
@@ -810,11 +838,11 @@ public class CallFeaturesSetting extends PreferenceActivity
     // called by syncCFUIState to do repetitive changes to UI button state.
     private void adjustCFbuttonState(EditPhoneNumberPreference epn,
             boolean isActive, int template, String number) {
-        
+
         if (epn == null) {
             return;
         }
-        
+
         CharSequence summaryOn = "";
 
         if (isActive) {
@@ -861,7 +889,7 @@ public class CallFeaturesSetting extends PreferenceActivity
         if (mSubMenuVoicemailSettings == null) {
             return;
         }
-        
+
         mOldVmNumber = mPhone.getVoiceMailNumber();
         if (mOldVmNumber == null) {
             mOldVmNumber = "";
@@ -1000,7 +1028,7 @@ public class CallFeaturesSetting extends PreferenceActivity
                     if (status != MSG_OK) {
                         setAppState(AppState.NETWORK_ERROR, status);
                     } else {
-                        mPhone.getCallWaiting(Message.obtain(mGetMoreOptionsComplete, 
+                        mPhone.getCallWaiting(Message.obtain(mGetMoreOptionsComplete,
                                 EVENT_CW_EXECUTED));
                     }
                     break;
@@ -1327,7 +1355,7 @@ public class CallFeaturesSetting extends PreferenceActivity
     protected void onResume() {
         super.onResume();
         mPhone = PhoneFactory.getDefaultPhone();
-        
+
         // upon resumption from the sub-activity, make sure we re-enable the
         // preferences.
         getPreferenceScreen().setEnabled(true);
@@ -1337,20 +1365,16 @@ public class CallFeaturesSetting extends PreferenceActivity
             // app to change this setting's backend, and re-launch this settings app
             // and the UI state would be inconsistent with actual state
             handleSetVPMessage();
-            mPhone.queryTTYModeEnabled(Message.obtain(mQueryTTYComplete, EVENT_TTY_EXECUTED));
-            mButtonCFExpand.setEnabled(false);
-            mButtonCLIR.setEnabled(false);
-            mButtonCW.setChecked(false);
-            mButtonCW.setEnabled(false);
+            mPhone.queryTTYMode(Message.obtain(mQueryTTYComplete, EVENT_TTY_EXECUTED));
+            // TODO(Moto): Re-launch DTMF settings if necessary onResume
         } else {
-            mButtonTTY.setChecked(false);
             mButtonTTY.setEnabled(false);
             mButtonVoicePrivacy.setChecked(false);
             mButtonVoicePrivacy.setEnabled(false);
         }
 
     }
-    
+
     /*
      * Activity class methods
      */
@@ -1360,125 +1384,156 @@ public class CallFeaturesSetting extends PreferenceActivity
         super.onCreate(icicle);
         mPhone = PhoneFactory.getDefaultPhone();
 
-        addPreferencesFromResource(R.xml.call_feature_setting);
-
+        // If the phone loads in CDMA mode , Call Settings XML is CDMA specific
+        // TODO: For World Phone, that has options to switch n/w mode dynamically, this
+        // design will not work and this piece of code may be moved to onResume()
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            addPreferencesFromResource(R.xml.cdma_call_feature_setting);
+        } else {
+            addPreferencesFromResource(R.xml.call_feature_setting);
+        }
         // get buttons
         PreferenceScreen prefSet = getPreferenceScreen();
-        mButtonCLIR  = (ListPreference) prefSet.findPreference(BUTTON_CLIR_KEY);
-        mButtonCW    = (CheckBoxPreference) prefSet.findPreference(BUTTON_CW_KEY);
-        mButtonCFU   = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFU_KEY);
-        mButtonCFB   = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFB_KEY);
-        mButtonCFNRy = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFNRY_KEY);
-        mButtonCFNRc = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFNRC_KEY);
         mSubMenuVoicemailSettings = (EditPhoneNumberPreference)
                 prefSet.findPreference(BUTTON_VOICEMAIL_KEY);
         mSubMenuFDNSettings = (PreferenceScreen) prefSet.findPreference(BUTTON_FDN_KEY);
+        mButtonVoicePrivacy = (CheckBoxPreference) findPreference(BUTTON_VP_KEY);
 
-        // get a reference to the Preference Screens for Call Forwarding and "More" settings.
-        mButtonCFExpand = (PreferenceScreen) prefSet.findPreference(BUTTON_CF_EXPAND_KEY);
-        mButtonGSMMoreExpand = (PreferenceScreen) prefSet.findPreference(
-                BUTTON_GSM_MORE_EXPAND_KEY);
-        mButtonCDMAMoreExpand = (PreferenceScreen) prefSet.findPreference(
-                BUTTON_CDMA_MORE_EXPAND_KEY);
+        mButtonTTY = (ListPreference) prefSet.findPreference(BUTTON_TTY_KEY);
+        mButtonTTY.setOnPreferenceChangeListener(this);
 
-        mButtonTTY = (CheckBoxPreference) findPreference(BUTTON_TTY_KEY);
-        mButtonVoicePrivacy = (CheckBoxPreference) findPreference(BUTTON_VP_KEY);
+        // Get the ttyMode from Settings.System and displays it
+        int settingsTtyMode = android.provider.Settings.Secure.getInt(
+                mPhone.getContext().getContentResolver(),
+                android.provider.Settings.Secure.PREFERRED_TTY_MODE,
+                preferredTtyMode);
+        mButtonTTY.setValue(Integer.toString(settingsTtyMode));
+        UpdatePreferredTtyModeSummary(settingsTtyMode);
+
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            mButtonDS = (ListPreference) findPreference(BUTTON_DS_KEY);
+            int index = Settings.System.getInt(getContentResolver(),
+                    Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, preferredDtmfMode);
+            mButtonDS.setValueIndex(index);
+            mButtonDS.setOnPreferenceChangeListener(this);
+        }
         if (mPhone.getPhoneName().equals("GSM")) {
+            mButtonCLIR  = (ListPreference) prefSet.findPreference(BUTTON_CLIR_KEY);
+            mButtonCW    = (CheckBoxPreference) prefSet.findPreference(BUTTON_CW_KEY);
+            mButtonCFU   = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFU_KEY);
+            mButtonCFB   = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFB_KEY);
+            mButtonCFNRy = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFNRY_KEY);
+            mButtonCFNRc = (EditPhoneNumberPreference) prefSet.findPreference(BUTTON_CFNRC_KEY);
+
+            // get a reference to the Preference Screens for Call Forwarding and "More" settings.
+            mButtonCFExpand = (PreferenceScreen) prefSet.findPreference(BUTTON_CF_EXPAND_KEY);
+            mButtonGSMMoreExpand = (PreferenceScreen) prefSet.findPreference(
+                    BUTTON_GSM_MORE_EXPAND_KEY);
+            mButtonCDMAMoreExpand = (PreferenceScreen) prefSet.findPreference(
+                    BUTTON_CDMA_MORE_EXPAND_KEY);
+
+            // The intent code that resided here in the past has been moved into the
+            // more conventional location in network_setting.xml
+
             mButtonVoicePrivacy.setEnabled(false);
+
+            // Set links to the current activity and any UI settings that
+            // effect the dialog for each preference.  Also set the
+            // dependencies between the child (CFB, CFNRy, CFNRc)
+            // preferences and the CFU preference.
+            if (mButtonCFU != null){
+                mButtonCFU.setParentActivity(this, CommandsInterface.CF_REASON_UNCONDITIONAL, this);
+                mButtonCFU.setDialogOnClosedListener(this);
+                mButtonCFU.setDialogTitle(R.string.labelCF);
+                mButtonCFU.setDialogMessage(R.string.messageCFU);
+            }
+
+            if (mButtonCFB != null) {
+                mButtonCFB.setParentActivity(this, CommandsInterface.CF_REASON_BUSY, this);
+                mButtonCFB.setDialogOnClosedListener(this);
+                mButtonCFB.setDependency(BUTTON_CFU_KEY);
+                mButtonCFB.setDialogTitle(R.string.labelCF);
+                mButtonCFB.setDialogMessage(R.string.messageCFB);
+            }
+
+            if (mButtonCFNRy != null) {
+                mButtonCFNRy.setParentActivity(this, CommandsInterface.CF_REASON_NO_REPLY, this);
+                mButtonCFNRy.setDialogOnClosedListener(this);
+                mButtonCFNRy.setDependency(BUTTON_CFU_KEY);
+                mButtonCFNRy.setDialogTitle(R.string.labelCF);
+                mButtonCFNRy.setDialogMessage(R.string.messageCFNRy);
+            }
+
+            if (mButtonCFNRc != null) {
+                mButtonCFNRc.setParentActivity(this, CommandsInterface.CF_REASON_NOT_REACHABLE, this);
+                mButtonCFNRc.setDialogOnClosedListener(this);
+                mButtonCFNRc.setDependency(BUTTON_CFU_KEY);
+                mButtonCFNRc.setDialogTitle(R.string.labelCF);
+                mButtonCFNRc.setDialogMessage(R.string.messageCFNRc);
+            }
+
+            // set the listener for the CLIR list preference so we can issue CLIR commands.
+            if (mButtonCLIR != null ) {
+                mButtonCLIR.setOnPreferenceChangeListener(this);
+            }
+            mFDNSettingIntent = new Intent(Intent.ACTION_MAIN);
+            mFDNSettingIntent.setClassName(this, FdnSetting.class.getName());
+            mSubMenuFDNSettings.setIntent (mFDNSettingIntent);
         }
 
-        // Set links to the current activity and any UI settings that
-        // effect the dialog for each preference.  Also set the
-        // dependencies between the child (CFB, CFNRy, CFNRc)
-        // preferences and the CFU preference.
-        if (mButtonCFU != null){
-            mButtonCFU.setParentActivity(this, CommandsInterface.CF_REASON_UNCONDITIONAL, this);
-            mButtonCFU.setDialogOnClosedListener(this);
-            mButtonCFU.setDialogTitle(R.string.labelCF);
-            mButtonCFU.setDialogMessage(R.string.messageCFU);
-        }
-        
-        if (mButtonCFB != null) {
-            mButtonCFB.setParentActivity(this, CommandsInterface.CF_REASON_BUSY, this);
-            mButtonCFB.setDialogOnClosedListener(this);
-            mButtonCFB.setDependency(BUTTON_CFU_KEY);
-            mButtonCFB.setDialogTitle(R.string.labelCF);
-            mButtonCFB.setDialogMessage(R.string.messageCFB);
-        }
-        
-        if (mButtonCFNRy != null) {
-            mButtonCFNRy.setParentActivity(this, CommandsInterface.CF_REASON_NO_REPLY, this);
-            mButtonCFNRy.setDialogOnClosedListener(this);
-            mButtonCFNRy.setDependency(BUTTON_CFU_KEY);
-            mButtonCFNRy.setDialogTitle(R.string.labelCF);
-            mButtonCFNRy.setDialogMessage(R.string.messageCFNRy);
-        }
-        
-        if (mButtonCFNRc != null) {
-            mButtonCFNRc.setParentActivity(this, CommandsInterface.CF_REASON_NOT_REACHABLE, this);
-            mButtonCFNRc.setDialogOnClosedListener(this);
-            mButtonCFNRc.setDependency(BUTTON_CFU_KEY);
-            mButtonCFNRc.setDialogTitle(R.string.labelCF);
-            mButtonCFNRc.setDialogMessage(R.string.messageCFNRc);
-        }
-        
         if (mSubMenuVoicemailSettings != null) {
             mSubMenuVoicemailSettings.setParentActivity(this, VOICEMAIL_PREF_ID, this);
             mSubMenuVoicemailSettings.setDialogOnClosedListener(this);
             mSubMenuVoicemailSettings.setDialogTitle(R.string.voicemail_settings_number_label);
         }
-        
-        // set the listener for the CLIR list preference so we can issue CLIR commands.
-        if (mButtonCLIR != null ) {
-            mButtonCLIR.setOnPreferenceChangeListener(this);
-        }
 
         // create intent to bring up contact list
         mContactListIntent = new Intent(Intent.ACTION_GET_CONTENT);
         mContactListIntent.setType(android.provider.Contacts.Phones.CONTENT_ITEM_TYPE);
 
-        mFDNSettingIntent = new Intent(Intent.ACTION_MAIN);
-        mFDNSettingIntent.setClassName(this, FdnSetting.class.getName());
-        mSubMenuFDNSettings.setIntent (mFDNSettingIntent);
+        if (mSubMenuFDNSettings != null) {
+            mFDNSettingIntent = new Intent(Intent.ACTION_MAIN);
+            mFDNSettingIntent.setClassName(this, FdnSetting.class.getName());
+            mSubMenuFDNSettings.setIntent (mFDNSettingIntent);
+        }
 
         mAppState = AppState.INPUT_READY;
 
         if (icicle != null) {
-            // retrieve number state
-            mDialingNumCFU = icicle.getString(SUMMARY_CFU_KEY);
-            mDialingNumCFB = icicle.getString(SUMMARY_CFB_KEY);
-            mDialingNumCFNRy = icicle.getString(SUMMARY_CFNRY_KEY);
-            mDialingNumCFNRc = icicle.getString(SUMMARY_CFNRC_KEY);
-
-            // reset CF buttons
-            adjustCFbuttonState(mButtonCFU, icicle.getBoolean(BUTTON_CFU_KEY),
-                    R.string.sum_cfu_enabled, mDialingNumCFU);
-            adjustCFbuttonState(mButtonCFB, icicle.getBoolean(BUTTON_CFB_KEY),
-                    R.string.sum_cfb_enabled, mDialingNumCFB);
-            adjustCFbuttonState(mButtonCFNRy, icicle.getBoolean(BUTTON_CFNRY_KEY),
-                    R.string.sum_cfnry_enabled, mDialingNumCFNRy);
-            adjustCFbuttonState(mButtonCFNRc, icicle.getBoolean(BUTTON_CFNRC_KEY),
-                    R.string.sum_cfnrc_enabled, mDialingNumCFNRc);
-
-            // reset other button state
-            setButtonCLIRValue(icicle.getInt(BUTTON_CLIR_KEY));
-            if (mButtonCW != null) {
-                mButtonCW.setChecked(icicle.getBoolean(BUTTON_CW_KEY));
-        }
-        if (mButtonVoicePrivacy != null) {
+            if (mButtonVoicePrivacy != null) {
                 mButtonVoicePrivacy.setChecked(icicle.getBoolean(BUTTON_VP_KEY));
-                if (mPhone.getPhoneName().equals("GSM")) {
+            }
+            if (mPhone.getPhoneName().equals("GSM")) {
+                // retrieve number state
+                mDialingNumCFU = icicle.getString(SUMMARY_CFU_KEY);
+                mDialingNumCFB = icicle.getString(SUMMARY_CFB_KEY);
+                mDialingNumCFNRy = icicle.getString(SUMMARY_CFNRY_KEY);
+                mDialingNumCFNRc = icicle.getString(SUMMARY_CFNRC_KEY);
+
+                // reset CF buttons
+                adjustCFbuttonState(mButtonCFU, icicle.getBoolean(BUTTON_CFU_KEY),
+                        R.string.sum_cfu_enabled, mDialingNumCFU);
+                adjustCFbuttonState(mButtonCFB, icicle.getBoolean(BUTTON_CFB_KEY),
+                        R.string.sum_cfb_enabled, mDialingNumCFB);
+                adjustCFbuttonState(mButtonCFNRy, icicle.getBoolean(BUTTON_CFNRY_KEY),
+                        R.string.sum_cfnry_enabled, mDialingNumCFNRy);
+                adjustCFbuttonState(mButtonCFNRc, icicle.getBoolean(BUTTON_CFNRC_KEY),
+                        R.string.sum_cfnrc_enabled, mDialingNumCFNRc);
+
+                // reset other button state
+                setButtonCLIRValue(icicle.getInt(BUTTON_CLIR_KEY));
+                if (mButtonCW != null) {
+                    mButtonCW.setChecked(icicle.getBoolean(BUTTON_CW_KEY));
+                }
+                if (mButtonVoicePrivacy != null) {
                     mButtonVoicePrivacy.setEnabled(false);
                 }
-            }
-            if (mButtonTTY != null) {
-                mButtonTTY.setChecked(icicle.getBoolean(BUTTON_TTY_KEY));
+                mCFDataStale = icicle.getBoolean(BUTTON_CF_EXPAND_KEY);
+                mMoreDataStale = icicle.getBoolean(BUTTON_GSM_MORE_EXPAND_KEY);
             }
 
             // set app state
             mAppState = (AppState) icicle.getSerializable(APP_STATE_KEY);
-            mCFDataStale = icicle.getBoolean(BUTTON_CF_EXPAND_KEY);
-            mMoreDataStale = icicle.getBoolean(BUTTON_GSM_MORE_EXPAND_KEY);
             mDisplayMode = icicle.getInt(DISPLAY_MODE_KEY);
 
         } else {
@@ -1504,50 +1559,87 @@ public class CallFeaturesSetting extends PreferenceActivity
 
         if (DBG) log("onSaveInstanceState: saving relevant UI state.");
 
-        // save button state
-        if (mButtonCLIR != null) {
-            outState.putInt(BUTTON_CLIR_KEY, mButtonCLIR.findIndexOfValue(mButtonCLIR.getValue()));
-        }
-        if (mButtonCW != null) {
-            outState.putBoolean(BUTTON_CW_KEY, mButtonCW.isChecked());
-        }
-        if (mButtonCFU != null) {
-            outState.putBoolean(BUTTON_CFU_KEY, mButtonCFU.isToggled());
-        }
-        if (mButtonCFB != null) {
-            outState.putBoolean(BUTTON_CFB_KEY, mButtonCFB.isToggled());
-        }
-        if (mButtonCFNRy != null) {
-            outState.putBoolean(BUTTON_CFNRY_KEY, mButtonCFNRy.isToggled());
-        }
-        if (mButtonCFNRc != null) {
-            outState.putBoolean(BUTTON_CFNRC_KEY, mButtonCFNRc.isToggled());
-        }
         if (mButtonVoicePrivacy != null) {
             outState.putBoolean(BUTTON_VP_KEY, mButtonVoicePrivacy.isChecked());
         }
         if (mButtonTTY != null) {
-            outState.putBoolean(BUTTON_TTY_KEY, mButtonTTY.isChecked());
+            outState.putInt(BUTTON_TTY_KEY, mButtonTTY.findIndexOfValue(mButtonTTY.getValue()));
         }
 
-        // save number state
-        outState.putString(SUMMARY_CFU_KEY, mDialingNumCFU);
-        outState.putString(SUMMARY_CFB_KEY, mDialingNumCFB);
-        outState.putString(SUMMARY_CFNRY_KEY, mDialingNumCFNRy);
-        outState.putString(SUMMARY_CFNRC_KEY, mDialingNumCFNRc);
+        // save button state
+        if (mPhone.getPhoneName().equals("GSM")) {
+            if (mButtonCLIR != null) {
+                outState.putInt(BUTTON_CLIR_KEY, mButtonCLIR.findIndexOfValue(mButtonCLIR.getValue()));
+            }
+            if (mButtonCW != null) {
+                outState.putBoolean(BUTTON_CW_KEY, mButtonCW.isChecked());
+            }
+            if (mButtonCFU != null) {
+                outState.putBoolean(BUTTON_CFU_KEY, mButtonCFU.isToggled());
+           }
+            if (mButtonCFB != null) {
+                outState.putBoolean(BUTTON_CFB_KEY, mButtonCFB.isToggled());
+            }
+            if (mButtonCFNRy != null) {
+                outState.putBoolean(BUTTON_CFNRY_KEY, mButtonCFNRy.isToggled());
+            }
+            if (mButtonCFNRc != null) {
+                 outState.putBoolean(BUTTON_CFNRC_KEY, mButtonCFNRc.isToggled());
+            }
+
+            // save number state
+            outState.putString(SUMMARY_CFU_KEY, mDialingNumCFU);
+            outState.putString(SUMMARY_CFB_KEY, mDialingNumCFB);
+            outState.putString(SUMMARY_CFNRY_KEY, mDialingNumCFNRy);
+            outState.putString(SUMMARY_CFNRC_KEY, mDialingNumCFNRc);
 
+            outState.putBoolean(BUTTON_CF_EXPAND_KEY, mCFDataStale);
+            outState.putBoolean(BUTTON_GSM_MORE_EXPAND_KEY, mMoreDataStale);
+        }
         // save state of the app
         outState.putSerializable(APP_STATE_KEY, mAppState);
-        outState.putBoolean(BUTTON_CF_EXPAND_KEY, mCFDataStale);
-        outState.putBoolean(BUTTON_GSM_MORE_EXPAND_KEY, mMoreDataStale);
+
         outState.putInt(DISPLAY_MODE_KEY, mDisplayMode);
     }
 
     // TTY object
-    private void handleTTYClickRequest(boolean b) {
+    private void handleTTYClickRequest(Preference preference, Object objValue) {
+        int buttonTtyMode;
+        buttonTtyMode = Integer.valueOf((String) objValue).intValue();
+        int settingsTtyMode = android.provider.Settings.Secure.getInt(
+                mPhone.getContext().getContentResolver(),
+                android.provider.Settings.Secure.PREFERRED_TTY_MODE, preferredTtyMode);
         if (DBG) log("handleTTYClickRequest: requesting set TTY mode enable (TTY) to" +
-                Boolean.toString(b));
-        mPhone.setTTYModeEnabled(b, Message.obtain(mSetTTYComplete, EVENT_TTY_EXECUTED));
+                Integer.toString(buttonTtyMode));
+
+        if (buttonTtyMode != settingsTtyMode) {
+            switch(buttonTtyMode) {
+            case Phone.TTY_MODE_OFF:
+                mPhone.setTTYMode(Phone.TTY_MODE_OFF,
+                        Message.obtain(mSetTTYComplete, EVENT_TTY_MODE_SET));
+                break;
+            case Phone.TTY_MODE_FULL:
+                mPhone.setTTYMode(Phone.TTY_MODE_FULL,
+                        Message.obtain(mSetTTYComplete, EVENT_TTY_MODE_SET));
+                break;
+            case Phone.TTY_MODE_HCO:
+                mPhone.setTTYMode(Phone.TTY_MODE_HCO,
+                        Message.obtain(mSetTTYComplete, EVENT_TTY_MODE_SET));
+                break;
+            case Phone.TTY_MODE_VCO:
+                mPhone.setTTYMode(Phone.TTY_MODE_VCO,
+                        Message.obtain(mSetTTYComplete, EVENT_TTY_MODE_SET));
+                break;
+            default:
+                mPhone.setTTYMode(Phone.TTY_MODE_OFF,
+                        Message.obtain(mSetTTYComplete, EVENT_TTY_MODE_SET));
+            }
+            UpdatePreferredTtyModeSummary(buttonTtyMode);
+
+            android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
+                    android.provider.Settings.Secure.PREFERRED_TTY_MODE,
+                    buttonTtyMode );
+        }
     }
 
     /*
@@ -1561,7 +1653,11 @@ public class CallFeaturesSetting extends PreferenceActivity
             // query to make sure we're looking at the same data as that in the network.
             switch (msg.what) {
                 case EVENT_TTY_EXECUTED:
-                    handleSetTTYMessage();
+                    handleQueryTtyResponse(msg);
+                    onResume();
+                    break;
+                case EVENT_TTY_MODE_SET:
+                    onResume();
                     break;
                 default:
                     // TODO: should never reach this, may want to throw exception
@@ -1574,9 +1670,89 @@ public class CallFeaturesSetting extends PreferenceActivity
         if (DBG) {
             log("handleSetTTYMessage: set TTY request complete, reading value from network.");
         }
-        mPhone.queryTTYModeEnabled(Message.obtain(mQueryTTYComplete, EVENT_TTY_EXECUTED));
+        mPhone.queryTTYMode(Message.obtain(mQueryTTYComplete, EVENT_TTY_EXECUTED));
         android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
-                android.provider.Settings.Secure.TTY_MODE_ENABLED, preferredTTYMode );
+                android.provider.Settings.Secure.TTY_MODE_ENABLED, preferredTtyMode );
+    }
+
+    private void handleQueryTtyResponse(Message msg) {
+        AsyncResult ar = (AsyncResult) msg.obj;
+
+        if (ar.exception == null) {
+            int ttyMode = ((int[])ar.result)[0];
+
+
+
+            int settingsTtyMode = android.provider.Settings.Secure.getInt(
+                    mPhone.getContext().getContentResolver(),
+                    android.provider.Settings.Secure.PREFERRED_TTY_MODE,
+                    preferredTtyMode);
+
+            //check that modemNetworkMode is from an accepted value
+            if (ttyMode == Phone.TTY_MODE_OFF ||
+                    ttyMode == Phone.TTY_MODE_HCO ||
+                    ttyMode == Phone.TTY_MODE_VCO ||
+                    ttyMode == Phone.TTY_MODE_FULL) {
+
+                //check changes in modemNetworkMode and updates settingsNetworkMode
+                if (ttyMode != settingsTtyMode) {
+                    if (DBG) {
+                        log("handleGetPreferredNetworkTypeResponse: if 2: " +
+                                "modemNetworkMode != settingsNetworkMode");
+                    }
+
+                    settingsTtyMode = ttyMode;
+
+                    if (DBG) { log("handleGetPreferredNetworkTypeResponse: if 2: " +
+                            "settingsNetworkMode = " + settingsTtyMode);
+                    }
+
+                    //changes the Settings.System accordingly to modemNetworkMode
+                    android.provider.Settings.Secure.putInt(
+                            mPhone.getContext().getContentResolver(),
+                            android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+                            settingsTtyMode);
+                }
+
+                UpdatePreferredTtyModeSummary(ttyMode);
+                // changes the mButtonPreferredNetworkMode accordingly to modemNetworkMode
+                mButtonTTY.setValue(Integer.toString(ttyMode));
+            } else {
+                if (DBG) log("handleGetPreferredNetworkTypeResponse: else: reset to default");
+                resetTtyModeToDefault();
+            }
+        }
+    }
+
+    private void resetTtyModeToDefault() {
+        //set the mButtonPreferredTtyMode
+        mButtonTTY.setValue(Integer.toString(preferredTtyMode));
+        //set the Settings.System
+        android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
+                    android.provider.Settings.Secure.PREFERRED_TTY_MODE,
+                    preferredTtyMode );
+        //Set the Modem
+        mPhone.setTTYMode(preferredTtyMode,
+                Message.obtain(mSetTTYComplete, EVENT_TTY_EXECUTED));
+    }
+
+    private void UpdatePreferredTtyModeSummary(int TtyMode) {
+        switch(TtyMode) {
+            case Phone.TTY_MODE_OFF:
+                mButtonTTY.setSummary("TTY Mode OFF");
+                break;
+            case Phone.TTY_MODE_HCO:
+                mButtonTTY.setSummary("TTY Mode HCO");
+                break;
+            case Phone.TTY_MODE_VCO:
+                mButtonTTY.setSummary("TTY Mode VCO");
+                break;
+            case Phone.TTY_MODE_FULL:
+                mButtonTTY.setSummary("TTY Mode Full");
+                break;
+            default:
+                mButtonTTY.setSummary("TTY Mode OFF");
+        }
     }
 
     /*
@@ -1606,42 +1782,40 @@ public class CallFeaturesSetting extends PreferenceActivity
             if (DBG) log("handleQueryTTYModeMessage: TTY enable state successfully queried.");
             syncTTYState((int[]) ar.result);
             android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
-                    android.provider.Settings.Secure.TTY_MODE_ENABLED, preferredTTYMode );
+                    android.provider.Settings.Secure.TTY_MODE_ENABLED, preferredTtyMode );
         }
         return MSG_OK;
     }
+    /**
+     * Tells the StatusBar whether the TTY mode is enabled or disabled
+     */
+    private static void setStatusBarIcon(Context context, boolean enabled) {
+        Intent ttyModeChanged = new Intent(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
+        ttyModeChanged.putExtra("ttyEnabled", enabled);
+        context.sendBroadcast(ttyModeChanged);
+    }
 
     // set the state of the UI based on TTY State
     private void syncTTYState(int ttyArray[]) {
-        if (DBG) log("syncTTYState: Setting UI state consistent with TTY enable state of " +
-                ((ttyArray[0] != 0) ? "ENABLED" : "DISABLED"));
-
-        mButtonTTY.setChecked(ttyArray[0] != 0);
+    if (DBG) log("syncTTYState: Setting UI state consistent with TTY enable state of " +
+           ((ttyArray[0] != 0) ? "ENABLED" : "DISABLED"));
 
         Context context = this;
 
-        if (ttyArray[0] == 1) {
-            //display TTY icon at StatusBar
-            setStatusBarIcon(context, true);
-        }
-        else {
+        if (ttyArray[0] == 0) {
             // turn off TTY icon at StatusBar
             setStatusBarIcon(context, false);
         }
+        else {
+            //display TTY icon at StatusBar
+            setStatusBarIcon(context, true);
+        }
     }
 
-    /**
-     * Tells the StatusBar whether the TTY mode is enabled or disabled
-     */
-    private static void setStatusBarIcon(Context context, boolean enabled) {
-        Intent ttyModeChanged = new Intent(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
-        ttyModeChanged.putExtra("ttyEnabled", enabled);
-        context.sendBroadcast(ttyModeChanged);
-    }
 
     //VP object click
     private void handleVoicePrivacyClickRequest(boolean value) {
-        mPhone.enableEnhancedVoicePrivacy(value, Message.obtain(mSetVoicePrivacyComplete, 
+        mPhone.enableEnhancedVoicePrivacy(value, Message.obtain(mSetVoicePrivacyComplete,
                 EVENT_ENHANCED_VP_EXECUTED));
     }
 
@@ -1662,7 +1836,7 @@ public class CallFeaturesSetting extends PreferenceActivity
 
     // VP Object Set
     private void handleSetVPMessage() {
-        mPhone.getEnhancedVoicePrivacy(Message.obtain(mQueryVoicePrivacyComplete, 
+        mPhone.getEnhancedVoicePrivacy(Message.obtain(mQueryVoicePrivacyComplete,
                 EVENT_ENHANCED_VP_EXECUTED));
         android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
                 android.provider.Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED, preferredVPMode);
@@ -1699,7 +1873,7 @@ public class CallFeaturesSetting extends PreferenceActivity
             }
             syncVPState((int[]) ar.result);
             android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
-                    android.provider.Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED, 
+                    android.provider.Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED,
                     preferredVPMode );
         }
         return MSG_OK;
old mode 100644 (file)
new mode 100755 (executable)
index da49d77..d844a3b
@@ -19,6 +19,10 @@ package com.android.phone;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
+import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
+import com.android.internal.telephony.cdma.SignalToneUtil;
+import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaDisplayInfoRec;
+import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.gsm.GSMPhone;
@@ -61,6 +65,18 @@ public class CallNotifier extends Handler
     // before giving up and falling back to the default ringtone.
     private static final int RINGTONE_QUERY_WAIT_TIME = 500;  // msec
 
+    // Timers related to CDMA Call Waiting
+    // 1) For displaying Caller Info
+    // 2) For disabling "Add Call" menu option once User selects Ignore or CW Timeout occures
+    private static final int CALLWAITING_CALLERINFO_DISPLAY_TIME = 20000; // msec
+    private static final int CALLWAITING_ADDCALL_DISABLE_TIME = 60000; // msec
+
+    // Time to display the  DisplayInfo Record sent by CDMA network
+    private static final int DISPLAYINFO_NOTIFICATION_TIME = 2000; // msec
+
+    // Boolean to store information if a Call Waiting timed out
+    private boolean mCallWaitingTimeOut = false;
+
     // values used to track the query state
     private static final int CALLERINFO_QUERY_READY = 0;
     private static final int CALLERINFO_QUERYING = -1;
@@ -80,9 +96,15 @@ public class CallNotifier extends Handler
     private static final int PHONE_DISCONNECT = 3;
     private static final int PHONE_UNKNOWN_CONNECTION_APPEARED = 4;
     private static final int PHONE_INCOMING_RING = 5;
+    private static final int PHONE_STATE_DISPLAYINFO = 6;
+    private static final int PHONE_STATE_SIGNALINFO = 7;
+    private static final int PHONE_CDMA_CALL_WAITING = 8;
     // Events generated internally:
-    private static final int PHONE_MWI_CHANGED = 6;
-    private static final int PHONE_BATTERY_LOW = 7;
+    private static final int PHONE_MWI_CHANGED = 9;
+    private static final int PHONE_BATTERY_LOW = 10;
+    private static final int CALLWAITING_CALLERINFO_DISPLAY_DONE = 11;
+    private static final int CALLWAITING_ADDCALL_DISABLE_TIMEOUT = 12;
+    private static final int DISPLAYINFO_NOTIFICATION_DONE = 13;
 
     private PhoneApp mApplication;
     private Phone mPhone;
@@ -90,6 +112,12 @@ public class CallNotifier extends Handler
     private BluetoothHandsfree mBluetoothHandsfree;
     private boolean mSilentRingerRequested;
 
+    // ToneGenerator instance for playing SignalInfo tones
+    private ToneGenerator mSignalInfoToneGenerator;
+
+    // The tone volume relative to other sounds in the stream SignalInfo
+    private static final int TONE_RELATIVE_VOLUME_LOPRI_SIGNALINFO = 50;
+
     public CallNotifier(PhoneApp app, Phone phone, Ringer ringer,
                         BluetoothHandsfree btMgr) {
         mApplication = app;
@@ -100,6 +128,27 @@ public class CallNotifier extends Handler
         mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);
         mPhone.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
         mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
+
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            if (DBG) log("Registering for Call Waiting, Signal and Display Info.");
+            mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
+            mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
+            mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
+
+            // Instantiate the ToneGenerator for SignalInfo and CallWaiting
+            // TODO(Moto): We probably dont need the mSignalInfoToneGenerator instance
+            // around forever. Need to change it so as to create a ToneGenerator instance only
+            // when a tone is being played and releases it after its done playing.
+            try {
+                mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION,
+                        TONE_RELATIVE_VOLUME_LOPRI_SIGNALINFO);
+            } catch (RuntimeException e) {
+                Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " +
+                        "mSignalInfoToneGenerator: " + e);
+                mSignalInfoToneGenerator = null;
+            }
+        }
+
         mRinger = ringer;
         mBluetoothHandsfree = btMgr;
 
@@ -166,6 +215,38 @@ public class CallNotifier extends Handler
                 onBatteryLow();
                 break;
 
+            case PHONE_CDMA_CALL_WAITING:
+                if (DBG) log("Received PHONE_CDMA_CALL_WAITING event");
+                onCdmaCallWaiting((AsyncResult) msg.obj);
+                break;
+
+            case CALLWAITING_CALLERINFO_DISPLAY_DONE:
+                if (DBG) log("Received CALLWAITING_CALLERINFO_DISPLAY_DONE event ...");
+                mCallWaitingTimeOut = true;
+                onCdmaCallWaitingReject();
+                break;
+
+            case CALLWAITING_ADDCALL_DISABLE_TIMEOUT:
+                if (DBG) log("Received CALLWAITING_ADDCALL_DISABLE_TIMEOUT event ...");
+                // Set the mAddCallMenuStateAfterCW state to true
+                mApplication.cdmaPhoneCallState.setAddCallMenuStateAfterCallWaiting(true);
+                break;
+
+            case PHONE_STATE_DISPLAYINFO:
+                if (DBG) log("Received PHONE_STATE_DISPLAYINFO event");
+                onDisplayInfo((AsyncResult) msg.obj);
+                break;
+
+            case PHONE_STATE_SIGNALINFO:
+                if (DBG) log("Received PHONE_STATE_SIGNALINFO event");
+                onSignalInfo((AsyncResult) msg.obj);
+                break;
+
+            case DISPLAYINFO_NOTIFICATION_DONE:
+                if (DBG) log("Received Display Info notification done event ...");
+                CdmaDisplayInfo.dismissDisplayInfoRecord();
+                break;
+
             default:
                 // super.handleMessage(msg);
         }
@@ -186,7 +267,6 @@ public class CallNotifier extends Handler
     private void onNewRingingConnection(AsyncResult r) {
         Connection c = (Connection) r.result;
         if (DBG) log("onNewRingingConnection(): " + c);
-        PhoneApp app = PhoneApp.getInstance();
 
         // Incoming calls are totally ignored if the device isn't provisioned yet
         boolean provisioned = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
@@ -432,20 +512,44 @@ public class CallNotifier extends Handler
     }
 
     void updateCallNotifierRegistrationsAfterRadioTechnologyChange() {
-        if(DBG) Log.d(LOG_TAG, "updateCallNotifierRegistrationsAfterRadioTechnologyChange...");
-        //Unregister all events from the old obsolete phone
+        if (DBG) Log.d(LOG_TAG, "updateCallNotifierRegistrationsAfterRadioTechnologyChange...");
+        // Unregister all events from the old obsolete phone
         mPhone.unregisterForNewRingingConnection(this);
         mPhone.unregisterForPhoneStateChanged(this);
         mPhone.unregisterForDisconnect(this);
         mPhone.unregisterForUnknownConnection(this);
         mPhone.unregisterForIncomingRing(this);
+        mPhone.unregisterForCallWaiting(this);
+        mPhone.unregisterForDisplayInfo(this);
+        mPhone.unregisterForSignalInfo(this);
+
+        // Release the ToneGenerator used for playing SignalInfo and CallWaiting
+        if (mSignalInfoToneGenerator != null) {
+            mSignalInfoToneGenerator.release();
+        }
 
-        //Register all events new to the new active phone
+        // Register all events new to the new active phone
         mPhone.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
         mPhone.registerForPhoneStateChanged(this, PHONE_STATE_CHANGED, null);
         mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);
         mPhone.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
         mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            if (DBG) log("Registering for Call Waiting, Signal and Display Info.");
+            mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
+            mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
+            mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
+
+            // Instantiate the ToneGenerator for SignalInfo
+            try {
+                mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION,
+                        TONE_RELATIVE_VOLUME_LOPRI_SIGNALINFO);
+            } catch (RuntimeException e) {
+                Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " +
+                        "mSignalInfoToneGenerator: " + e);
+                mSignalInfoToneGenerator = null;
+            }
+        }
     }
 
     /**
@@ -501,6 +605,11 @@ public class CallNotifier extends Handler
             PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);
         }
 
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            // Create the SignalInfo tone player to stop any signalInfo tone being played.
+            new SignalInfoTonePlayer(ToneGenerator.TONE_CDMA_SIGNAL_OFF).start();
+        }
+
         Connection c = (Connection) r.result;
         if (DBG && c != null) {
             log("- onDisconnect: cause = " + c.getDisconnectCause()
@@ -575,6 +684,7 @@ public class CallNotifier extends Handler
         if (c != null) {
             final String number = c.getAddress();
             final int presentation = c.getNumberPresentation();
+            if (DBG) log("- onDisconnect: presentation=" + presentation);
             final long date = c.getCreateTime();
             final long duration = c.getDurationMillis();
             final Connection.DisconnectCause cause = c.getDisconnectCause();
@@ -618,7 +728,7 @@ public class CallNotifier extends Handler
                 // the user deliberately rejected.)
 
                 PhoneUtils.CallerInfoToken info =
-                    PhoneUtils.startGetCallerInfo(mApplication, c, this, new Long(date));
+                        PhoneUtils.startGetCallerInfo(mApplication, c, this, Long.valueOf(date));
                 if (info != null) {
                     // at this point, we've requested to start a query, but it makes no
                     // sense to log this missed call until the query comes back.
@@ -673,6 +783,15 @@ public class CallNotifier extends Handler
                 if (VDBG) log("- phone still in use; not releasing wake locks.");
             }
         }
+
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            // Resetting the CdmaPhoneCallState members
+            mApplication.cdmaPhoneCallState.resetCdmaPhoneCallState();
+
+            // Remove Call waiting timers
+            removeMessages(CALLWAITING_CALLERINFO_DISPLAY_DONE);
+            removeMessages(CALLWAITING_ADDCALL_DISABLE_TIMEOUT);
+        }
     }
 
     /**
@@ -890,6 +1009,171 @@ public class CallNotifier extends Handler
         }
     }
 
+    /**
+     * Displays a notification when the phone receives a DisplayInfo record.
+     */
+    private void onDisplayInfo(AsyncResult r) {
+        // Extract the DisplayInfo String from the message
+        CdmaDisplayInfoRec displayInfoRec = (CdmaDisplayInfoRec)(r.result);
+
+        if (displayInfoRec != null) {
+            String displayInfo = displayInfoRec.alpha;
+            if (DBG) log("onDisplayInfo: displayInfo=" + displayInfo);
+            CdmaDisplayInfo.displayInfoRecord(mApplication, displayInfo);
+
+            // start a 2 second timer
+            sendEmptyMessageDelayed(DISPLAYINFO_NOTIFICATION_DONE,
+                    DISPLAYINFO_NOTIFICATION_TIME);
+        }
+    }
+
+    /**
+     * Helper class to play SignalInfo tones using the ToneGenerator.
+     *
+     * To use, just instantiate a new SignalInfoTonePlayer
+     * (passing in the ToneID constant for the tone you want)
+     * and start() it.
+     */
+    private class SignalInfoTonePlayer extends Thread {
+        private int mToneId;
+
+        SignalInfoTonePlayer(int toneId) {
+            super();
+            mToneId = toneId;
+        }
+
+        @Override
+        public void run() {
+            if (DBG) log("SignalInfoTonePlayer.run(toneId = " + mToneId + ")...");
+
+            if (mSignalInfoToneGenerator != null) {
+                //First stop any ongoing SignalInfo tone
+                mSignalInfoToneGenerator.stopTone();
+
+                //Start playing the new tone if its a valid tone
+                mSignalInfoToneGenerator.startTone(mToneId);
+            }
+        }
+    }
+
+    /**
+     * Plays a tone when the phone receives a SignalInfo record.
+     */
+    private void onSignalInfo(AsyncResult r) {
+        // Extract the SignalInfo String from the message
+        CdmaSignalInfoRec signalInfoRec = (CdmaSignalInfoRec)(r.result);
+        // Only proceed if a Signal info is present.
+        if (signalInfoRec != null) {
+            boolean isPresent = signalInfoRec.isPresent;
+            if (DBG) log("onSignalInfo: isPresent=" + isPresent);
+            if (isPresent) {// if tone is valid
+                int uSignalType = signalInfoRec.signalType;
+                int uAlertPitch = signalInfoRec.alertPitch;
+                int uSignal = signalInfoRec.signal;
+
+                if (DBG) log("onSignalInfo: uSignalType=" + uSignalType + ", uAlertPitch=" +
+                        uAlertPitch + ", uSignal=" + uSignal);
+                //Map the Signal to a ToneGenerator ToneID only if Signal info is present
+                int toneID =
+                        SignalToneUtil.getAudioToneFromSignalInfo(uSignalType, uAlertPitch, uSignal);
+
+                //Create the SignalInfo tone player and pass the ToneID
+                new SignalInfoTonePlayer(toneID).start();
+            }
+        }
+    }
+
+    /**
+     * Plays a Call waiting tone if it is present in the second incoming call.
+     */
+    private void onCdmaCallWaiting(AsyncResult r) {
+        // Start the InCallScreen Activity if its not on foreground
+        if (!mApplication.isShowingCallScreen()) {
+            PhoneUtils.showIncomingCallUi();
+        }
+
+        // Start timer for CW display
+        mCallWaitingTimeOut = false;
+        sendEmptyMessageDelayed(CALLWAITING_CALLERINFO_DISPLAY_DONE,
+                CALLWAITING_CALLERINFO_DISPLAY_TIME);
+
+        // Set the mAddCallMenuStateAfterCW state to false
+        mApplication.cdmaPhoneCallState.setAddCallMenuStateAfterCallWaiting(false);
+
+        // Start the timer for disabling "Add Call" menu option
+        sendEmptyMessageDelayed(CALLWAITING_ADDCALL_DISABLE_TIMEOUT,
+                CALLWAITING_ADDCALL_DISABLE_TIME);
+
+        // Extract the Call waiting information
+        CdmaCallWaitingNotification infoCW = (CdmaCallWaitingNotification) r.result;
+        int isPresent = infoCW.isPresent;
+        if (DBG) log("onCdmaCallWaiting: isPresent=" + isPresent);
+        if (isPresent == 1 ) {//'1' if tone is valid
+            int uSignalType = infoCW.signalType;
+            int uAlertPitch = infoCW.alertPitch;
+            int uSignal = infoCW.signal;
+            if (DBG) log("onCdmaCallWaiting: uSignalType=" + uSignalType + ", uAlertPitch="
+                    + uAlertPitch + ", uSignal=" + uSignal);
+            //Map the Signal to a ToneGenerator ToneID only if Signal info is present
+            int toneID =
+                SignalToneUtil.getAudioToneFromSignalInfo(uSignalType, uAlertPitch, uSignal);
+
+            //Create the SignalInfo tone player and pass the ToneID
+            new SignalInfoTonePlayer(toneID).start();
+        }
+    }
+
+    /**
+     * Performs Call logging based on Timeout or Ignore Call Waiting Call for CDMA,
+     * and finally calls Hangup on the Call Waiting connection.
+     */
+    /* package */ void onCdmaCallWaitingReject() {
+        final Call ringingCall = mPhone.getRingingCall();
+
+        // Call waiting timeout scenario
+        if (ringingCall.getState() == Call.State.WAITING) {
+            // Code for perform Call logging and missed call notification
+            Connection c = ringingCall.getLatestConnection();
+
+            if (c != null) {
+                String number = c.getAddress();
+                int isPrivateNumber = c.getNumberPresentation();
+                long date = c.getCreateTime();
+                long duration = c.getDurationMillis();
+                int callLogType = mCallWaitingTimeOut ?
+                        CallLog.Calls.MISSED_TYPE  : CallLog.Calls.INCOMING_TYPE;
+
+                // get the callerinfo object and then log the call with it.
+                Object o = c.getUserData();
+                CallerInfo ci;
+                if ((o == null) || (o instanceof CallerInfo)) {
+                    ci = (CallerInfo) o;
+                } else {
+                    ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
+                }
+
+                // Add Call log
+                Calls.addCall(ci, mApplication, number, isPrivateNumber, callLogType,
+                        date, (int) duration / 1000);
+
+                if (callLogType == CallLog.Calls.MISSED_TYPE) {
+                    // Add missed call notification
+                    NotificationMgr.getDefault().notifyMissedCall(ci.name,
+                            ci.phoneNumber, ci.phoneLabel, date);
+                }
+
+                // Set the Phone Call State to SINGLE_ACTIVE as there is only one connection
+                mApplication.cdmaPhoneCallState.setCurrentCallState(
+                        CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE);
+
+                // Hangup the RingingCall connection for CW
+                PhoneUtils.hangup(c);
+            }
+
+            //Reset the mCallWaitingTimeOut boolean
+            mCallWaitingTimeOut = false;
+        }
+    }
 
     private void log(String msg) {
         Log.d(LOG_TAG, msg);
diff --git a/src/com/android/phone/CdmaDisplayInfo.java b/src/com/android/phone/CdmaDisplayInfo.java
new file mode 100755 (executable)
index 0000000..1e7dee8
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 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.phone;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.WindowManager;
+
+/**
+ * Helper class for displaying the DisplayInfo sent by CDMA network.
+ */
+public class CdmaDisplayInfo {
+    private static final String LOG_TAG = "CdmaDisplayInfo";
+    private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
+
+    /** CDMA DisplayInfo dialog */
+    private static AlertDialog sDisplayInfoDialog = null;
+
+    /**
+     * Handle the DisplayInfo record and display the alert dialog with
+     * the network message.
+     *
+     * @param context context to get strings.
+     * @param infoMsg Text message from Network.
+     */
+    public static void displayInfoRecord(Context context, String infoMsg) {
+
+        if (DBG) log("displayInfoRecord: infoMsg=" + infoMsg);
+
+        if (sDisplayInfoDialog != null) {
+            sDisplayInfoDialog.dismiss();
+        }
+
+        // displaying system alert dialog on the screen instead of
+        // using another activity to display the message.  This
+        // places the message at the forefront of the UI.
+        sDisplayInfoDialog = new AlertDialog.Builder(context)
+                .setIcon(android.R.drawable.ic_dialog_info)
+                .setTitle(context.getText(R.string.network_message))
+                .setMessage(infoMsg)
+                .setCancelable(true)
+                .create();
+
+        sDisplayInfoDialog.getWindow().setType(
+                WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+        sDisplayInfoDialog.getWindow().addFlags(
+                WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+
+        sDisplayInfoDialog.show();
+        PhoneApp.getInstance().wakeUpScreen();
+
+    }
+
+    /**
+     * Dismiss the DisplayInfo record
+     */
+    public static void dismissDisplayInfoRecord() {
+
+        if (DBG) log("Dissmissing Display Info Record...");
+
+        if (sDisplayInfoDialog != null) {
+            sDisplayInfoDialog.dismiss();
+            sDisplayInfoDialog = null;
+        }
+    }
+
+    private static void log(String msg) {
+        Log.d(LOG_TAG, "[CdmaDisplayInfo] " + msg);
+    }
+}
index c63ab31..f340933 100644 (file)
@@ -61,7 +61,7 @@ public class CdmaOptions extends PreferenceActivity implements Preference.OnPref
     
     //preferredSubscriptionMode  0 - RUIM/SIM, preferred
     //                           1 - NV
-    static final int preferredSubscriptionMode = 0;
+    static final int preferredSubscriptionMode = CDMA_SUBSCRIPTION_NV;
     
     //UI objects
     private ListPreference mButtonCdmaRoam;
@@ -229,8 +229,10 @@ public class CdmaOptions extends PreferenceActivity implements Preference.OnPref
                         statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_NV;
                         break;
                     case CDMA_SUBSCRIPTION_RUIM_SIM:
-                    default:
                         statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_RUIM_SIM;
+                        break;
+                    default:
+                        statusCdmaSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
                 } 
                 //Set the Settings.System network mode        
                 android.provider.Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
diff --git a/src/com/android/phone/CdmaPhoneCallState.java b/src/com/android/phone/CdmaPhoneCallState.java
new file mode 100755 (executable)
index 0000000..a26baaa
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 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.phone;
+
+/**
+ * Class to internally keep track of Call states to maintain
+ * information for Call Waiting and 3Way for CDMA instance of Phone App.
+ *
+ * Explaination for PhoneApp's Call states and why it is required:
+ * IDLE - When no call is going on. This is just required as default state to reset the PhoneApp
+ *        call state to when the complete call gets disconnected
+ * SINGLE_ACTIVE - When only single call is active.
+ *        In normal case(on a single call) this state would be similar for FW's state of ACTIVE
+ *        call or phone state of OFFHOOK, but in more complex conditions e.g. when phone is already
+ *        in a CONF_CALL state and user rejects a CW, which basically tells the PhoneApp that the
+ *        Call is back to a single call, the FW's state still would remain ACTIVE or OFFHOOK and
+ *        isGeneric would still be true. At this condition PhoneApp does need to enable the
+ *        "Add Call" menu item and disable the "Swap" and "Merge" options
+ * THRWAY_ACTIVE - When user initiate an outgoing call when already on a call.
+ *        fgCall can have more than one connections from various scenarios (accepting the CW or
+ *        making a 3way call) but once we are in this state and one of the parties drops off,
+ *        when the user originates another call we need to remember this state to update the menu
+ *        items accordingly. FW currently does not differentiate this condition hence PhoneApp
+ *        needs to maintain it.
+ * CONF_CALL - When the user merges two calls or on accepting the Call waiting call.
+ *        This is required cause even though a call might be generic but that does not mean it is
+ *        in conference. We can take the same example mention in the SINGLE_ACTIVE state.
+ *
+ * TODO(Moto): Eventually this state information should be maintained by Telephony FW.
+ */
+   public class CdmaPhoneCallState {
+
+        /**
+         * Allowable values for the PhoneCallState.
+         *   IDLE - When no call is going on.
+         *   SINGLE_ACTIVE - When only single call is active
+         *   THRWAY_ACTIVE - When user initiate an outgoing call when already on a call
+         *   CONF_CALL - When the user merges two calls or on accepting the Call waiting call
+         */
+        public enum PhoneCallState {
+            IDLE,
+            SINGLE_ACTIVE,
+            THRWAY_ACTIVE,
+            CONF_CALL
+        }
+
+        // For storing current and previous PhoneCallState's
+        private PhoneCallState mPreviousCallState;
+        private PhoneCallState mCurrentCallState;
+
+        // Boolean to track 3Way display state
+        private boolean mThreeWayCallOrigStateDialing;
+
+        // Flag to indicate if the "Add Call" menu item in an InCallScreen is OK
+        // to be displayed after a Call Waiting call was ignored or timed out
+        private boolean mAddCallMenuStateAfterCW;
+
+        /**
+         * Initialize PhoneCallState related members - constructor
+         */
+        public void CdmaPhoneCallStateInit() {
+            mCurrentCallState = PhoneCallState.IDLE;
+            mPreviousCallState = PhoneCallState.IDLE;
+            mThreeWayCallOrigStateDialing = false;
+            mAddCallMenuStateAfterCW = true;
+        }
+
+        /**
+         * Returns the current call state
+         */
+        public PhoneCallState getCurrentCallState() {
+            return mCurrentCallState;
+        }
+
+        /**
+         * Set current and previous PhoneCallState's
+         */
+        public void setCurrentCallState(PhoneCallState newState) {
+            mPreviousCallState = mCurrentCallState;
+            mCurrentCallState = newState;
+
+            //Reset the 3Way display boolean
+            mThreeWayCallOrigStateDialing = false;
+
+            //Set mAddCallMenuStateAfterCW to true
+            //if the current state is being set to SINGLE_ACTIVE
+            //and previous state was IDLE as we could reach the SINGLE_ACTIVE
+            //from CW ignore too. For all other cases let the timer or
+            //specific calls to setAddCallMenuStateAfterCallWaiting set
+            //mAddCallMenuStateAfterCW.
+            if ((mCurrentCallState == PhoneCallState.SINGLE_ACTIVE)
+                && (mPreviousCallState == PhoneCallState.IDLE)) {
+                mAddCallMenuStateAfterCW = true;
+            }
+        }
+
+        /**
+         * Return 3Way display information
+         */
+        public boolean IsThreeWayCallOrigStateDialing() {
+            return mThreeWayCallOrigStateDialing;
+        }
+
+        /**
+         * Set 3Way display information
+         */
+        public void setThreeWayCallOrigState(boolean newState) {
+            mThreeWayCallOrigStateDialing = newState;
+        }
+
+        /**
+         * Return information for enabling/disabling "Add Call" menu item
+         */
+        public boolean getAddCallMenuStateAfterCallWaiting() {
+            return mAddCallMenuStateAfterCW;
+        }
+
+        /**
+         * Set mAddCallMenuStateAfterCW to enabling/disabling "Add Call" menu item
+         */
+        public void setAddCallMenuStateAfterCallWaiting(boolean newState) {
+            mAddCallMenuStateAfterCW = newState;
+        }
+
+        /**
+         * Return previous PhoneCallState's
+         */
+        public PhoneCallState getPreviousCallState() {
+            return mPreviousCallState;
+        }
+
+        /**
+         * Reset all PhoneCallState
+         */
+        public void resetCdmaPhoneCallState() {
+            mCurrentCallState = PhoneCallState.IDLE;
+            mPreviousCallState = PhoneCallState.IDLE;
+            mThreeWayCallOrigStateDialing = false;
+            mAddCallMenuStateAfterCW = true;
+        }
+   }
index 19e89eb..a5369f7 100644 (file)
@@ -442,15 +442,11 @@ public class CellBroadcastSms extends PreferenceActivity
     protected void onPause() {
         super.onPause();
 
-        int currentSelection[] = CellBroadcastSmsConfig.getCbSmsAllValues();
-
-        if (currentSelection[0] > 0) {
             CellBroadcastSmsConfig.setCbSmsNoOfStructs(NO_OF_SERVICE_CATEGORIES);
 
             mPhone.setCellBroadcastSmsConfig(CellBroadcastSmsConfig.getCbSmsAllValues(),
                     Message.obtain(mHandler, MESSAGE_SET_CB_SMS_CONFIG));
         }
-    }
 
     private void enableDisableAllCbConfigButtons(boolean enable) {
         mButtonEmergencyBroadcast.setEnabled(enable);
@@ -630,6 +626,7 @@ public class CellBroadcastSms extends PreferenceActivity
             return(mBSelected);
         }
         
+        // TODO: Change the return value to a RIL_BroadcastSMSConfig
         private static int[] getCbSmsAllValues() {
             return(mConfigDataComplete);
         }
old mode 100644 (file)
new mode 100755 (executable)
index 667d6e7..a5962f3
@@ -44,6 +44,9 @@ import com.android.internal.telephony.CallerInfoAsyncQuery;
 import com.android.internal.telephony.Phone;
 
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Queue;
+
 
 /**
  * Dialer class that encapsulates the DTMF twelve key behaviour.
@@ -60,14 +63,31 @@ public class DTMFTwelveKeyDialer implements
 
     // events
     private static final int PHONE_DISCONNECT = 100;
+    private static final int DTMF_SEND_CNF = 101;
+    private static final int STOP_DTMF_TONE = 102;
+
+
 
-    private static Phone mPhone;
+    private Phone mPhone;
     private ToneGenerator mToneGenerator;
     private Object mToneGeneratorLock = new Object();
 
     // indicate if we want to enable the DTMF tone playback.
     private boolean mDTMFToneEnabled;
 
+    // DTMF tone type
+    private int mDTMFToneType;
+
+    // indicate if the confirmation from TelephonyFW is pending.
+    private boolean mDTMFBurstCnfPending = false;
+
+    // Queue to queue the short dtmf characters.
+    private Queue<Character> mDTMFQueue = new LinkedList<Character>();
+
+    //  Short Dtmf tone duration
+    private static final int DTMF_DURATION_MS = 120;
+
+
     /** Hash Map to map a character to a tone*/
     private static final HashMap<Character, Integer> mToneMap =
         new HashMap<Character, Integer>();
@@ -130,7 +150,7 @@ public class DTMFTwelveKeyDialer implements
      * Create an input method just so that the textview can display the cursor.
      * There is no selecting / positioning on the dialer field, only number input.
      */
-    private class DTMFDisplayMovementMethod implements MovementMethod {
+    private static class DTMFDisplayMovementMethod implements MovementMethod {
 
         /**Return false since we are NOT consuming the input.*/
         public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
@@ -457,8 +477,10 @@ public class DTMFTwelveKeyDialer implements
          */
         public boolean onKeyUp(KeyEvent event) {
             if (event == null) {
-                if (DBG) log("Stopping the last played tone.");
-                stopTone();
+                //the below piece of code sends stopDTMF event unnecessarily even when a null event
+                //is received, hence commenting it.
+                /*if (DBG) log("Stopping the last played tone.");
+                stopTone();*/
                 return true;
             }
 
@@ -526,6 +548,15 @@ public class DTMFTwelveKeyDialer implements
                     mPhone.unregisterForDisconnect(this);
                     closeDialer(false);
                     break;
+                case DTMF_SEND_CNF:
+                    if (DBG) log("dtmf confirmation received from FW.");
+                    // handle burst dtmf confirmation
+                    handleBurstDtmfConfirmation();
+                    break;
+                case STOP_DTMF_TONE:
+                    if (DBG) log("stop-dtmf-tone received.");
+                    stopToneCdma();
+                    break;
             }
         }
     };
@@ -602,6 +633,14 @@ public class DTMFTwelveKeyDialer implements
             mDialerContainer.setOnDrawerOpenListener(null);
             mDialerContainer.setOnDrawerCloseListener(null);
         }
+        if (mPhone.getPhoneName().equals("CDMA")) {
+            mHandler.removeMessages(STOP_DTMF_TONE);
+            mHandler.removeMessages(DTMF_SEND_CNF);
+            synchronized (mDTMFQueue) {
+                mDTMFBurstCnfPending = false;
+                mDTMFQueue.clear();
+            }
+        }
         closeDialer(false);
     }
 
@@ -953,18 +992,21 @@ public class DTMFTwelveKeyDialer implements
     /**
      * Starts playing a DTMF tone.  Also begins the local tone playback,
      * if enabled.
-     *
+     * The access of this function is package rather than private
+     * since this is being referred from InCallScreen.
+     * InCallScreen calls this function to utilize the DTMF ToneGenerator properties
+     * defined here.
      * @param tone a tone code from {@link ToneGenerator}
      */
-    private void startTone(char tone) {
-        if (DBG) log("startTone()...");
-        PhoneApp.getInstance().phone.startDtmf(tone);
+    /* package */ void startDtmfTone(char tone) {
+        if (DBG) log("startDtmfTone()...");
+        mPhone.startDtmf(tone);
 
         // if local tone playback is enabled, start it.
         if (mDTMFToneEnabled) {
             synchronized (mToneGeneratorLock) {
                 if (mToneGenerator == null) {
-                    if (DBG) log("startTone: mToneGenerator == null, tone: " + tone);
+                    if (DBG) log("startDtmfTone: mToneGenerator == null, tone: " + tone);
                 } else {
                     if (DBG) log("starting local tone " + tone);
                     mToneGenerator.startTone(mToneMap.get(tone));
@@ -979,17 +1021,21 @@ public class DTMFTwelveKeyDialer implements
      * The ToneStopper class (similar to that in {@link TwelveKeyDialer#mToneStopper})
      * has been removed in favor of synchronous start / stop calls since tone duration
      * is now a function of the input.
+     * The acess of this function is package rather than private
+     * since this is being referred from InCallScreen.
+     * InCallScreen calls this function to utilize the DTMF ToneGenerator properties
+     * defined here.
      */
-    private void stopTone() {
-        if (DBG) log("stopTone()...");
-        PhoneApp.getInstance().phone.stopDtmf();
+    /* package */ void stopDtmfTone() {
+        if (DBG) log("stopDtmfTone()...");
+        mPhone.stopDtmf();
 
         // if local tone playback is enabled, stop it.
         if (DBG) log("trying to stop local tone...");
         if (mDTMFToneEnabled) {
             synchronized (mToneGeneratorLock) {
                 if (mToneGenerator == null) {
-                    if (DBG) log("stopTone: mToneGenerator == null");
+                    if (DBG) log("stopDtmfTone: mToneGenerator == null");
                 } else {
                     if (DBG) log("stopping local tone.");
                     mToneGenerator.stopTone();
@@ -1011,4 +1057,130 @@ public class DTMFTwelveKeyDialer implements
     private static void log(String msg) {
         Log.d(LOG_TAG, msg);
     }
+
+    /**
+     * Plays the local tone based the phone type.
+     */
+    private void startTone(char c) {
+        if (mPhone.getPhoneName().equals("GSM")) {
+            startDtmfTone(c);
+        } else {
+            startToneCdma(c);
+        }
+    }
+
+    /**
+     * Stops the local tone based on the phone type.
+     */
+    private void stopTone() {
+        if (mPhone.getPhoneName().equals("GSM")) {
+            stopDtmfTone();
+        } else {
+            // Cdma case we do stopTone only for Long DTMF Setting
+            if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_LONG) {
+                stopToneCdma();
+            }
+        }
+    }
+
+    /**
+     * Plays tone when the DTMF setting is normal(Short).
+     */
+    void startToneCdma(char tone) {
+        // Read the settings as it may be changed by the user during the call
+        mDTMFToneType = Settings.System.getInt(mInCallScreen.getContentResolver(),
+                Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
+                CallFeaturesSetting.preferredDtmfMode);
+        // For Short DTMF we need to play the local tone for fixed duration
+        if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL) {
+            sendShortDtmfToNetwork (tone);
+        } else {
+            // Pass as a char to be sent to network
+            Log.i(LOG_TAG, "send long dtmf for " + tone);
+            mPhone.startDtmf(tone);
+        }
+
+        // if local tone playback is enabled, start it.
+        if (mDTMFToneEnabled) {
+            synchronized (mToneGeneratorLock) {
+                if (mToneGenerator == null) {
+                    if (DBG) log("startToneCdma: mToneGenerator == null, tone: " + tone);
+                } else {
+                    if (DBG) log("starting local tone " + tone);
+
+                    // Stop any playing tone and start the new tone.
+                    stopToneCdma();
+                    mToneGenerator.startTone(mToneMap.get(tone));
+
+                    // Stopped pending and Started new STOP_DTMF_TONE timer.
+                    if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL) {
+                        mHandler.removeMessages(STOP_DTMF_TONE);
+                        mHandler.sendEmptyMessageDelayed(STOP_DTMF_TONE,DTMF_DURATION_MS);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Sends the dtmf character over the network for short DTMF settings
+     * When the characters are entered in quick succession,
+     * the characters are queued before sending over the network.
+     */
+    private void sendShortDtmfToNetwork(char dtmfDigit) {
+        synchronized (mDTMFQueue) {
+            if (mDTMFBurstCnfPending == true) {
+                // Insert the dtmf char to the queue
+                mDTMFQueue.add(new Character(dtmfDigit));
+            } else {
+                String dtmfStr = Character.toString(dtmfDigit);
+                Log.i(LOG_TAG,"dtmfsent = " + dtmfStr);
+                mPhone.sendBurstDtmf(dtmfStr, mHandler.obtainMessage(DTMF_SEND_CNF));
+                // Set flag to indicate wait for Telephony confirmation.
+                mDTMFBurstCnfPending = true;
+            }
+        }
+    }
+
+    /**
+     * Stops the dtmf from being sent over the network for Long DTMF case and stops local DTMF key feedback tone.
+     */
+    private void stopToneCdma() {
+        if (DBG) log("stopping remote tone.");
+
+        if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_LONG) {
+            mPhone.stopDtmf();
+        }
+
+        // if local tone playback is enabled, stop it.
+        if (DBG) log("trying to stop local tone...");
+        if (mDTMFToneEnabled) {
+            synchronized (mToneGeneratorLock) {
+                if (mToneGenerator == null) {
+                    if (DBG) log("stopToneCdma: mToneGenerator == null");
+                } else {
+                    if (DBG) log("stopping local tone.");
+                    mToneGenerator.stopTone();
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles Burst Dtmf Confirmation from the Framework.
+     */
+    void handleBurstDtmfConfirmation() {
+        Character dtmfChar = null;
+        synchronized(mDTMFQueue) {
+            mDTMFBurstCnfPending = false;
+            if(!mDTMFQueue.isEmpty()) {
+                dtmfChar = mDTMFQueue.remove();
+                Log.i(LOG_TAG, "The dtmf character removed from queue" + dtmfChar);
+            }
+        }
+        if (dtmfChar != null) {
+            sendShortDtmfToNetwork(dtmfChar);
+        }
+    }
+
 }
index e8e72e6..910db76 100644 (file)
@@ -91,7 +91,6 @@ class DTMFTwelveKeyDialerView extends LinearLayout {
 
         final int numTouchables = touchables.size();
         
-        Rect closestBounds = new Rect();
         Rect touchableBounds = new Rect();
         
         for (int i = 0; i < numTouchables; i++) {
diff --git a/src/com/android/phone/EmergencyCallbackMode.java b/src/com/android/phone/EmergencyCallbackMode.java
new file mode 100644 (file)
index 0000000..5bbc51b
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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.phone;
+
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ImageButton;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+/**
+ * Phone app Emergency Callback screen.
+ */
+public class EmergencyCallbackMode extends Activity {
+
+    /** Event for TTY mode change */
+    private static final int EVENT_EXIT_ECBM    = 100;
+
+    private Phone mPhone;
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ecbm_layout);
+
+        //get mPhone instance
+        mPhone = PhoneFactory.getDefaultPhone();
+
+        // Watch for button clicks.
+        ImageButton dialButton = (ImageButton)findViewById(R.id.button_dial);
+        dialButton.setOnClickListener(mDialListener);
+
+        Button exitButton = (Button)findViewById(R.id.button_exit);
+        exitButton.setOnClickListener(mExitListener);
+
+        Button okButton = (Button)findViewById(R.id.button_ok);
+        okButton.setOnClickListener(mOkListener);
+
+        //cancel ECBM notification
+        NotificationMgr.getDefault().cancelEcbmNotification();
+    }
+
+    private OnClickListener mDialListener = new OnClickListener()
+    {
+        public void onClick(View v)
+        {
+            Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY,  Uri.parse("tel:911"));
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(intent);
+            //create Notification
+            NotificationMgr.getDefault().notifyECBM();
+            // finish Application
+            finish();
+
+        }
+    };
+
+    private OnClickListener mExitListener = new OnClickListener()
+    {
+        public void onClick(View v) {
+            // Send ECBM exit
+
+            // TODO(Moto): There is a change, no parameter looks like an intent is sent?
+            //mPhone.exitEmergencyCallbackMode(Message.obtain(mExitEmergencyCallbackMode,
+            //        EVENT_EXIT_ECBM));
+        }
+    };
+
+
+    // **Callback on Exit Emergency callback mode
+    private Handler mExitEmergencyCallbackMode = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            // query to make sure we're looking at the same data as that in the network.
+            switch (msg.what) {
+                case EVENT_EXIT_ECBM:
+                    handleExitEmergencyCallbackModeResponse(msg);
+                    break;
+                default:
+                    // TODO: should never reach this, may want to throw exception
+            }
+        }
+    };
+
+    /*
+     * Handle the respone of the ExitEmergencyCallbackMode request
+     */
+    private void handleExitEmergencyCallbackModeResponse(Message msg) {
+        AsyncResult ar = (AsyncResult) msg.obj;
+
+        if (ar.exception == null) {
+            // Finish Emergency Callback Mode Application
+            finish();
+        }
+    }
+
+
+    private OnClickListener mOkListener = new OnClickListener()
+    {
+        public void onClick(View v)
+        {
+            // create a notification
+            NotificationMgr.getDefault().notifyECBM();
+            // finish Application
+            finish();
+        }
+    };
+
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        // suppress all key presses except of call key
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_CALL: {
+                Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY,  Uri.parse("tel:911"));
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                startActivity(intent);
+                finish();
+            }
+        }
+        return true;
+    }
+
+}
\ No newline at end of file
index cf20ef7..827fb30 100644 (file)
@@ -44,7 +44,7 @@ import android.view.WindowManager;
 import android.widget.EditText;
 
 /**
- * EmergencyDialer is a special dailer that is used ONLY for dialing emergency calls.
+ * EmergencyDialer is a special dialer that is used ONLY for dialing emergency calls.
  * It is a special case of the TwelveKeyDialer that:
  *   1. allows ONLY emergency calls to be dialed
  *   2. disallows voicemail functionality
@@ -286,8 +286,6 @@ View.OnLongClickListener, View.OnKeyListener, TextWatcher {
     }
 
     public void onClick(View view) {
-        final Editable digits = mDigits.getText();
-
         switch (view.getId()) {
             case R.id.one: {
                 playTone(ToneGenerator.TONE_DTMF_1);
@@ -418,7 +416,7 @@ View.OnLongClickListener, View.OnKeyListener, TextWatcher {
     public void onPause() {
         // Turn keyguard back on and set the poke lock timeout to default.  There
         // is no need to do anything with the wake lock.
-        if (DBG) Log.d(LOG_TAG, "turning keyguard back on and closing the dailer");
+        if (DBG) Log.d(LOG_TAG, "turning keyguard back on and closing the dialer");
         PhoneApp app = (PhoneApp) getApplication();
         app.reenableKeyguard();
         app.setScreenTimeout(PhoneApp.ScreenTimeoutDuration.DEFAULT);
diff --git a/src/com/android/phone/EriTextWidgetProvider.java b/src/com/android/phone/EriTextWidgetProvider.java
new file mode 100644 (file)
index 0000000..c44679c
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2009 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.phone;
+
+import android.app.PendingIntent;
+import android.app.Service;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.IBinder;
+import android.telephony.TelephonyManager;
+import android.text.format.Time;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+public class EriTextWidgetProvider extends AppWidgetProvider {
+    static final String LOG_TAG = "EriTextWidgetProvider";
+
+    static final ComponentName THIS_APPWIDGET =
+        new ComponentName("com.android.phone",
+                "com.android.phone.EriTextWidgetProvider");
+
+    private static EriTextWidgetProvider sInstance;
+
+    static synchronized EriTextWidgetProvider getInstance() {
+        if (sInstance == null) {
+            sInstance = new EriTextWidgetProvider();
+        }
+        return sInstance;
+    }
+
+    @Override
+    public void onEnabled(Context context) {
+        TelephonyManager mPhone;
+        String eriText = "ERI not init";
+
+        try {
+            mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+            eriText = mPhone.getCdmaEriText();
+        } catch (Exception ex){
+            Log.e(LOG_TAG, "onEnabled, error setting Cdma Eri Text: " + ex);
+        }
+
+        if (eriText == null) eriText = "ERI not available";
+
+        performUpdate(context,eriText);
+    }
+
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+        TelephonyManager mPhone;
+        String eriText = "ERI not init";
+
+        try {
+            mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+            eriText = mPhone.getCdmaEriText();
+        } catch (Exception ex){
+            Log.e(LOG_TAG, "onEnabled, error setting Cdma Eri Text: " + ex);
+        }
+
+        if (eriText == null) eriText = "ERI not available";
+
+        performUpdate(context,eriText);
+    }
+
+    void performUpdate(Context context, String eriText) {
+        final Resources res = context.getResources();
+        final RemoteViews views = new RemoteViews(context.getPackageName(),
+            R.layout.eri_text_layout);
+
+        views.setTextViewText(R.id.message, eriText);
+
+        AppWidgetManager manager = AppWidgetManager.getInstance(context);
+        manager.updateAppWidget(THIS_APPWIDGET, views);
+
+    }
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index b724ad0..b12f7df
@@ -66,6 +66,8 @@ class InCallMenu {
     InCallMenuItemView mHold;
     InCallMenuItemView mAnswerAndHold;
     InCallMenuItemView mAnswerAndEnd;
+    InCallMenuItemView mAnswer;
+    InCallMenuItemView mIgnore;
 
     InCallMenu(InCallScreen inCallScreen) {
         if (DBG) log("InCallMenu constructor...");
@@ -185,6 +187,16 @@ class InCallMenu {
         mAnswerAndEnd.setOnClickListener(mInCallScreen);
         mAnswerAndEnd.setText(R.string.menu_answerAndEnd);
 
+        mAnswer = new InCallMenuItemView(wrappedContext);
+        mAnswer.setId(R.id.menuAnswer);
+        mAnswer.setOnClickListener(mInCallScreen);
+        mAnswer.setText(R.string.menu_answer);
+
+        mIgnore = new InCallMenuItemView(wrappedContext);
+        mIgnore.setId(R.id.menuIgnore);
+        mIgnore.setOnClickListener(mInCallScreen);
+        mIgnore.setText(R.string.menu_ignore);
+
         //
         // Load all the items into the correct "slots" in the InCallMenuView.
         //
@@ -201,7 +213,11 @@ class InCallMenu {
         // Row 0:
         // This usually has "Show/Hide dialpad", but that gets replaced by
         // "Manage conference" if a conference call is active.
-        mInCallMenuView.addItemView(mManageConference, 0);
+        PhoneApp app = PhoneApp.getInstance();
+        // As managing conference is only valid for GSM and not for CDMA
+        if (app.phone.getPhoneName().equals("GSM")) {
+            mInCallMenuView.addItemView(mManageConference, 0);
+        }
         mInCallMenuView.addItemView(mShowDialpad, 0);
 
         // Row 1:
@@ -213,12 +229,18 @@ class InCallMenu {
         // Row 2:
         // In this row we see *either*  bluetooth/speaker/mute/hold
         // *or* answerAndHold/answerAndEnd, but never all 6 together.
-        mInCallMenuView.addItemView(mHold, 2);
+        // For CDMA only Answer or Ignore option is valid for a Call Waiting scenario
+        if (app.phone.getPhoneName().equals("CDMA")) {
+            mInCallMenuView.addItemView(mAnswer, 2);
+            mInCallMenuView.addItemView(mIgnore, 2);
+        } else {
+            mInCallMenuView.addItemView(mHold, 2);
+            mInCallMenuView.addItemView(mAnswerAndHold, 2);
+            mInCallMenuView.addItemView(mAnswerAndEnd, 2);
+        }
         mInCallMenuView.addItemView(mMute, 2);
         mInCallMenuView.addItemView(mSpeaker, 2);
         mInCallMenuView.addItemView(mBluetooth, 2);
-        mInCallMenuView.addItemView(mAnswerAndHold, 2);
-        mInCallMenuView.addItemView(mAnswerAndEnd, 2);
 
         mInCallMenuView.dumpState();
     }
@@ -257,12 +279,29 @@ class InCallMenu {
             // TODO: be sure to test this for "only one line in use and it's
             // active" AND for "only one line in use and it's on hold".
             if (hasActiveCall && !hasHoldingCall) {
-                mAnswerAndHold.setVisible(true);
-                mAnswerAndHold.setEnabled(true);
-                mAnswerAndEnd.setVisible(true);
-                mAnswerAndEnd.setEnabled(true);
+                // For CDMA only make "Answer" and "Ignore" visible
+                if (phone.getPhoneName().equals("CDMA")) {
+                    mAnswer.setVisible(true);
+                    mAnswer.setEnabled(true);
+                    mIgnore.setVisible(true);
+                    mIgnore.setEnabled(true);
+
+                    // Explicitly remove GSM menu items
+                    mAnswerAndHold.setVisible(false);
+                    mAnswerAndEnd.setVisible(false);
+                } else {
+                    mAnswerAndHold.setVisible(true);
+                    mAnswerAndHold.setEnabled(true);
+                    mAnswerAndEnd.setVisible(true);
+                    mAnswerAndEnd.setEnabled(true);
+
+                    // Explicitly remove CDMA menu items
+                    mAnswer.setVisible(false);
+                    mIgnore.setVisible(false);
+
+                    mManageConference.setVisible(false);
+                }
 
-                mManageConference.setVisible(false);
                 mShowDialpad.setVisible(false);
                 mEndCall.setVisible(false);
                 mAddCall.setVisible(false);
@@ -371,6 +410,13 @@ class InCallMenu {
         mHold.setIndicatorState(onHold);
         mHold.setEnabled(canHold);
 
+        // In CDMA "Answer" and "Ignore" are only useful
+        // when there's an incoming ringing call (Callwaiting)
+        mAnswer.setVisible(false);
+        mAnswer.setEnabled(false);
+        mIgnore.setVisible(false);
+        mIgnore.setEnabled(false);
+
         // "Answer & end" and "Answer & hold" are only useful
         // when there's an incoming ringing call (see above.)
         mAnswerAndHold.setVisible(false);
old mode 100644 (file)
new mode 100755 (executable)
index bce7625..88e7fbc
@@ -43,6 +43,8 @@ import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.provider.CallLog;
+import android.provider.CallLog.Calls;
 import android.provider.Checkin;
 import android.provider.Settings;
 import android.telephony.PhoneNumberUtils;
@@ -56,6 +58,7 @@ import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.animation.Animation;
@@ -121,6 +124,9 @@ public class InCallScreen extends Activity
     // The "touch lock" overlay timeout comes from Gservices; this is the default.
     private static final int TOUCH_LOCK_DELAY_DEFAULT =  6000;  // msec
 
+    // Amount of time for Displaying "Dialing" for 3way Calling origination
+    private static final int THREEWAY_CALLERINFO_DISPLAY_TIME = 2000; // msec
+
     // See CallTracker.MAX_CONNECTIONS_PER_CALL
     private static final int MAX_CALLERS_IN_CONFERENCE = 5;
 
@@ -139,6 +145,8 @@ public class InCallScreen extends Activity
     private static final int ALLOW_SCREEN_ON = 112;
     private static final int TOUCH_LOCK_TIMER = 113;
     private static final int BLUETOOTH_STATE_CHANGED = 114;
+    private static final int PHONE_CDMA_CALL_WAITING = 115;
+    private static final int THREEWAY_CALLERINFO_DISPLAY_DONE = 116;
 
 
     // High-level "modes" of the in-call UI.
@@ -222,6 +230,11 @@ public class InCallScreen extends Activity
     private Animation mTouchLockFadeIn;
     private long mTouchLockLastTouchTime;  // in SystemClock.uptimeMillis() time base
 
+    // Onscreen "answer" UI, for devices with no hardware CALL button.
+    private View mOnscreenAnswerUiContainer;  // The container for the whole UI, or null if unused
+    private View mOnscreenAnswerButton;  // The "answer" button itself
+    private long mOnscreenAnswerButtonLastTouchTime;  // in SystemClock.uptimeMillis() time base
+
     // Various dialogs we bring up (see dismissAllDialogs())
     // The MMI started dialog can actually be one of 2 items:
     //   1. An alert dialog if the MMI code is a normal MMI
@@ -264,6 +277,7 @@ public class InCallScreen extends Activity
                 // foreground...
             }
 
+            PhoneApp app = PhoneApp.getInstance();
             switch (msg.what) {
                 case SUPP_SERVICE_FAILED:
                     onSuppServiceFailed((AsyncResult) msg.obj);
@@ -315,7 +329,7 @@ public class InCallScreen extends Activity
                     MmiCode mmiCode = (MmiCode) ((AsyncResult) msg.obj).result;
                     // if phone is a CDMA phone display feature code completed message
                     if (mPhone.getPhoneName().equals("CDMA")) {
-                        PhoneUtils.displayMMIComplete(mPhone, PhoneApp.getInstance(), mmiCode, null, null);
+                        PhoneUtils.displayMMIComplete(mPhone, app, mmiCode, null, null);
                     } else {
                         if (mmiCode.getState() != MmiCode.State.PENDING) {
                             if (DBG) log("Got MMI_COMPLETE, finishing...");
@@ -351,7 +365,7 @@ public class InCallScreen extends Activity
                     // (Note this will cause the screen to turn on
                     // immediately, if it's currently off because of a
                     // prior preventScreenOn(true) call.)
-                    PhoneApp.getInstance().preventScreenOn(false);
+                    app.preventScreenOn(false);
                     break;
 
                 case TOUCH_LOCK_TIMER:
@@ -368,6 +382,31 @@ public class InCallScreen extends Activity
                     // directly from PhoneApp.showBluetoothIndication().)
                     updateScreen();
                     break;
+
+                case PHONE_CDMA_CALL_WAITING:
+                    if (DBG) log("Received PHONE_CDMA_CALL_WAITING event ...");
+                    Connection cn = mRingingCall.getLatestConnection();
+
+                    // Only proceed if we get a valid connection object
+                    if (cn != null) {
+                        // Finally update screen with Call waiting info and request
+                        // screen to wake up
+                        updateScreen();
+                        app.updateWakeState();
+                    }
+                    break;
+
+                case THREEWAY_CALLERINFO_DISPLAY_DONE:
+                    if (DBG) log("Received THREEWAY_CALLERINFO_DISPLAY_DONE event ...");
+                    if (app.cdmaPhoneCallState.getCurrentCallState()
+                            == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
+                        // Set the mThreeWayCallOrigStateDialing state to true
+                        app.cdmaPhoneCallState.setThreeWayCallOrigState(false);
+
+                        //Finally update screen with with the current on going call
+                        updateScreen();
+                    }
+                    break;
             }
         }
     };
@@ -675,7 +714,7 @@ public class InCallScreen extends Activity
         // the same time that the phone state is changing.  This can
         // end up causing the sleep request to be ignored.
         if (mHandler.hasMessages(DELAYED_CLEANUP_AFTER_DISCONNECT)) {
-            if (DBG) log("onPause(): DELAYED_CLEANUP_AFTER_DISCONNECT detected, finishing...");
+            if (DBG) log("DELAYED_CLEANUP_AFTER_DISCONNECT detected, moving UI to background.");
             finish();
         }
 
@@ -820,14 +859,19 @@ public class InCallScreen extends Activity
         if (!mRegisteredForPhoneStates) {
             mPhone.registerForPhoneStateChanged(mHandler, PHONE_STATE_CHANGED, null);
             mPhone.registerForDisconnect(mHandler, PHONE_DISCONNECT, null);
-            mPhone.registerForMmiInitiate(mHandler, PhoneApp.MMI_INITIATE, null);
-
-            // register for the MMI complete message.  Upon completion,
-            // PhoneUtils will bring up a system dialog instead of the
-            // message display class in PhoneUtils.displayMMIComplete().
-            // We'll listen for that message too, so that we can finish
-            // the activity at the same time.
-            mPhone.registerForMmiComplete(mHandler, PhoneApp.MMI_COMPLETE, null);
+            if (mPhone.getPhoneName().equals("GSM")) {
+                mPhone.registerForMmiInitiate(mHandler, PhoneApp.MMI_INITIATE, null);
+
+                // register for the MMI complete message.  Upon completion,
+                // PhoneUtils will bring up a system dialog instead of the
+                // message display class in PhoneUtils.displayMMIComplete().
+                // We'll listen for that message too, so that we can finish
+                // the activity at the same time.
+                mPhone.registerForMmiComplete(mHandler, PhoneApp.MMI_COMPLETE, null);
+            } else { // CDMA
+                if (DBG) log("Registering for Call Waiting.");
+                mPhone.registerForCallWaiting(mHandler, PHONE_CDMA_CALL_WAITING, null);
+            }
 
             mPhone.setOnPostDialCharacter(mHandler, POST_ON_DIAL_CHARS, null);
             mPhone.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);
@@ -839,10 +883,20 @@ public class InCallScreen extends Activity
         mPhone.unregisterForPhoneStateChanged(mHandler);
         mPhone.unregisterForDisconnect(mHandler);
         mPhone.unregisterForMmiInitiate(mHandler);
+        mPhone.unregisterForCallWaiting(mHandler);
         mPhone.setOnPostDialCharacter(null, POST_ON_DIAL_CHARS, null);
         mRegisteredForPhoneStates = false;
     }
 
+    /* package */ void updateAfterRadioTechnologyChange() {
+        if (DBG) Log.d(LOG_TAG, "updateAfterRadioTechnologyChange()...");
+        // Unregister for all events from the old obsolete phone
+        unregisterForPhoneStates();
+
+        // (Re)register for all events relevant to the new active phone
+        registerForPhoneStates();
+    }
+
     @Override
     protected void onNewIntent(Intent intent) {
         if (DBG) log("onNewIntent: intent=" + intent);
@@ -951,11 +1005,13 @@ public class InCallScreen extends Activity
         mCallCard = (CallCard) callCardLayout.findViewById(R.id.callCard);
         if (VDBG) log("  - mCallCard = " + mCallCard);
         mCallCard.setInCallScreenInstance(this);
-        mCallCard.reset();
 
         // Menu Button hint
         mMenuButtonHint = (TextView) findViewById(R.id.menuButtonHint);
 
+        // Other platform-specific UI initialization.
+        initOnscreenAnswerUi();
+
         // Make any final updates to our View hierarchy that depend on the
         // current configuration.
         ConfigurationHelper.applyConfigurationToLayout(this);
@@ -1038,20 +1094,31 @@ public class InCallScreen extends Activity
         final boolean hasHoldingCall = !mBackgroundCall.isIdle();
 
         if (mPhone.getPhoneName().equals("CDMA")) {
-            // WINK:TODO Teleca is this enough?
-
             // The green CALL button means either "Answer", "Swap calls/On Hold", or
             // "Add to 3WC", depending on the current state of the Phone.
 
+            PhoneApp app = PhoneApp.getInstance();
+            CdmaPhoneCallState.PhoneCallState currCallState =
+                app.cdmaPhoneCallState.getCurrentCallState();
             if (hasRingingCall) {
-                if (VDBG) log("handleCallKey: ringing ==> answer!");
+                //Scenario 1: Accepting the First Incoming and Call Waiting call
+                if (DBG) log("answerCall: First Incoming and Call Waiting scenario");
                 internalAnswerCall();  // Automatically holds the current active call,
                                        // if there is one
-            } else {
-                // send an empty CDMA flash string
+            } else if ((currCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE)
+                    && (hasActiveCall)) {
+                //Scenario 2: Merging 3Way calls
+                if (DBG) log("answerCall: Merge 3-way call scenario");
+                // Merge calls
+                PhoneUtils.mergeCalls(mPhone);
+            } else if (currCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
+                //Scenario 3: Switching between two Call waiting calls or drop the latest
+                // connection if in a 3Way merge scenario
+                if (DBG) log("answerCall: Switch btwn 2 calls scenario");
+                // Send flash cmd
                 PhoneUtils.switchHoldingAndActive(mPhone);
             }
-        } else {
+        } else { // GSM.
             if (hasRingingCall) {
                 // If an incoming call is ringing, the CALL button is actually
                 // handled by the PhoneWindowManager.  (We do this to make
@@ -1435,6 +1502,33 @@ public class InCallScreen extends Activity
         } else if (cause == Connection.DisconnectCause.CS_RESTRICTED_NORMAL) {
             showGenericErrorDialog(R.string.callFailed_dsac_restricted_normal, false);
             return;
+        } else if (cause == Connection.DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE) {
+            showGenericErrorDialog(R.string.callFailed_cdma_lockedUntilPowerCycle, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_DROP) {
+            showGenericErrorDialog(R.string.callFailed_cdma_drop, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_INTERCEPT) {
+            showGenericErrorDialog(R.string.callFailed_cdma_intercept, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_REORDER) {
+            showGenericErrorDialog(R.string.callFailed_cdma_reorder, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_SO_REJECT) {
+            showGenericErrorDialog(R.string.callFailed_cdma_SO_reject, false);
+            return;
+        }else if (cause == Connection.DisconnectCause.CDMA_RETRY_ORDER) {
+            showGenericErrorDialog(R.string.callFailed_cdma_retryOrder, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_ACCESS_FAILURE) {
+            showGenericErrorDialog(R.string.callFailed_cdma_accessFailure, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_PREEMPTED) {
+            showGenericErrorDialog(R.string.callFailed_cdma_preempted, false);
+            return;
+        } else if (cause == Connection.DisconnectCause.CDMA_NOT_EMERGENCY) {
+            showGenericErrorDialog(R.string.callFailed_cdma_notEmergency, false);
+            return;
         }
 
         final PhoneApp app = PhoneApp.getInstance();
@@ -1573,6 +1667,9 @@ public class InCallScreen extends Activity
             mHandler.sendEmptyMessageDelayed(DELAYED_CLEANUP_AFTER_DISCONNECT,
                                              callEndedDisplayDelay);
         }
+
+        // Remove 3way timer (only meaningful for CDMA)
+        mHandler.removeMessages(THREEWAY_CALLERINFO_DISPLAY_DONE);
     }
 
     /**
@@ -1835,6 +1932,7 @@ public class InCallScreen extends Activity
         if (VDBG) log("- updateScreen: updating the in-call UI...");
         mCallCard.updateState(mPhone);
         updateDialpadVisibility();
+        updateOnscreenAnswerUi();
         updateMenuButtonHint();
     }
 
@@ -1859,6 +1957,7 @@ public class InCallScreen extends Activity
         // this screen in the first place.)
 
         // Need to treat running MMI codes as a connection as well.
+        // Do not check for getPendingMmiCodes when phone is a CDMA phone
         if (!mForegroundCall.isIdle() || !mBackgroundCall.isIdle() || !mRingingCall.isIdle()
             || mPhone.getPhoneName().equals("CDMA") || !mPhone.getPendingMmiCodes().isEmpty()) {
             if (VDBG) log("syncWithPhoneState: it's ok to be here; update the screen...");
@@ -2001,6 +2100,26 @@ public class InCallScreen extends Activity
                 // onPhoneStateChanged().
                 mDialer.clearDigits();
 
+                PhoneApp app = PhoneApp.getInstance();
+                if (app.phone.getPhoneName().equals("CDMA")) {
+                    // Start the 2 second timer for 3 Way CallerInfo
+                    if (app.cdmaPhoneCallState.getCurrentCallState()
+                            == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
+                        //Unmute for the second MO call
+                        PhoneUtils.setMuteInternal(mPhone, false);
+
+                        //Start the timer for displaying "Dialing" for second call
+                        Message msg = Message.obtain(mHandler, THREEWAY_CALLERINFO_DISPLAY_DONE);
+                        mHandler.sendMessageDelayed(msg, THREEWAY_CALLERINFO_DISPLAY_TIME);
+
+                        // Set the mThreeWayCallOrigStateDialing state to true
+                        app.cdmaPhoneCallState.setThreeWayCallOrigState(true);
+
+                        //Update screen to show 3way dialing
+                        updateScreen();
+                    }
+                }
+
                 return InCallInitStatus.SUCCESS;
             case PhoneUtils.CALL_STATUS_DIALED_MMI:
                 if (DBG) log("placeCall: specified number was an MMI code: '" + number + "'.");
@@ -2109,9 +2228,10 @@ public class InCallScreen extends Activity
             mMissingVoicemailDialog.dismiss();
             mMissingVoicemailDialog = null;
         }
-        if (DBG) log("show vm setting, finishing...");
         finish();
 
+        if (DBG) log("show vm setting");
+
         // navigate to the Voicemail setting in the Call Settings activity.
         Intent intent = new Intent(CallFeaturesSetting.ACTION_ADD_VOICEMAIL);
         intent.setClass(this, CallFeaturesSetting.class);
@@ -2158,7 +2278,6 @@ public class InCallScreen extends Activity
         // connections still in that state.]
         mPhone.clearDisconnected();
 
-        final PhoneApp app = PhoneApp.getInstance();
         if (!phoneIsInUse()) {
             // Phone is idle!  We should exit this screen now.
             if (DBG) log("- delayedCleanupAfterDisconnect: phone is idle...");
@@ -2227,6 +2346,17 @@ public class InCallScreen extends Activity
                 internalAnswerAndEnd();
                 break;
 
+            case R.id.menuAnswer:
+                if (DBG) log("onClick: Answer...");
+                internalAnswerCall();
+                break;
+
+            case R.id.menuIgnore:
+                if (DBG) log("onClick: Ignore...");
+                final CallNotifier notifier = PhoneApp.getInstance().notifier;
+                notifier.onCdmaCallWaitingReject();
+                break;
+
             case R.id.menuSwapCalls:
                 if (VDBG) log("onClick: SwapCalls...");
                 internalSwapCalls();
@@ -3237,6 +3367,58 @@ public class InCallScreen extends Activity
         return !ConfigurationHelper.isLandscape() && okToDialDTMFTones();
     }
 
+
+    /**
+     * Initializes the onscreen "answer" UI on devices that need it.
+     */
+    private void initOnscreenAnswerUi() {
+        // This UI is only used on devices with no hard CALL or SEND button.
+
+        // TODO: For now, explicitly enable this for sholes devices.
+        // (Note PRODUCT_DEVICE is "sholes" for both sholes and voles builds.)
+        boolean allowOnscreenAnswerUi =
+                "sholes".equals(SystemProperties.get("ro.product.device"));
+        //
+        // TODO: But ultimately we should either (a) use some framework API
+        // to detect whether the current device has a hard SEND button, or
+        // (b) have this depend on a product-specific resource flag in
+        // config.xml, like the forthcoming "is_full_touch_ui" boolean.
+
+        if (DBG) log("initOnscreenAnswerUi: device '" + SystemProperties.get("ro.product.device")
+                     + "', allowOnscreenAnswerUi = " + allowOnscreenAnswerUi);
+
+        if (allowOnscreenAnswerUi) {
+            ViewStub stub = (ViewStub) findViewById(R.id.onscreenAnswerUiStub);
+            mOnscreenAnswerUiContainer = stub.inflate();
+
+            mOnscreenAnswerButton = findViewById(R.id.onscreenAnswerButton);
+            mOnscreenAnswerButton.setOnTouchListener(this);
+        }
+    }
+
+    /**
+     * Updates the visibility of the onscreen "answer" UI.  On devices
+     * with no hardware CALL button, this UI becomes visible while an
+     * incoming call is ringing.
+     *
+     * TODO: This method should eventually be rolled into a more general
+     * method to update *all* onscreen UI elements that need to be
+     * different on different devices (depending on which hard buttons are
+     * present and/or if we don't have to worry about false touches while
+     * in-call.)
+     */
+    private void updateOnscreenAnswerUi() {
+        if (mOnscreenAnswerUiContainer != null) {
+            if (mPhone.getState() == Phone.State.RINGING) {
+                // A phone call is ringing *or* call waiting.
+                mOnscreenAnswerUiContainer.setVisibility(View.VISIBLE);
+            } else {
+                mOnscreenAnswerUiContainer.setVisibility(View.GONE);
+            }
+        }
+    }
+
+
     /**
      * Helper class to manage the (small number of) manual layout and UI
      * changes needed by the in-call UI when switching between landscape
@@ -3735,77 +3917,137 @@ public class InCallScreen extends Activity
     public boolean onTouch(View v, MotionEvent event) {
         if (VDBG) log ("onTouch(View " + v + ")...");
 
-        //
         // Handle touch events on the "touch lock" overlay.
-        // (v == mTouchLockIcon) means the user hit the lock icon in the
-        // middle of the screen, and (v == mTouchLockOverlay) is a touch
-        // anywhere else on the overlay.
-        //
+        if ((v == mTouchLockIcon) || (v == mTouchLockOverlay)) {
+
+            // TODO: move this big hunk of code to a helper function, or
+            // even better out to a separate helper class containing all
+            // the touch lock overlay code.
+
+            // We only care about these touches while the touch lock UI is
+            // visible (including the time during the fade-in animation.)
+            if (!isTouchLocked()) {
+                // Got an event from the touch lock UI, but we're not locked!
+                // (This was probably a touch-UP right after we unlocked.
+                // Ignore it.)
+                return false;
+            }
 
-        // We only care about touch events while the touch lock UI is
-        // visible (including the time during the fade-in animation.)
-        if (((v == mTouchLockIcon) || (v == mTouchLockOverlay)) && !isTouchLocked()) {
-            // Got an event from the touch lock UI, but we're not locked!
-            // (This was probably a touch-UP right after we unlocked.
-            // Ignore it.)
-            return false;
-        }
+            // (v == mTouchLockIcon) means the user hit the lock icon in the
+            // middle of the screen, and (v == mTouchLockOverlay) is a touch
+            // anywhere else on the overlay.
+
+            if (v == mTouchLockIcon) {
+                // Direct hit on the "lock" icon.  Handle the double-tap gesture.
+                if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                    long now = SystemClock.uptimeMillis();
+                    if (VDBG) log("- touch lock icon: handling a DOWN event, t = " + now);
+
+                    // Look for the double-tap gesture:
+                    if (now < mTouchLockLastTouchTime + ViewConfiguration.getDoubleTapTimeout()) {
+                        if (VDBG) log("==> touch lock icon: DOUBLE-TAP!");
+                        // This was the 2nd tap of a double-tap gesture.
+                        // Take down the touch lock overlay, but post a
+                        // message in the future to bring it back later.
+                        enableTouchLock(false);
+                        resetTouchLockTimer();
+                        // This counts as explicit "user activity".
+                        PhoneApp.getInstance().pokeUserActivity();
+                    }
+                } else if (event.getAction() == MotionEvent.ACTION_UP) {
+                    // Stash away the current time in case this is the first
+                    // tap of a double-tap gesture.  (We measure the time from
+                    // the first tap's UP to the second tap's DOWN.)
+                    mTouchLockLastTouchTime = SystemClock.uptimeMillis();
+                }
 
-        if (v == mTouchLockIcon) {
-            // Direct hit on the "lock" icon.  Handle the double-tap gesture.
+                // And regardless of what just happened, we *always* consume
+                // touch events while the touch lock UI is (or was) visible.
+                return true;
+
+            } else {  // (v == mTouchLockOverlay)
+                // User touched the "background" area of the touch lock overlay.
+
+                // TODO: If we're in the middle of the fade-in animation,
+                // consider making a touch *anywhere* immediately unlock the
+                // UI.  This could be risky, though, if the user tries to
+                // *double-tap* during the fade-in (in which case the 2nd tap
+                // might 't become a false touch on the dialpad!)
+                //
+                //if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                //    if (DBG) log("- touch lock overlay background: handling a DOWN event.");
+                //
+                //    if (mTouchLockFadeIn.hasStarted() && !mTouchLockFadeIn.hasEnded()) {
+                //        // If we're still fading-in, a touch *anywhere* onscreen
+                //        // immediately unlocks.
+                //        if (DBG) log("==> touch lock: tap during fade-in!");
+                //
+                //        mTouchLockOverlay.clearAnimation();
+                //        enableTouchLock(false);
+                //        // ...but post a message in the future to bring it
+                //        // back later.
+                //        resetTouchLockTimer();
+                //    }
+                //}
+
+                // And regardless of what just happened, we *always* consume
+                // touch events while the touch lock UI is (or was) visible.
+                return true;
+            }
+
+        // Handle touch events on the onscreen "answer" button.
+        } else if (v == mOnscreenAnswerButton) {
+
+            // TODO: this "double-tap detection" code is also duplicated
+            // above (for mTouchLockIcon).  Instead, extract it out to a
+            // helper class that can listen for double-taps on an
+            // arbitrary View, or maybe even a whole new "DoubleTapButton"
+            // widget.
+
+            // Look for the double-tap gesture.
             if (event.getAction() == MotionEvent.ACTION_DOWN) {
                 long now = SystemClock.uptimeMillis();
-                if (VDBG) log("- touch lock icon: handling a DOWN event, t = " + now);
+                if (DBG) log("- onscreen answer button: handling a DOWN event, t = " + now);  // foo -- VDBG
 
                 // Look for the double-tap gesture:
-                if (now < mTouchLockLastTouchTime + ViewConfiguration.getDoubleTapTimeout()) {
-                    if (VDBG) log("==> touch lock icon: DOUBLE-TAP!");
-                    // This was the 2nd tap of a double-tap gesture.
-                    // Take down the touch lock overlay, but post a
-                    // message in the future to bring it back later.
-                    enableTouchLock(false);
-                    resetTouchLockTimer();
-                    // This counts as explicit "user activity".
-                    PhoneApp.getInstance().pokeUserActivity();
+                if (now < mOnscreenAnswerButtonLastTouchTime + ViewConfiguration.getDoubleTapTimeout()) {
+                    if (DBG) log("==> onscreen answer button: DOUBLE-TAP!");
+                    // This was the 2nd tap of the double-tap gesture: answer the call!
+
+                    final boolean hasRingingCall = !mRingingCall.isIdle();
+                    if (hasRingingCall) {
+                        final boolean hasActiveCall = !mForegroundCall.isIdle();
+                        final boolean hasHoldingCall = !mBackgroundCall.isIdle();
+                        if (hasActiveCall && hasHoldingCall) {
+                            if (DBG) log("onscreen answer button: ringing (both lines in use) ==> answer!");
+                            internalAnswerCallBothLinesInUse();
+                        } else {
+                            if (DBG) log("onscreen answer button: ringing ==> answer!");
+                            internalAnswerCall();  // Automatically holds the current active call,
+                                                   // if there is one
+                        }
+                    } else {
+                        // The ringing call presumably stopped just when
+                        // the user was double-tapping.
+                        if (DBG) log("onscreen answer button: no ringing call (any more); ignoring...");
+                    }
                 }
+                // The onscreen "answer" button will go away as soon as
+                // the phone goes from ringing to offhook, since that
+                // state change will trigger an updateScreen() call.
+                // TODO: consider explicitly starting some fancier
+                // animation here, like fading out the "answer" button, or
+                // sliding it offscreen...
+
             } else if (event.getAction() == MotionEvent.ACTION_UP) {
                 // Stash away the current time in case this is the first
                 // tap of a double-tap gesture.  (We measure the time from
                 // the first tap's UP to the second tap's DOWN.)
-                mTouchLockLastTouchTime = SystemClock.uptimeMillis();
+                mOnscreenAnswerButtonLastTouchTime = SystemClock.uptimeMillis();
             }
 
-            // And regardless of what just happened, we *always* consume
-            // touch events while the touch lock UI is (or was) visible.
-            return true;
-
-        } else if (v == mTouchLockOverlay) {
-            // User touched the "background" area of the touch lock overlay.
-
-            // TODO: If we're in the middle of the fade-in animation,
-            // consider making a touch *anywhere* immediately unlock the
-            // UI.  This could be risky, though, if the user tries to
-            // *double-tap* during the fade-in (in which case the 2nd tap
-            // might 't become a false touch on the dialpad!)
-            //
-            //if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            //    if (DBG) log("- touch lock overlay background: handling a DOWN event.");
-            //
-            //    if (mTouchLockFadeIn.hasStarted() && !mTouchLockFadeIn.hasEnded()) {
-            //        // If we're still fading-in, a touch *anywhere* onscreen
-            //        // immediately unlocks.
-            //        if (DBG) log("==> touch lock: tap during fade-in!");
-            //
-            //        mTouchLockOverlay.clearAnimation();
-            //        enableTouchLock(false);
-            //        // ...but post a message in the future to bring it
-            //        // back later.
-            //        resetTouchLockTimer();
-            //    }
-            //}
-
-            // And regardless of what just happened, we *always* consume
-            // touch events while the touch lock UI is (or was) visible.
+            // And regardless of what just happened, we *always*
+            // consume touch events to this button.
             return true;
 
         } else {
index e68ab8c..67d719b 100644 (file)
@@ -39,6 +39,7 @@ import android.util.Log;
 import android.widget.RemoteViews;
 import android.widget.Toast;
 
+import com.android.internal.R.drawable;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
@@ -90,6 +91,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
     static final int VOICEMAIL_NOTIFICATION = 5;
     static final int CALL_FORWARD_NOTIFICATION = 6;
     static final int DATA_DISCONNECTED_ROAMING_NOTIFICATION = 7;
+    static final int ECBM_NOTIFICATION = 8;
 
     private static NotificationMgr sMe = null;
     private Phone mPhone;
@@ -134,7 +136,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
 
     static void init(Context context) {
         sMe = new NotificationMgr(context);
-        
+
         // update the notifications that need to be touched at startup.
         sMe.updateNotifications();
     }
@@ -149,9 +151,9 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
      * the Status bar.  All interaction with the status bar should be
      * though the methods contained herein.
      */
-    
-    /** 
-     * Factory method 
+
+    /**
+     * Factory method
      */
     StatusBarMgr getStatusBarMgr() {
         if (mStatusBarMgr == null) {
@@ -159,23 +161,23 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         }
         return mStatusBarMgr;
     }
-    
+
     /**
      * StatusBarMgr implementation
-     */ 
+     */
     class StatusBarMgr {
         // current settings
         private boolean mIsNotificationEnabled = true;
         private boolean mIsExpandedViewEnabled = true;
-        
+
         private StatusBarMgr () {
         }
-        
+
         /**
-         * Sets the notification state (enable / disable 
+         * Sets the notification state (enable / disable
          * vibrating notifications) for the status bar,
          * updates the status bar service if there is a change.
-         * Independent of the remaining Status Bar 
+         * Independent of the remaining Status Bar
          * functionality, including icons and expanded view.
          */
         void enableNotificationAlerts(boolean enable) {
@@ -184,12 +186,12 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
                 updateStatusBar();
             }
         }
-        
+
         /**
-         * Sets the ability to expand the notifications for the 
-         * status bar, updates the status bar service if there 
-         * is a change. Independent of the remaining Status Bar 
-         * functionality, including icons and notification 
+         * Sets the ability to expand the notifications for the
+         * status bar, updates the status bar service if there
+         * is a change. Independent of the remaining Status Bar
+         * functionality, including icons and notification
          * alerts.
          */
         void enableExpandedView(boolean enable) {
@@ -198,28 +200,28 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
                 updateStatusBar();
             }
         }
-        
+
         /**
-         * Method to synchronize status bar state with our current 
+         * Method to synchronize status bar state with our current
          * state.
          */
         void updateStatusBar() {
             int state = StatusBarManager.DISABLE_NONE;
-            
+
             if (!mIsExpandedViewEnabled) {
                 state |= StatusBarManager.DISABLE_EXPAND;
             }
-            
+
             if (!mIsNotificationEnabled) {
                 state |= StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
             }
-            
+
             // send the message to the status bar manager.
             if (DBG) log("updating status bar state: " + state);
             mStatusBar.disable(state);
         }
     }
-    
+
     /**
      * Makes sure notifications are up to date.
      */
@@ -233,11 +235,11 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         StringBuilder where = new StringBuilder("type=");
         where.append(Calls.MISSED_TYPE);
         where.append(" AND new=1");
-        
+
         // start the query
         mQueryHandler.startQuery(CALL_LOG_TOKEN, null, Calls.CONTENT_URI,  CALL_LOG_PROJECTION,
                 where.toString(), null, Calls.DEFAULT_SORT_ORDER);
-        
+
         // synchronize the in call notification
         if (mPhone.getState() != Phone.State.OFFHOOK) {
             if (DBG) log("Phone is idle, canceling notification.");
@@ -246,27 +248,27 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             if (DBG) log("Phone is offhook, updating notification.");
             updateInCallNotification();
         }
-        
+
         // Depend on android.app.StatusBarManager to be set to
         // disable(DISABLE_NONE) upon startup.  This will be the
         // case even if the phone app crashes.
     }
-    
+
     /** The projection to use when querying the phones table */
     static final String[] PHONES_PROJECTION = new String[] {
             Phones.NUMBER,
             Phones.NAME
     };
-    
+
     /**
      * Class used to run asynchronous queries to re-populate
      * the notifications we care about.
      */
     private class QueryHandler extends AsyncQueryHandler {
-        
+
         /**
-         * Used to store relevant fields for the Missed Call 
-         * notifications. 
+         * Used to store relevant fields for the Missed Call
+         * notifications.
          */
         private class NotificationInfo {
             public String name;
@@ -274,7 +276,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             public String label;
             public long date;
         }
-        
+
         public QueryHandler(ContentResolver cr) {
             super(cr);
         }
@@ -283,63 +285,63 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
          * Handles the query results.  There are really 2 steps to this,
          * similar to what happens in RecentCallsListActivity.
          *  1. Find the list of missed calls
-         *  2. For each call, run a query to retrieve the caller's name. 
+         *  2. For each call, run a query to retrieve the caller's name.
          */
         @Override
         protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
             // TODO: it would be faster to use a join here, but for the purposes
             // of this small record set, it should be ok.
-            
-            // Note that CursorJoiner is not useable here because the number 
-            // comparisons are not strictly equals; the comparisons happen in 
-            // the SQL function PHONE_NUMBERS_EQUAL, which is not available for 
+
+            // Note that CursorJoiner is not useable here because the number
+            // comparisons are not strictly equals; the comparisons happen in
+            // the SQL function PHONE_NUMBERS_EQUAL, which is not available for
             // the CursorJoiner.
-            
+
             // Executing our own query is also feasible (with a join), but that
             // will require some work (possibly destabilizing) in Contacts
             // Provider.
-            
+
             // At this point, we will execute subqueries on each row just as
             // RecentCallsListActivity.java does.
             switch (token) {
                 case CALL_LOG_TOKEN:
                     if (DBG) log("call log query complete.");
-                    
+
                     // initial call to retrieve the call list.
                     if (cursor != null) {
                         while (cursor.moveToNext()) {
-                            // for each call in the call log list, create 
+                            // for each call in the call log list, create
                             // the notification object and query contacts
                             NotificationInfo n = getNotificationInfo (cursor);
-                            
+
                             if (DBG) log("query contacts for number: " + n.number);
-                            
-                            mQueryHandler.startQuery(CONTACT_TOKEN, n, 
-                                    Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, n.number), 
+
+                            mQueryHandler.startQuery(CONTACT_TOKEN, n,
+                                    Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, n.number),
                                     PHONES_PROJECTION, null, null, Phones.DEFAULT_SORT_ORDER);
                         }
-                        
+
                         if (DBG) log("closing call log cursor.");
                         cursor.close();
                     }
                     break;
                 case CONTACT_TOKEN:
                     if (DBG) log("contact query complete.");
-                    
+
                     // subqueries to get the caller name.
                     if ((cursor != null) && (cookie != null)){
                         NotificationInfo n = (NotificationInfo) cookie;
-                        
+
                         if (cursor.moveToFirst()) {
                             // we have contacts data, get the name.
                             if (DBG) log("contact :" + n.name + " found for phone: " + n.number);
                             n.name = cursor.getString(cursor.getColumnIndexOrThrow(Phones.NAME));
                         }
-                        
+
                         // send the notification
                         if (DBG) log("sending notification.");
                         notifyMissedCall(n.name, n.number, n.label, n.date);
-                        
+
                         if (DBG) log("closing contact cursor.");
                         cursor.close();
                     }
@@ -347,10 +349,10 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
                 default:
             }
         }
-        
+
         /**
          * Factory method to generate a NotificationInfo object given a
-         * cursor from the call log table. 
+         * cursor from the call log table.
          */
         private final NotificationInfo getNotificationInfo(Cursor cursor) {
             NotificationInfo n = new NotificationInfo();
@@ -358,23 +360,23 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             n.number = cursor.getString(cursor.getColumnIndexOrThrow(Calls.NUMBER));
             n.label = cursor.getString(cursor.getColumnIndexOrThrow(Calls.TYPE));
             n.date = cursor.getLong(cursor.getColumnIndexOrThrow(Calls.DATE));
-            
+
             // make sure we update the number depending upon saved values in
             // CallLog.addCall().  If either special values for unknown or
             // private number are detected, we need to hand off the message
             // to the missed call notification.
-            if ( (n.number.equals(CallerInfo.UNKNOWN_NUMBER)) || 
+            if ( (n.number.equals(CallerInfo.UNKNOWN_NUMBER)) ||
                  (n.number.equals(CallerInfo.PRIVATE_NUMBER)) ||
                  (n.number.equals(CallerInfo.PAYPHONE_NUMBER)) ) {
                 n.number = null;
             }
-            
+
             if (DBG) log("NotificationInfo constructed for number: " + n.number);
 
             return n;
         }
     }
-    
+
     /**
      * Displays a notification about a missed call.
      *
@@ -386,7 +388,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         int titleResId;
         // the text in the notification's line 1 and 2.
         String expandedText, callName;
-        
+
         // increment number of missed calls.
         mNumberMissedCalls++;
 
@@ -400,7 +402,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             // use "unknown" if the caller is unidentifiable.
             callName = mContext.getString(R.string.unknown);
         }
-        
+
         // display the first line of the notification:
         // 1 missed call: call name
         // more than 1 missed call: <number of calls> + "missed calls"
@@ -409,13 +411,13 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             expandedText = callName;
         } else {
             titleResId = R.string.notification_missedCallsTitle;
-            expandedText = mContext.getString(R.string.notification_missedCallsMsg, 
+            expandedText = mContext.getString(R.string.notification_missedCallsMsg,
                     mNumberMissedCalls);
         }
-        
+
         // create the target call log intent
         final Intent intent = PhoneApp.createCallLogIntent();
-        
+
         // make the notification
         mNotificationMgr.notify(
                 MISSED_CALL_NOTIFICATION,
@@ -437,6 +439,49 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         mNotificationMgr.cancel(MISSED_CALL_NOTIFICATION);
     }
 
+    /**
+     * Displays a notification for Emergency Callback Mode.
+     *
+     * @param nameOrNumber either the contact name, or the phone number if no contact
+     * @param label the label of the number if nameOrNumber is a name, null if it is a number
+     */
+    void notifyECBM() {
+        // The details of our message
+        CharSequence message = "Emergency Callback Mode is active";
+
+        // look up the notification manager service
+        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
+        // The PendingIntent to launch our activity if the user selects this notification
+        Intent EmcbAlarm = new Intent(Intent.ACTION_MAIN, null);
+        EmcbAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        EmcbAlarm.setClassName("com.android.phone", EmergencyCallbackMode.class.getName());
+
+        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0,
+                EmcbAlarm, 0);
+
+        // The ticker text, this uses a formatted string so our message could be localized
+        String tickerText = mContext.getString(R.string.ecbm_mode_text, message);
+
+        // construct the Notification object.
+         Notification ecbmNotif = new Notification(com.android.internal.R.drawable.stat_ecb_mode,
+                 tickerText, System.currentTimeMillis());
+
+        // Set the info for the views that show in the notification panel.
+        ecbmNotif.setLatestEventInfo(mContext, null, message, contentIntent);
+
+        // Note that we use R.layout.incoming_message_panel as the ID for
+        // the notification.  It could be any integer you want, but we use
+        // the convention of using a resource id for a string related to
+        // the notification.  It will always be a unique number within your
+        // application.
+        mNotificationMgr.notify(ECBM_NOTIFICATION, ecbmNotif);
+    }
+
+    void cancelEcbmNotification() {
+        mNotificationMgr.cancel(ECBM_NOTIFICATION);
+    }
+
     void notifySpeakerphone() {
         if (mSpeakerphoneIcon == null) {
             mSpeakerphoneIcon = mStatusBar.addIcon("speakerphone",
@@ -494,8 +539,11 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         }
     }
 
+    void updateInCallNotification() {
+        updateInCallNotification(false);
+    }
+
     private void updateInCallNotification(boolean enhancedVoicePrivacy) {
-        // WINK:TODO: Teleca, what is the correct code here.
         int resId;
         if (DBG) log("updateInCallNotification()...");
 
@@ -519,11 +567,17 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             }
         } else if (PhoneApp.getInstance().showBluetoothIndication()) {
             // Bluetooth is active.
-            resId = com.android.internal.R.drawable.stat_sys_phone_call_bluetooth;
-        } else if (enhancedVoicePrivacy) {
-            resId = android.R.drawable.stat_sys_vp_phone_call;
+            if (enhancedVoicePrivacy) {
+                resId = com.android.internal.R.drawable.stat_sys_vp_phone_call_bluetooth;
+            } else {
+                resId = com.android.internal.R.drawable.stat_sys_phone_call_bluetooth;
+            }
         } else {
-            resId = android.R.drawable.stat_sys_phone_call;
+            if (enhancedVoicePrivacy) {
+                resId = android.R.drawable.stat_sys_vp_phone_call;
+            } else {
+                resId = android.R.drawable.stat_sys_phone_call;
+            }
         }
 
         // Note we can't just bail out now if (resId == mInCallResId),
@@ -567,7 +621,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         RemoteViews contentView = new RemoteViews(mContext.getPackageName(),
                                                    R.layout.ongoing_call_notification);
         contentView.setImageViewResource(R.id.icon, expandedViewIcon);
-        
+
         // if the connection is valid, then build what we need for the
         // first line of notification information, and start the chronometer.
         // Otherwise, don't bother and just stick with line 2.
@@ -599,7 +653,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             }
 
             if (DBG) log("- Updating expanded view: line 1 '" + expandedViewLine1 + "'");
-    
+
             // Text line #1 is actually a Chronometer, not a plain TextView.
             // We format the elapsed time of the current call into a line like
             // "Ongoing call (01:23)".
@@ -610,26 +664,26 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         } else if (DBG) {
             log("updateInCallNotification: connection is null, call status not updated.");
         }
-        
-        // display conference call string if this call is a conference 
+
+        // display conference call string if this call is a conference
         // call, otherwise display the connection information.
-        
-        // TODO: it may not make sense for every point to make separate 
+
+        // TODO: it may not make sense for every point to make separate
         // checks for isConferenceCall, so we need to think about
         // possibly including this in startGetCallerInfo or some other
         // common point.
-        String expandedViewLine2 = ""; 
+        String expandedViewLine2 = "";
         if (PhoneUtils.isConferenceCall(currentCall)) {
             // if this is a conference call, just use that as the caller name.
             expandedViewLine2 = mContext.getString(R.string.card_title_conf_call);
         } else {
             // Start asynchronous call to get the compact name.
-            PhoneUtils.CallerInfoToken cit = 
+            PhoneUtils.CallerInfoToken cit =
                 PhoneUtils.startGetCallerInfo (mContext, currentCall, this, contentView);
             // Line 2 of the expanded view (smaller text):
             expandedViewLine2 = PhoneUtils.getCompactNameFromCallerInfo(cit.currentInfo, mContext);
         }
-        
+
         if (DBG) log("- Updating expanded view: line 2 '" + expandedViewLine2 + "'");
         contentView.setTextViewText(R.id.text2, expandedViewLine2);
         notification.contentView = contentView;
@@ -651,18 +705,14 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
         updateMuteNotification();
     }
 
-    void updateInCallNotification() {
-        updateInCallNotification(false);
-    }
-
     /**
      * Implemented for CallerInfoAsyncQuery.OnQueryCompleteListener interface.
-     * refreshes the contentView when called. 
+     * refreshes the contentView when called.
      */
     public void onQueryComplete(int token, Object cookie, CallerInfo ci){
         if (DBG) log("callerinfo query complete, updating ui.");
 
-        ((RemoteViews) cookie).setTextViewText(R.id.text2, 
+        ((RemoteViews) cookie).setTextViewText(R.id.text2,
                 PhoneUtils.getCompactNameFromCallerInfo(ci, mContext));
     }
 
@@ -695,7 +745,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             int resId = android.R.drawable.stat_notify_voicemail;
 
             // This Notification can get a lot fancier once we have more
-            // information about the current voicemail messages. 
+            // information about the current voicemail messages.
             // (For example, the current voicemail system can't tell
             // us the caller-id or timestamp of a message, or tell us the
             // message count.)
@@ -750,6 +800,12 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
                 }
             }
 
+            if (mPhone.getPhoneName().equals("CDMA")) {
+                int vmCount = mPhone.getVoiceMessageCount();
+                String titleFormat = mContext.getString(R.string.notification_voicemail_title_count);
+                notificationTitle = String.format(titleFormat, vmCount);
+            }
+
             String notificationText;
             if (TextUtils.isEmpty(vmNumber)) {
                 notificationText = mContext.getString(
@@ -763,7 +819,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             Intent intent = new Intent(Intent.ACTION_CALL,
                     Uri.fromParts("voicemail", "", null));
             PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
-            
+
             Notification notification = new Notification(
                     resId,  // icon
                     null, // tickerText
@@ -783,7 +839,7 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             notification.ledARGB = 0xff00ff00;
             notification.ledOnMS = 500;
             notification.ledOffMS = 2000;
-            
+
             mNotificationMgr.notify(
                     VOICEMAIL_NOTIFICATION,
                     notification);
@@ -803,12 +859,12 @@ public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteList
             // If Unconditional Call Forwarding (forward all calls) for VOICE
             // is enabled, just show a notification.  We'll default to expanded
             // view for now, so the there is less confusion about the icon.  If
-            // it is deemed too weird to have CF indications as expanded views, 
+            // it is deemed too weird to have CF indications as expanded views,
             // then we'll flip the flag back.
 
-            // TODO: We may want to take a look to see if the notification can 
-            // display the target to forward calls to.  This will require some 
-            // effort though, since there are multiple layers of messages that 
+            // TODO: We may want to take a look to see if the notification can
+            // display the target to forward calls to.  This will require some
+            // effort though, since there are multiple layers of messages that
             // will need to propagate that information.
 
             Notification notification;
index 99ed6af..f895de2 100644 (file)
@@ -45,14 +45,10 @@ public class OutgoingCallBroadcaster extends Activity {
     public static final String EXTRA_ALREADY_CALLED = "android.phone.extra.ALREADY_CALLED";
     public static final String EXTRA_ORIGINAL_URI = "android.phone.extra.ORIGINAL_URI";
 
-    private Phone mPhone;
-
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mPhone = PhoneApp.getInstance().phone;
-
         Intent intent = getIntent();
         if (LOGV) Log.v(TAG, "onResume: Got intent " + intent + ".");
 
old mode 100644 (file)
new mode 100755 (executable)
index 147b179..5591da2
@@ -45,11 +45,13 @@ import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
 import android.provider.Settings.System;
+import android.telephony.ServiceState;
 import android.util.Config;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.widget.Toast;
 
+import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
@@ -91,6 +93,7 @@ public class PhoneApp extends Application {
     private static final int EVENT_UPDATE_INCALL_NOTIFICATION = 9;
     private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
     private static final int EVENT_DATA_ROAMING_OK = 11;
+    private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
 
     // The MMI codes are also used by the InCallScreen.
     public static final int MMI_INITIATE = 51;
@@ -138,6 +141,9 @@ public class PhoneApp extends Application {
     int mBluetoothHeadsetAudioState = BluetoothHeadset.STATE_ERROR;
     boolean mShowBluetoothIndication = false;
 
+    // Internal PhoneApp Call state tracker
+    CdmaPhoneCallState cdmaPhoneCallState;
+
     // The InCallScreen instance (or null if the InCallScreen hasn't been
     // created yet.)
     private InCallScreen mInCallScreen;
@@ -286,6 +292,10 @@ public class PhoneApp extends Application {
                         }
                     }
                     break;
+
+                case EVENT_UNSOL_CDMA_INFO_RECORD:
+                    //TODO: handle message here;
+                    break;
             }
         }
     };
@@ -363,6 +373,8 @@ public class PhoneApp extends Application {
             intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
             intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
             intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+            intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+            intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
             registerReceiver(mReceiver, intentFilter);
 
             // Use a separate receiver for ACTION_MEDIA_BUTTON broadcasts,
@@ -409,6 +421,16 @@ public class PhoneApp extends Application {
 
         // start with the default value to set the mute state.
         mShouldRestoreMuteOnInCallResume = false;
+
+        // Register for Cdma Information Records
+        // TODO(Moto): Merge
+        // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
+
+        if (phone.getPhoneName().equals("CDMA")) {
+            // Create an instance of CdmaPhoneCallState and initialize it to IDLE
+            cdmaPhoneCallState = new CdmaPhoneCallState();
+            cdmaPhoneCallState.CdmaPhoneCallStateInit();
+        }
    }
 
     /**
@@ -900,24 +922,42 @@ public class PhoneApp extends Application {
     }
 
     private void initForNewRadioTechnology() {
-        if(DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
+        if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
 
         ringer.updateRingerContextAfterRadioTechnologyChange(this.phone);
         notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
-        if(mBtHandsfree != null) {
+        if (mBtHandsfree != null) {
             mBtHandsfree.updateBtHandsfreeAfterRadioTechnologyChange();
         }
+        if (mInCallScreen != null) {
+            mInCallScreen.updateAfterRadioTechnologyChange();
+        }
 
-        //Update registration for ICC status after radio technology change
+        // Update registration for ICC status after radio technology change
         IccCard sim = phone.getIccCard();
         if (sim != null) {
-            if(DBG) Log.d(LOG_TAG, "Update registration for ICC status...");
+            if (DBG) Log.d(LOG_TAG, "Update registration for ICC status...");
 
             //Register all events new to the new active phone
             sim.registerForAbsent(mHandler, EVENT_SIM_ABSENT, null);
             sim.registerForLocked(mHandler, EVENT_SIM_LOCKED, null);
             sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null);
         }
+
+        if (phone.getPhoneName().equals("CDMA")) {
+            // Create an instance of CdmaPhoneCallState and initialize it to IDLE
+            cdmaPhoneCallState = new CdmaPhoneCallState();
+            cdmaPhoneCallState.CdmaPhoneCallStateInit();
+        }
+    }
+
+
+    /**
+     * Send ECBM Exit Request
+     */
+
+    void sendEcbmExitRequest() {
+            mHandler.sendEmptyMessage(EVENT_UPDATE_INCALL_NOTIFICATION);
     }
 
     /**
@@ -1036,10 +1076,10 @@ public class PhoneApp extends Application {
                 if (VDBG) Log.d(LOG_TAG, "==> new state: " + mBluetoothHeadsetAudioState);
                 updateBluetoothIndication(true);  // Also update any visible UI if necessary
             } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
-                // if (DBG) Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED");
-                // if (DBG) Log.d(LOG_TAG, "- state: " + intent.getStringExtra(Phone.STATE_KEY));
-                // if (DBG) Log.d(LOG_TAG, "- reason: "
-                //                + intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY));
+                if (VDBG) Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED");
+                if (VDBG) Log.d(LOG_TAG, "- state: " + intent.getStringExtra(Phone.STATE_KEY));
+                if (VDBG) Log.d(LOG_TAG, "- reason: "
+                                + intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY));
 
                 // The "data disconnected due to roaming" notification is
                 // visible if you've lost data connectivity because you're
@@ -1078,6 +1118,15 @@ public class PhoneApp extends Application {
                 String newPhone = intent.getStringExtra(Phone.PHONE_NAME_KEY);
                 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active.");
                 initForNewRadioTechnology();
+            } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
+                handleServiceStateChanged(intent);
+            } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
+                Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
+                // Send Intend to start ECBM application
+                Intent EcbmAlarm = new Intent(Intent.ACTION_MAIN, null);
+                EcbmAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                EcbmAlarm.setClassName("com.android.phone", EmergencyCallbackMode.class.getName());
+                startActivity(EcbmAlarm);
             }
         }
     }
@@ -1118,4 +1167,49 @@ public class PhoneApp extends Application {
             }
         }
     }
+
+    private void handleServiceStateChanged(Intent intent) {
+        // If service just returned, start sending out the queued messages
+        ServiceState ss = ServiceState.newFromBundle(intent.getExtras());
+
+        boolean hasService = true;
+        boolean isCdma = false;
+        String eriText = "";
+
+        if (ss != null) {
+            int state = ss.getState();
+            switch (state) {
+                case ServiceState.STATE_OUT_OF_SERVICE:
+                case ServiceState.STATE_POWER_OFF:
+                    hasService = false;
+                    break;
+            }
+        } else {
+            hasService = false;
+        }
+
+        if (ss.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_1xRTT
+                || ss.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                || ss.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A
+                || ss.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_IS95A
+                || ss.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_IS95B) {
+            isCdma = true;
+        }
+
+        if (!isCdma) {
+            eriText = "";
+        } else {
+            if (!hasService) {
+                eriText = getText(com.android.internal.R.string.roamingTextSearching).toString();
+            } else {
+                eriText = phone.getCdmaEriText();
+            }
+        }
+
+        if (eriText != null) {
+            EriTextWidgetProvider mEriTextWidgetProvider = EriTextWidgetProvider.getInstance();
+            mEriTextWidgetProvider.performUpdate(this, eriText);
+        }
+
+    }
 }
index 6ecc69c..a034628 100644 (file)
@@ -538,7 +538,7 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
         mPhone.enableLocationUpdates();
     }
-    
+
     public void disableLocationUpdates() {
         mApp.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
@@ -551,16 +551,16 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
             mApp.enforceCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_FINE_LOCATION, null);
         } catch (SecurityException e) {
-            // If we have ACCESS_FINE_LOCATION permission, skip the check 
-            // for ACCESS_COARSE_LOCATION 
-            // A failure should throw the SecurityException from 
+            // If we have ACCESS_FINE_LOCATION permission, skip the check
+            // for ACCESS_COARSE_LOCATION
+            // A failure should throw the SecurityException from
             // ACCESS_COARSE_LOCATION since this is the weaker precondition
             mApp.enforceCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-        }            
+        }
 
         ArrayList<NeighboringCellInfo> cells = null;
-    
+
         try {
             cells = (ArrayList<NeighboringCellInfo>) sendRequest(
                     CMD_HANDLE_NEIGHBORING_CELL, null);
@@ -602,7 +602,7 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
     }
 
-    
+
     private String createTelUrl(String number) {
         if (TextUtils.isEmpty(number)) {
             return null;
@@ -624,6 +624,35 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
             return GSM_PHONE;
         }
     }
-}
 
+    /**
+     * Returns the CDMA ERI icon index to display
+     */
+    public int getCdmaEriIconIndex() {
+        return mPhone.getCdmaEriIconIndex();
+    }
 
+    /**
+     * Returns the CDMA ERI icon mode,
+     * 0 - ON
+     * 1 - FLASHING
+     */
+    public int getCdmaEriIconMode() {
+        return mPhone.getCdmaEriIconMode();
+    }
+
+    /**
+     * Returns the CDMA ERI text,
+     */
+    public String getCdmaEriText() {
+        return mPhone.getCdmaEriText();
+    }
+
+    /**
+     * Returns the unread count of voicemails
+     */
+    public int getVoiceMessageCount() {
+        return mPhone.getVoiceMessageCount();
+    }
+
+}
old mode 100644 (file)
new mode 100755 (executable)
index d8621e2..7268880
@@ -20,14 +20,18 @@ import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.KeyguardManager;
 import android.app.ProgressDialog;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
+import android.os.RemoteException;
 import android.provider.Contacts;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
@@ -44,6 +48,7 @@ import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.IExtendedNetworkService;
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
 
@@ -51,13 +56,6 @@ import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 
-import com.android.internal.telephony.IExtendedNetworkService;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.content.ComponentName;
-import android.os.RemoteException;
-
-
 /**
  * Misc utilities for the Phone app.
  */
@@ -228,6 +226,21 @@ public class PhoneUtils {
                 phone.acceptCall();
                 answered = true;
                 setAudioMode(phone.getContext(), AudioManager.MODE_IN_CALL);
+                if (phone.getPhoneName().equals("CDMA")) {
+                    PhoneApp app = PhoneApp.getInstance();
+                    if (app.cdmaPhoneCallState.getCurrentCallState()
+                            == CdmaPhoneCallState.PhoneCallState.IDLE) {
+                        // This is the FIRST incoming call being answered.
+                        // Set the Phone Call State to SINGLE_ACTIVE
+                        app.cdmaPhoneCallState.setCurrentCallState(
+                                CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE);
+                    } else {
+                        // This is the CALL WAITING call being answered.
+                        // Set the Phone Call State to CONF_CALL
+                        app.cdmaPhoneCallState.setCurrentCallState(
+                                CdmaPhoneCallState.PhoneCallState.CONF_CALL);
+                    }
+                }
             } catch (CallStateException ex) {
                 Log.w(LOG_TAG, "answerCall: caught " + ex, ex);
             }
@@ -360,6 +373,21 @@ public class PhoneUtils {
                 }
 
             } else {
+                PhoneApp app = PhoneApp.getInstance();
+
+                if (phone.getPhoneName().equals("CDMA")){
+                    if (app.cdmaPhoneCallState.getCurrentCallState()
+                            == CdmaPhoneCallState.PhoneCallState.IDLE) {
+                        // This is the first outgoing call. Set the Phone Call State to ACTIVE
+                        app.cdmaPhoneCallState.setCurrentCallState(
+                                CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE);
+                    } else {
+                        // This is the second outgoing call. Set the Phone Call State to 3WAY
+                        app.cdmaPhoneCallState.setCurrentCallState(
+                                CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE);
+                    }
+                }
+
                 PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_OFFHOOK);
 
                 // phone.dial() succeeded: we're now in a normal phone call.
@@ -427,11 +455,27 @@ public class PhoneUtils {
     }
 
     static void mergeCalls(Phone phone) {
-        try {
-            if (DBG) log("mergeCalls");
-            phone.conference();
-        } catch (CallStateException ex) {
-            Log.w(LOG_TAG, "mergeCalls: caught " + ex, ex);
+        if (phone.getPhoneName().equals("GSM")) {
+            try {
+                if (DBG) log("mergeCalls");
+                phone.conference();
+            } catch (CallStateException ex) {
+                Log.w(LOG_TAG, "mergeCalls: caught " + ex, ex);
+            }
+        } else { // CDMA
+            PhoneApp app = PhoneApp.getInstance();
+            if (app.cdmaPhoneCallState.getCurrentCallState()
+                    == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
+                // Send flash cmd
+                // TODO(Moto): Need to change the call from switchHoldingAndActive to
+                // something meaningful as we are not actually trying to swap calls but
+                // instead are merging two calls by sending a Flash command.
+                switchHoldingAndActive(phone);
+
+                // Set the Phone Call State to conference
+                app.cdmaPhoneCallState.setCurrentCallState(
+                        CdmaPhoneCallState.PhoneCallState.CONF_CALL);
+            }
         }
     }
 
@@ -649,7 +693,7 @@ public class PhoneUtils {
                         mNwService = null;
                     }
                     if (DBG) log("Extended NW displayMMIInitiate (" + text + ")");
-                    if (text == null)
+                    if (text == null || text.length() == 0)
                         return;
                 }
 
@@ -915,7 +959,14 @@ public class PhoneUtils {
      */
     static CallerInfoToken startGetCallerInfo(Context context, Call call,
             CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) {
-        Connection conn = call.getEarliestConnection();
+        PhoneApp app = PhoneApp.getInstance();
+        Connection conn = null;
+        if (app.phone.getPhoneName().equals("CDMA")) {
+            conn = call.getLatestConnection();
+        } else {
+            conn = call.getEarliestConnection();
+        }
+
         return startGetCallerInfo(context, conn, listener, cookie);
     }
 
@@ -990,6 +1041,15 @@ public class PhoneUtils {
             // handling case where number is null (caller id hidden) as well.
             if (!TextUtils.isEmpty(number)) {
                 cit.currentInfo.phoneNumber = number;
+                // Store CNAP information retrieved from the Connection
+                cit.currentInfo.cnapName =  c.getCnapName();
+                cit.currentInfo.name = cit.currentInfo.cnapName; // This can still get overwritten
+                                                                 // by ContactInfo later
+                cit.currentInfo.numberPresentation = c.getNumberPresentation();
+                cit.currentInfo.namePresentation = c.getCnapNamePresentation();
+                if (DBG) log("startGetCallerInfo: CNAP Info from FW: name="
+                        + cit.currentInfo.cnapName
+                        + ", Name/Number Pres=" + cit.currentInfo.numberPresentation);
                 cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context,
                         number, sCallerInfoQueryListener, c);
                 cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie);
@@ -1046,7 +1106,19 @@ public class PhoneUtils {
             public void onQueryComplete(int token, Object cookie, CallerInfo ci){
                 if (DBG) log("query complete, updating connection.userdata");
 
-                ((Connection) cookie).setUserData(ci);
+                // Added a check if CallerInfo is coming from ContactInfo or from Connection.
+                // If no ContactInfo, then we want to use CNAP information coming from network
+                if (DBG) log("- onQueryComplete: contactExists=" + ci.contactExists);
+                if (ci.contactExists) {
+                    ((Connection) cookie).setUserData(ci);
+                } else {
+                    CallerInfo newCi = getCallerInfo(null, (Connection) cookie);
+                    if (newCi != null) {
+                        newCi.phoneNumber = ci.phoneNumber; // To get formatted phone number
+                        ((Connection) cookie).setUserData(newCi);
+                    }
+                    else ((Connection) cookie).setUserData(ci);
+                }
             }
         };
 
@@ -1058,52 +1130,6 @@ public class PhoneUtils {
     }
 
     /**
-     * Returns a single "name" for the specified Connection.
-     * This may be the caller name, the phone number, or a generic "unknown"
-     * string, depending on what info is available.
-     *
-     * NOTE: This API should be avoided, with preference given to the
-     * asynchronous startGetCallerInfo API, used in conjunction with
-     * getCompactNameFromCallerInfo().
-     */
-    static String getCompactName(Context context, Connection conn) {
-        CallerInfo info = getCallerInfo(context, conn);
-        if (DBG) log("getCompactName: info = " + info);
-
-        String compactName = null;
-        if (info != null) {
-            compactName = info.name;
-            if (compactName == null) {
-                compactName = info.phoneNumber;
-            }
-        }
-        // TODO: figure out UNKNOWN, PRIVATE numbers?
-        if (compactName == null) {
-            compactName = context.getString(R.string.unknown);
-        }
-        return compactName;
-    }
-
-    /**
-     * Returns a single "name" for the specified Call.
-     * If the call only has a single connection, this is
-     * just like calling getCompactName() on that connection.
-     * But if this call has more than one connection,
-     * return a generic string like "Conference call".
-     *
-     * NOTE: This API should be avoided, with preference given to the
-     * asynchronous startGetCallerInfo API, used in conjunction with
-     * getCompactNameFromCallerInfo().
-     */
-    static String getCompactName(Context context, Call call) {
-        if (isConferenceCall(call)) {
-            return context.getString(R.string.confCall);
-        }
-        Connection conn = call.getEarliestConnection();  // may be null
-        return getCompactName(context, conn);  // OK if conn is null
-    }
-
-    /**
      * Returns a single "name" for the specified given a CallerInfo object.
      * If the name is null, return defaultString as the default value, usually
      * context.getString(R.string.unknown).
@@ -1114,12 +1140,12 @@ public class PhoneUtils {
         String compactName = null;
         if (ci != null) {
             compactName = ci.name;
-            if (compactName == null) {
+            if ((compactName == null) || (TextUtils.isEmpty(compactName))) {
                 compactName = ci.phoneNumber;
             }
         }
         // TODO: figure out UNKNOWN, PRIVATE numbers?
-        if (compactName == null) {
+        if ((compactName == null) || (TextUtils.isEmpty(compactName))) {
             compactName = context.getString(R.string.unknown);
         }
         return compactName;
@@ -1127,7 +1153,10 @@ public class PhoneUtils {
 
     /**
      * Returns true if the specified Call is a "conference call", meaning
-     * that it owns more than one Connection object.
+     * that it owns more than one Connection object.  This information is
+     * used to trigger certain UI changes that appear when a conference
+     * call is active (like displaying the label "Conference call", and
+     * enabling the "Manage conference" UI.)
      *
      * Watch out: This method simply checks the number of Connections,
      * *not* their states.  So if a Call has (for example) one ACTIVE
@@ -1138,9 +1167,23 @@ public class PhoneUtils {
      * @return true if the specified call has more than one connection (in any state.)
      */
     static boolean isConferenceCall(Call call) {
-        List<Connection> connections = call.getConnections();
-        if (connections != null && connections.size() > 1) {
-            return true;
+        // CDMA phones don't have the same concept of "conference call" as
+        // GSM phones do; there's no special "conference call" state of
+        // the UI or a "manage conference" function.  (Instead, when
+        // you're in a 3-way call, all we can do is display the "generic"
+        // state of the UI.)  So as far as the in-call UI is concerned,
+        // Conference corresponds to generic display.
+        PhoneApp app = PhoneApp.getInstance();
+        if (app.phone.getPhoneName().equals("CDMA")) {
+            if (app.cdmaPhoneCallState.getCurrentCallState()
+                    == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
+                return true;
+            }
+        } else {
+            List<Connection> connections = call.getConnections();
+            if (connections != null && connections.size() > 1) {
+                return true;
+            }
         }
         return false;
 
@@ -1417,25 +1460,52 @@ public class PhoneUtils {
         final boolean hasActiveCall = !phone.getForegroundCall().isIdle();
         final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle();
 
-        if (hasRingingCall) {
-            // If an incoming call is ringing, answer it (just like with the
-            // CALL button):
-            if (hasActiveCall && hasHoldingCall) {
-                if (DBG) log("handleHeadsetHook: ringing (both lines in use) ==> answer!");
-                answerAndEndActive(phone);
+        if (phone.getPhoneName().equals("CDMA")) {
+            PhoneApp app = PhoneApp.getInstance();
+            if (hasRingingCall) {
+                answerCall(phone);
             } else {
-                if (DBG) log("handleHeadsetHook: ringing ==> answer!");
-                answerCall(phone);  // Automatically holds the current active call,
-                                     // if there is one
+                if (app.cdmaPhoneCallState.getCurrentCallState()
+                        == CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE) {
+                    // Send a flash command to CDMA network for putting the other
+                    // party on hold.
+                    // For CDMA networks which do not support this the user would just
+                    // hear a beep from the network.
+                    // For CDMA networks which do support it it will put the other
+                    // party on hold.
+                    switchHoldingAndActive(phone);
+                }
+
+                // No incoming ringing call.  Toggle the mute state.
+                if (getMute(phone)) {
+                    if (DBG) log("handleHeadsetHook: UNmuting...");
+                    setMute(phone, false);
+                } else {
+                    if (DBG) log("handleHeadsetHook: muting...");
+                    setMute(phone, true);
+                }
             }
-        } else {
-            // No incoming ringing call.  Toggle the mute state.
-            if (getMute(phone)) {
-                if (DBG) log("handleHeadsetHook: UNmuting...");
-                setMute(phone, false);
+        } else { // GSM
+            if (hasRingingCall) {
+                // If an incoming call is ringing, answer it (just like with the
+                // CALL button):
+                if (hasActiveCall && hasHoldingCall) {
+                    if (DBG) log("handleHeadsetHook: ringing (both lines in use) ==> answer!");
+                    answerAndEndActive(phone);
+                } else {
+                    if (DBG) log("handleHeadsetHook: ringing ==> answer!");
+                    answerCall(phone);  // Automatically holds the current active call,
+                                     // if there is one
+                }
             } else {
-                if (DBG) log("handleHeadsetHook: muting...");
-                setMute(phone, true);
+                // No incoming ringing call.  Toggle the mute state.
+                if (getMute(phone)) {
+                    if (DBG) log("handleHeadsetHook: UNmuting...");
+                    setMute(phone, false);
+                } else {
+                    if (DBG) log("handleHeadsetHook: muting...");
+                    setMute(phone, true);
+                }
             }
         }
 
@@ -1491,14 +1561,22 @@ public class PhoneUtils {
      * state of the Phone.
      */
     /* package */ static boolean okToSwapCalls(Phone phone) {
-        // "Swap" is available if both lines are in use and there's no
-        // incoming call.  (Actually we need to verify that the active
-        // call really is in the ACTIVE state and the holding call really
-        // is in the HOLDING state, since you *can't* actually swap calls
-        // when the foreground call is DIALING or ALERTING.)
-        return phone.getRingingCall().isIdle()
-                && (phone.getForegroundCall().getState() == Call.State.ACTIVE)
-                && (phone.getBackgroundCall().getState() == Call.State.HOLDING);
+        if (phone.getPhoneName().equals("CDMA")) {
+            // CDMA: "Swap" is enabled only when the phone reaches a *generic*.
+            // state by either accepting a Call Waiting or by merging two calls
+            PhoneApp app = PhoneApp.getInstance();
+            return (app.cdmaPhoneCallState.getCurrentCallState()
+                    == CdmaPhoneCallState.PhoneCallState.CONF_CALL);
+        } else {
+            // GSM: "Swap" is available if both lines are in use and there's no
+            // incoming call.  (Actually we need to verify that the active
+            // call really is in the ACTIVE state and the holding call really
+            // is in the HOLDING state, since you *can't* actually swap calls
+            // when the foreground call is DIALING or ALERTING.)
+            return phone.getRingingCall().isIdle()
+                    && (phone.getForegroundCall().getState() == Call.State.ACTIVE)
+                    && (phone.getBackgroundCall().getState() == Call.State.HOLDING);
+        }
     }
 
     /**
@@ -1506,10 +1584,17 @@ public class PhoneUtils {
      * state of the Phone.
      */
     /* package */ static boolean okToMergeCalls(Phone phone) {
-        // "Merge" is available if both lines are in use and there's no
-        // incoming call, *and* the current conference isn't already
-        // "full".
-        return phone.getRingingCall().isIdle() && phone.canConference();
+        if (phone.getPhoneName().equals("CDMA")) {
+            // CDMA: "Merge" is enabled only when the user is in a 3Way call.
+            PhoneApp app = PhoneApp.getInstance();
+            return (app.cdmaPhoneCallState.getCurrentCallState()
+                    == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE);
+        } else { //GSM.
+            // GSM: "Merge" is available if both lines are in use and there's no
+            // incoming call, *and* the current conference isn't already