Merge "Add getCdmaMdn and getCdmaMin to phoneinterfacemanager." into lmp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index fe79017..7add3a8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -40,7 +40,6 @@
<protected-broadcast android:name="com.android.internal.telephony.data-restart-trysetup" />
<protected-broadcast android:name="com.android.internal.telephony.data-stall" />
- <uses-permission android:name="android.permission.BIND_CALL_SERVICE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CALL_PRIVILEGED" />
@@ -479,7 +478,8 @@
</service>
<service android:name="com.android.services.telephony.sip.SipConnectionService"
android:label="@string/sip_connection_service_label"
- android:singleUser="true" >
+ android:singleUser="true"
+ android:permission="android.permission.BIND_CONNECTION_SERVICE" >
<intent-filter>
<action android:name="android.telecomm.ConnectionService" />
</intent-filter>
@@ -572,7 +572,8 @@
<service
android:singleUser="true"
android:name="com.android.services.telephony.TelephonyConnectionService"
- android:label="@string/pstn_connection_service_label">
+ android:label="@string/pstn_connection_service_label"
+ android:permission="android.permission.BIND_CONNECTION_SERVICE" >
<intent-filter>
<action android:name="android.telecomm.ConnectionService" />
</intent-filter>
diff --git a/res/values/config.xml b/res/values/config.xml
index 0d1ae54..cfca00b 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -121,7 +121,7 @@
<!-- Show cdma auto network mode in (glabal) roaming -->
<bool name="config_show_cdma" translatable="false">false</bool>
<!-- Display enhanced 4G LTE mode menu if true -->
- <bool name="config_enhanced_4g_lte_mode_enable" translatable="false">true</bool>
+ <bool name="config_enhanced_4g_lte_mode_enable" translatable="false">false</bool>
<!-- Package name for the default in-call UI and dialer [DO NOT TRANSLATE] -->
<string name="ui_default_package" translatable="false">com.android.dialer</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c343deb..0745ad7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1139,11 +1139,6 @@
on this device. [CHAR LIMIT=40] -->
<string name="not_voice_capable">Voice calling not supported</string>
- <!-- Title of settings screen for managing the "Respond via SMS" feature. [CHAR LIMIT=30] -->
- <string name="respond_via_sms_setting_title">Quick responses</string>
- <!-- Settings summary string for the "Respond via SMS" feature. [CHAR LIMIT=40] -->
- <string name="respond_via_sms_setting_summary"></string>
-
<!-- String describing the Dial ImageButton
Used by AccessibilityService to announce the purpose of the button.
@@ -1161,12 +1156,6 @@
[CHAR LIMIT=30] -->
<string name="voicemail_notification_ringtone_title">Sound</string>
- <!-- The string used to describe a notification if it is the default one in the system. For
- example, if the user selects the default notification, it will appear as something like
- Default sound(Capella) in the notification summary.
- [CHAR LIMIT=40] -->
- <string name="default_notification_description">Default sound (<xliff:g id="default_sound_title">%1$s</xliff:g>)</string>
-
<!-- The default value value for voicemail notification. -->
<string name="voicemail_notification_vibrate_when_default" translatable="false">never</string>
@@ -1177,18 +1166,6 @@
<item>never</item>
</string-array>
- <!-- Setting option name to pick ringtone (a list dialog comes up). [CHAR LIMIT=30] -->
- <string name="ringtone_title" msgid="5379026328015343686">Phone ringtone</string>
-
- <!-- Setting option name to enable or disable vibration when ringing
- the phone.
- [CHAR LIMIT=30] -->
- <string name="vibrate_on_ring_title">Vibrate when ringing</string>
-
- <!-- Setting option name to enable or disable DTMF tone sound
- [CHAR LIMIT=30] -->
- <string name="dtmf_tone_enable_title">Dial pad touch tones</string>
-
<!-- Setting option name to enable or disable dialpad autocomplete functionality
[CHAR LIMIT=30] -->
<string name="dial_pad_autocomplete">Dial pad autocomplete</string>
diff --git a/res/xml/call_feature_setting.xml b/res/xml/call_feature_setting.xml
index 30811e4..625ff4c 100644
--- a/res/xml/call_feature_setting.xml
+++ b/res/xml/call_feature_setting.xml
@@ -17,110 +17,77 @@
xmlns:phone="http://schemas.android.com/apk/res/com.android.phone"
android:title="@string/call_settings">
- <PreferenceCategory
- android:key="button_ringtone_category_key"
- android:title="@string/preference_category_ringtone"
- android:persistent="false">
-
- <com.android.phone.DefaultRingtonePreference
- android:key="button_ringtone_key"
- android:title="@string/ringtone_title"
- android:dialogTitle="@string/ringtone_title"
- android:persistent="false"
- android:ringtoneType="ringtone" />
-
- <CheckBoxPreference
- android:key="button_vibrate_on_ring"
- android:title="@string/vibrate_on_ring_title"
- android:persistent="false"
- android:defaultValue="false" />
- </PreferenceCategory>
-
- <PreferenceCategory
- android:key="button_misc_category_key"
- android:title="@string/other_settings"
- android:persistent="false" />
-
<Preference
- android:key="phone_accounts"
- android:title="@string/phone_accounts" >
+ android:key="phone_accounts"
+ android:title="@string/phone_accounts">
+
<intent
- android:targetClass="com.android.telecomm.PhoneAccountPreferencesActivity"
- android:targetPackage="com.android.telecomm" />
+ android:targetClass="com.android.telecomm.PhoneAccountPreferencesActivity"
+ android:targetPackage="com.android.telecomm" />
+
</Preference>
- <PreferenceScreen
- android:key="button_voicemail_category_key"
- android:title="@string/voicemail"
- android:persistent="false">
- <ListPreference
- android:key="button_voicemail_provider_key"
- android:title="@string/voicemail_provider"
- android:summary="@string/sum_voicemail_choose_provider"
- android:defaultValue=""
- android:persistent="true" />
- <PreferenceScreen
- android:key="button_voicemail_setting_key"
- android:title="@string/voicemail_settings"
- android:persistent="false">
+ <PreferenceScreen
+ android:key="button_voicemail_category_key"
+ android:title="@string/voicemail"
+ android:persistent="false">
- <!-- Note for all com.android.phone.EditPhoneNumberPreference objects
+ <ListPreference
+ android:key="button_voicemail_provider_key"
+ android:title="@string/voicemail_provider"
+ android:summary="@string/sum_voicemail_choose_provider"
+ android:defaultValue=""
+ android:persistent="true" />
- 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 -->
+ <PreferenceScreen
+ android:key="button_voicemail_setting_key"
+ android:title="@string/voicemail_settings"
+ android:persistent="false">
- <com.android.phone.EditPhoneNumberPreference
- android:key="button_voicemail_key"
- android:title="@string/voicemail_settings_number_label"
- android:persistent="false"
- android:dialogTitle="@string/voicemail"
- phone:confirmMode="confirm"
- android:singleLine="true"
- android:autoText="false" />
- </PreferenceScreen>
+ <!-- Note for all com.android.phone.EditPhoneNumberPreference objects
- <RingtonePreference
- android:key="button_voicemail_notification_ringtone_key"
- android:title="@string/voicemail_notification_ringtone_title"
- android:persistent="true"
- android:ringtoneType="notification"
- android:defaultValue="content://settings/system/notification_sound" />
- <CheckBoxPreference
- android:key="button_voicemail_notification_vibrate_key"
- android:title="@string/voicemail_notification_vibrate_when_title"
- android:persistent="true"
- />
- </PreferenceScreen>
+ 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 -->
- <CheckBoxPreference
- android:key="button_play_dtmf_tone"
- android:title="@string/dtmf_tone_enable_title"
- android:persistent="false"
- android:defaultValue="true" />
+ <com.android.phone.EditPhoneNumberPreference
+ android:key="button_voicemail_key"
+ android:title="@string/voicemail_settings_number_label"
+ android:persistent="false"
+ android:dialogTitle="@string/voicemail"
+ phone:confirmMode="confirm"
+ android:singleLine="true"
+ android:autoText="false" />
- <PreferenceScreen
- android:key="button_respond_via_sms_key"
- android:title="@string/respond_via_sms_setting_title"
- android:summary="@string/respond_via_sms_setting_summary"
- android:persistent="false">
- <intent
- android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.telecomm"
- android:targetClass="com.android.telecomm.RespondViaSmsSettings$Settings" />
- </PreferenceScreen>
+ </PreferenceScreen>
- <PreferenceScreen
- android:key="button_fdn_key"
- android:title="@string/fdn"
- android:persistent="false">
- <intent android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.phone"
- android:targetClass="com.android.phone.FdnSetting" />
- </PreferenceScreen>
+ <RingtonePreference
+ android:key="button_voicemail_notification_ringtone_key"
+ android:title="@string/voicemail_notification_ringtone_title"
+ android:persistent="true"
+ android:ringtoneType="notification"
+ android:defaultValue="content://settings/system/notification_sound" />
+
+ <CheckBoxPreference
+ android:key="button_voicemail_notification_vibrate_key"
+ android:title="@string/voicemail_notification_vibrate_when_title"
+ android:persistent="true" />
+
+ </PreferenceScreen>
+
+ <PreferenceScreen
+ android:key="button_fdn_key"
+ android:title="@string/fdn"
+ android:persistent="false">
+
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.phone"
+ android:targetClass="com.android.phone.FdnSetting" />
+
+ </PreferenceScreen>
<CheckBoxPreference
android:key="button_auto_retry_key"
@@ -136,7 +103,7 @@
android:entries="@array/tty_mode_entries"
android:entryValues="@array/tty_mode_values"/>
- <CheckBoxPreference
+ <CheckBoxPreference
android:key="button_hac_key"
android:title="@string/hac_mode_title"
android:persistent="true"
@@ -158,6 +125,7 @@
<intent android:action="android.intent.action.MAIN"
android:targetPackage="com.android.phone"
android:targetClass="com.android.phone.GsmUmtsCallOptions"/>
+
</PreferenceScreen>
<PreferenceScreen
@@ -169,6 +137,7 @@
<intent android:action="android.intent.action.MAIN"
android:targetPackage="com.android.phone"
android:targetClass="com.android.phone.CdmaCallOptions"/>
+
</PreferenceScreen>
<CheckBoxPreference
@@ -176,4 +145,5 @@
android:title="@string/enable_video_calling_title"
android:persistent="true"
android:defaultValue="true" />
+
</PreferenceScreen>
diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml
index 1156f91..3f85ea8 100644
--- a/res/xml/gsm_umts_options.xml
+++ b/res/xml/gsm_umts_options.xml
@@ -22,7 +22,7 @@
android:title="@string/apn_settings"
android:persistent="false">
- <intent android:action="android.settings.APN_SETTINGS" />
+ <!-- The launching Intent will be defined thru code as we need to pass some Extra -->
</PreferenceScreen>
diff --git a/sip/res/xml/sip_settings_category.xml b/sip/res/xml/sip_settings_category.xml
index 17ee577..9527d6a 100644
--- a/sip/res/xml/sip_settings_category.xml
+++ b/sip/res/xml/sip_settings_category.xml
@@ -15,34 +15,38 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:phone="http://schemas.android.com/apk/res/com.android.phone">
- <PreferenceCategory
- android:key="sip_settings_category_key"
- android:title="@string/sip_settings"
+
+ <PreferenceScreen
+ android:key="sip_settings_preference_screen_key"
+ android:title="@string/sip_settings"
+ android:persistent="false" >
+
+ <PreferenceScreen
+ android:key="sip_account_settings_key"
+ android:title="@string/sip_accounts_title"
android:persistent="false">
- <PreferenceScreen
- android:key="sip_account_settings_key"
- android:title="@string/sip_accounts_title"
- android:persistent="false">
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.phone"
+ android:targetClass="com.android.services.telephony.sip.SipSettings" />
- <intent android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.phone"
- android:targetClass="com.android.services.telephony.sip.SipSettings" />
- </PreferenceScreen>
+ </PreferenceScreen>
- <ListPreference
- android:key="sip_call_options_key"
- android:title="@string/sip_call_options_title"
- android:persistent="true"
- android:entries="@array/sip_call_options_entries"
- android:entryValues="@array/sip_call_options_values"/>
+ <ListPreference
+ android:key="sip_call_options_key"
+ android:title="@string/sip_call_options_title"
+ android:persistent="true"
+ android:entries="@array/sip_call_options_entries"
+ android:entryValues="@array/sip_call_options_values"/>
- <ListPreference
- android:key="sip_call_options_wifi_only_key"
- android:title="@string/sip_call_options_title"
- android:dialogTitle="@string/sip_call_options_wifi_only_title"
- android:persistent="true"
- android:entries="@array/sip_call_options_wifi_only_entries"
- android:entryValues="@array/sip_call_options_values"/>
- </PreferenceCategory>
+ <ListPreference
+ android:key="sip_call_options_wifi_only_key"
+ android:title="@string/sip_call_options_title"
+ android:dialogTitle="@string/sip_call_options_wifi_only_title"
+ android:persistent="true"
+ android:entries="@array/sip_call_options_wifi_only_entries"
+ android:entryValues="@array/sip_call_options_values"/>
+
+ </PreferenceScreen>
+
</PreferenceScreen>
diff --git a/sip/src/com/android/services/telephony/sip/SipConnection.java b/sip/src/com/android/services/telephony/sip/SipConnection.java
index 58db1f5..2603b98 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnection.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnection.java
@@ -180,11 +180,6 @@
}
@Override
- public void onChildrenChanged(List<Connection> children) {
- if (VERBOSE) log("onChildrenChanged, children: " + children);
- }
-
- @Override
public void onPhoneAccountClicked() {
if (VERBOSE) log("onPhoneAccountClicked");
}
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index bda564f..8f11935 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -61,7 +61,7 @@
com.android.internal.telephony.Connection chosenConnection =
createConnectionForProfile(profile, request);
if (chosenConnection == null) {
- connection.setCanceled();
+ connection.setDisconnected(DisconnectCause.OUTGOING_CANCELED, null);
} else {
connection.initialize(chosenConnection);
}
@@ -70,13 +70,13 @@
@Override
public void onSipNotChosen() {
if (VERBOSE) log("onCreateOutgoingConnection, onSipNotChosen");
- connection.setFailed(DisconnectCause.ERROR_UNSPECIFIED, null);
+ connection.setDisconnected(DisconnectCause.ERROR_UNSPECIFIED, null);
}
@Override
public void onCancelCall() {
if (VERBOSE) log("onCreateOutgoingConnection, onCancelCall");
- connection.setCanceled();
+ connection.setDisconnected(DisconnectCause.OUTGOING_CANCELED, null);
}
};
@@ -87,14 +87,6 @@
}
@Override
- public void onCreateConferenceConnection(
- String token,
- Connection connection,
- Response<String, Connection> response) {
- if (VERBOSE) log("onCreateConferenceConnection, connection: " + connection);
- }
-
- @Override
public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerAccount,
ConnectionRequest request) {
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 9f0dad7..103606a 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -34,27 +34,21 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
import android.media.AudioManager;
import android.media.RingtoneManager;
-import android.net.Uri;
import android.net.sip.SipManager;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
-import android.os.Vibrator;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
-import android.preference.PreferenceCategory;
-import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.provider.ContactsContract.CommonDataKinds;
-import android.provider.MediaStore;
import android.provider.Settings;
import android.telecomm.ConnectionService;
import android.telecomm.TelecommManager;
@@ -69,9 +63,11 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.phone.common.util.SettingsUtil;
import com.android.services.telephony.sip.SipSharedPreferences;
import com.android.services.telephony.sip.SipUtil;
+import java.lang.String;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -95,14 +91,16 @@
* For the "Mobile network settings" screen under the main Settings app,
* See {@link MobileNetworkSettings}.
*
+ * TODO: Settings should be split into PreferenceFragments where possible (ie. voicemail, SIP).
+ *
* @see com.android.phone.MobileNetworkSettings
*/
public class CallFeaturesSetting extends PreferenceActivity
implements DialogInterface.OnClickListener,
- Preference.OnPreferenceChangeListener,
- Preference.OnPreferenceClickListener,
- EditPhoneNumberPreference.OnDialogClosedListener,
- EditPhoneNumberPreference.GetDefaultNumberListener {
+ Preference.OnPreferenceChangeListener,
+ Preference.OnPreferenceClickListener,
+ EditPhoneNumberPreference.OnDialogClosedListener,
+ EditPhoneNumberPreference.GetDefaultNumberListener {
private static final String LOG_TAG = "CallFeaturesSetting";
private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
@@ -176,13 +174,7 @@
/* package */ static final String BUTTON_VOICEMAIL_NOTIFICATION_RINGTONE_KEY =
"button_voicemail_notification_ringtone_key";
private static final String BUTTON_FDN_KEY = "button_fdn_key";
- private static final String BUTTON_RESPOND_VIA_SMS_KEY = "button_respond_via_sms_key";
- private static final String BUTTON_RINGTONE_CATEGORY = "button_ringtone_category_key";
-
- private static final String BUTTON_RINGTONE_KEY = "button_ringtone_key";
- private static final String BUTTON_VIBRATE_ON_RING = "button_vibrate_on_ring";
- private static final String BUTTON_PLAY_DTMF_TONE = "button_play_dtmf_tone";
private static final String BUTTON_DTMF_KEY = "button_dtmf_settings";
private static final String BUTTON_RETRY_KEY = "button_auto_retry_key";
private static final String BUTTON_TTY_KEY = "button_tty_mode_key";
@@ -193,12 +185,11 @@
private static final String VM_NUMBERS_SHARED_PREFERENCES_NAME = "vm_numbers";
- private static final String BUTTON_SIP_CALL_OPTIONS =
- "sip_call_options_key";
+ private static final String BUTTON_SIP_CALL_OPTIONS = "sip_call_options_key";
private static final String BUTTON_SIP_CALL_OPTIONS_WIFI_ONLY =
"sip_call_options_wifi_only_key";
- private static final String SIP_SETTINGS_CATEGORY_KEY =
- "sip_settings_category_key";
+ private static final String SIP_SETTINGS_PREFERENCE_SCREEN_KEY =
+ "sip_settings_preference_screen_key";
private Intent mContactListIntent;
@@ -207,8 +198,7 @@
private static final int EVENT_FORWARDING_CHANGED = 501;
private static final int EVENT_FORWARDING_GET_COMPLETED = 502;
- private static final int MSG_UPDATE_RINGTONE_SUMMARY = 1;
- private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 2;
+ private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
public static final String HAC_KEY = "HACSetting";
public static final String HAC_VAL_ON = "ON";
@@ -251,14 +241,11 @@
private EditPhoneNumberPreference mSubMenuVoicemailSettings;
- private Runnable mRingtoneLookupRunnable;
- private final Handler mRingtoneLookupComplete = new Handler() {
+ private Runnable mVoicemailRingtoneLookupRunnable;
+ private final Handler mVoicemailRingtoneLookupComplete = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_UPDATE_RINGTONE_SUMMARY:
- mRingtonePreference.setSummary((CharSequence) msg.obj);
- break;
case MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY:
mVoicemailNotificationRingtone.setSummary((CharSequence) msg.obj);
break;
@@ -266,10 +253,7 @@
}
};
- private Preference mRingtonePreference;
- private CheckBoxPreference mVibrateWhenRinging;
/** Whether dialpad plays DTMF tone or not. */
- private CheckBoxPreference mPlayDtmfTone;
private CheckBoxPreference mButtonAutoRetry;
private CheckBoxPreference mButtonHAC;
private ListPreference mButtonDTMF;
@@ -489,9 +473,6 @@
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference == mSubMenuVoicemailSettings) {
return true;
- } else if (preference == mPlayDtmfTone) {
- Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,
- mPlayDtmfTone.isChecked() ? 1 : 0);
} else if (preference == mButtonDTMF) {
return true;
} else if (preference == mButtonTTY) {
@@ -553,11 +534,8 @@
log("onPreferenceChange(). preferenece: \"" + preference + "\""
+ ", value: \"" + objValue + "\"");
}
- if (preference == mVibrateWhenRinging) {
- boolean doVibrate = (Boolean) objValue;
- Settings.System.putInt(mPhone.getContext().getContentResolver(),
- Settings.System.VIBRATE_WHEN_RINGING, doVibrate ? 1 : 0);
- } else if (preference == mButtonDTMF) {
+
+ if (preference == mButtonDTMF) {
int index = mButtonDTMF.findIndexOfValue((String) objValue);
Settings.System.putInt(mPhone.getContext().getContentResolver(),
Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, index);
@@ -1533,9 +1511,6 @@
mSubMenuVoicemailSettings.setDialogTitle(R.string.voicemail_settings_number_label);
}
- mRingtonePreference = findPreference(BUTTON_RINGTONE_KEY);
- mVibrateWhenRinging = (CheckBoxPreference) findPreference(BUTTON_VIBRATE_ON_RING);
- mPlayDtmfTone = (CheckBoxPreference) findPreference(BUTTON_PLAY_DTMF_TONE);
mButtonDTMF = (ListPreference) findPreference(BUTTON_DTMF_KEY);
mButtonAutoRetry = (CheckBoxPreference) findPreference(BUTTON_RETRY_KEY);
mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
@@ -1543,6 +1518,7 @@
mConnectionService = (ListPreference)
findPreference(BUTTON_DEFAULT_CONNECTION_SERVICE);
mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
+
if (mVoicemailProviders != null) {
mVoicemailProviders.setOnPreferenceChangeListener(this);
mVoicemailSettings = (PreferenceScreen)findPreference(BUTTON_VOICEMAIL_SETTING_KEY);
@@ -1553,24 +1529,8 @@
initVoiceMailProviders();
}
- if (mVibrateWhenRinging != null) {
- Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
- if (vibrator != null && vibrator.hasVibrator()) {
- mVibrateWhenRinging.setOnPreferenceChangeListener(this);
- } else {
- PreferenceCategory ringToneCategory = (PreferenceCategory)findPreference(BUTTON_RINGTONE_CATEGORY);
- ringToneCategory.removePreference(mVibrateWhenRinging);
- mVibrateWhenRinging = null;
- }
- }
-
final ContentResolver contentResolver = getContentResolver();
- if (mPlayDtmfTone != null) {
- mPlayDtmfTone.setChecked(Settings.System.getInt(contentResolver,
- Settings.System.DTMF_TONE_WHEN_DIALING, 1) != 0);
- }
-
if (mButtonDTMF != null) {
if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
mButtonDTMF.setOnPreferenceChangeListener(this);
@@ -1611,23 +1571,25 @@
if (!getResources().getBoolean(R.bool.world_phone)) {
Preference options = prefSet.findPreference(BUTTON_CDMA_OPTIONS);
- if (options != null)
+ if (options != null) {
prefSet.removePreference(options);
+ }
options = prefSet.findPreference(BUTTON_GSM_UMTS_OPTIONS);
- if (options != null)
+ if (options != null) {
prefSet.removePreference(options);
+ }
int phoneType = mPhone.getPhoneType();
if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
Preference fdnButton = prefSet.findPreference(BUTTON_FDN_KEY);
- if (fdnButton != null)
+ if (fdnButton != null) {
prefSet.removePreference(fdnButton);
+ }
if (!getResources().getBoolean(R.bool.config_voice_privacy_disable)) {
addPreferencesFromResource(R.xml.cdma_call_privacy);
}
} else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
- if (getResources().getBoolean(
- R.bool.config_additional_call_setting)) {
+ if (getResources().getBoolean(R.bool.config_additional_call_setting)) {
addPreferencesFromResource(R.xml.gsm_umts_call_options);
}
} else {
@@ -1663,16 +1625,16 @@
mVMProviderSettingsForced = false;
createSipCallSettings();
- mRingtoneLookupRunnable = new Runnable() {
+ mVoicemailRingtoneLookupRunnable = new Runnable() {
@Override
public void run() {
- if (mRingtonePreference != null) {
- updateRingtoneName(RingtoneManager.TYPE_RINGTONE, mRingtonePreference,
- MSG_UPDATE_RINGTONE_SUMMARY);
- }
if (mVoicemailNotificationRingtone != null) {
- updateRingtoneName(RingtoneManager.TYPE_NOTIFICATION,
- mVoicemailNotificationRingtone, MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
+ SettingsUtil.updateRingtoneName(
+ mPhone.getContext(),
+ mVoicemailRingtoneLookupComplete,
+ RingtoneManager.TYPE_NOTIFICATION,
+ mVoicemailNotificationRingtone,
+ MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
}
}
};
@@ -1692,65 +1654,6 @@
}
}
- /**
- * Updates ringtone name. This is a method copied from com.android.settings.SoundSettings
- *
- * @see com.android.settings.SoundSettings
- */
- private void updateRingtoneName(int type, Preference preference, int msg) {
- if (preference == null) return;
- final Uri ringtoneUri;
- boolean defaultRingtone = false;
- if (type == RingtoneManager.TYPE_RINGTONE) {
- // For ringtones, we can just lookup the system default because changing the settings
- // in Call Settings changes the system default.
- ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(this, type);
- } else {
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
- mPhone.getContext());
- // for voicemail notifications, we use the value saved in Phone's shared preferences.
- String uriString = prefs.getString(preference.getKey(), null);
- if (TextUtils.isEmpty(uriString)) {
- // silent ringtone
- ringtoneUri = null;
- } else {
- if (uriString.equals(Settings.System.DEFAULT_NOTIFICATION_URI.toString())) {
- // If it turns out that the voicemail notification is set to the system
- // default notification, we retrieve the actual URI to prevent it from showing
- // up as "Unknown Ringtone".
- defaultRingtone = true;
- ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(this, type);
- } else {
- ringtoneUri = Uri.parse(uriString);
- }
- }
- }
- CharSequence summary = getString(com.android.internal.R.string.ringtone_unknown);
- // Is it a silent ringtone?
- if (ringtoneUri == null) {
- summary = getString(com.android.internal.R.string.ringtone_silent);
- } else {
- // Fetch the ringtone title from the media provider
- try {
- Cursor cursor = getContentResolver().query(ringtoneUri,
- new String[] { MediaStore.Audio.Media.TITLE }, null, null, null);
- if (cursor != null) {
- if (cursor.moveToFirst()) {
- summary = cursor.getString(0);
- }
- cursor.close();
- }
- } catch (SQLiteException sqle) {
- // Unknown title for the ringtone
- }
- }
- if (defaultRingtone) {
- summary = mPhone.getContext().getString(
- R.string.default_notification_description, summary);
- }
- mRingtoneLookupComplete.sendMessage(mRingtoneLookupComplete.obtainMessage(msg, summary));
- }
-
private void createSipCallSettings() {
// Add Internet call settings.
if (SipUtil.isVoipSupported(this)) {
@@ -1779,8 +1682,8 @@
findPreference(BUTTON_SIP_CALL_OPTIONS);
ListPreference wifiOnly = (ListPreference)
findPreference(BUTTON_SIP_CALL_OPTIONS_WIFI_ONLY);
- PreferenceGroup sipSettings = (PreferenceGroup)
- findPreference(SIP_SETTINGS_CATEGORY_KEY);
+ PreferenceScreen sipSettings = (PreferenceScreen)
+ getPreferenceScreen().findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
if (SipManager.isSipWifiOnly(this)) {
sipSettings.removePreference(wifiAnd3G);
return wifiOnly;
@@ -1796,7 +1699,7 @@
mForeground = true;
if (isAirplaneModeOn()) {
- Preference sipSettings = findPreference(SIP_SETTINGS_CATEGORY_KEY);
+ Preference sipSettings = findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
PreferenceScreen screen = getPreferenceScreen();
int count = screen.getPreferenceCount();
for (int i = 0 ; i < count ; ++i) {
@@ -1806,10 +1709,6 @@
return;
}
- if (mVibrateWhenRinging != null) {
- mVibrateWhenRinging.setChecked(getVibrateWhenRinging(this));
- }
-
if (mButtonDTMF != null) {
int dtmf = Settings.System.getInt(getContentResolver(),
Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, Constants.DTMF_TONE_TYPE_NORMAL);
@@ -1842,7 +1741,8 @@
BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false));
}
- lookupRingtoneName();
+ // Look up the voicemail ringtone name asynchronously and update its preference.
+ new Thread(mVoicemailRingtoneLookupRunnable).start();
}
// Migrate settings from BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY to
@@ -1864,28 +1764,6 @@
return false;
}
- /**
- * Obtain the setting for "vibrate when ringing" setting.
- *
- * Watch out: if the setting is missing in the device, this will try obtaining the old
- * "vibrate on ring" setting from AudioManager, and save the previous setting to the new one.
- */
- public static boolean getVibrateWhenRinging(Context context) {
- Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- if (vibrator == null || !vibrator.hasVibrator()) {
- return false;
- }
- return Settings.System.getInt(context.getContentResolver(),
- Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
- }
-
- /**
- * Lookups ringtone name asynchronously and updates the relevant Preference.
- */
- private void lookupRingtoneName() {
- new Thread(mRingtoneLookupRunnable).start();
- }
-
private boolean isAirplaneModeOn() {
return Settings.System.getInt(getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
diff --git a/src/com/android/phone/DefaultRingtonePreference.java b/src/com/android/phone/DefaultRingtonePreference.java
deleted file mode 100644
index 8205fd0..0000000
--- a/src/com/android/phone/DefaultRingtonePreference.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2012 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.content.Context;
-import android.content.Intent;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.preference.RingtonePreference;
-import android.util.AttributeSet;
-
-/**
- * RingtonePreference which doesn't show default ringtone setting.
- *
- * @see com.android.settings.DefaultRingtonePreference
- */
-public class DefaultRingtonePreference extends RingtonePreference {
- public DefaultRingtonePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
- super.onPrepareRingtonePickerIntent(ringtonePickerIntent);
-
- /*
- * Since this preference is for choosing the default ringtone, it
- * doesn't make sense to show a 'Default' item.
- */
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
- }
-
- @Override
- protected void onSaveRingtone(Uri ringtoneUri) {
- RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri);
- }
-
- @Override
- protected Uri onRestoreRingtone() {
- return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType());
- }
-}
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index e84805f..bed49a9 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -44,6 +44,7 @@
import android.widget.EditText;
import com.android.phone.common.HapticFeedback;
+import com.android.phone.common.dialpad.DialpadKeyButton;
import com.android.phone.common.util.ViewUtil;
@@ -65,7 +66,8 @@
* also?
*/
public class EmergencyDialer extends Activity implements View.OnClickListener,
- View.OnLongClickListener, View.OnHoverListener, View.OnKeyListener, TextWatcher {
+ View.OnLongClickListener, View.OnKeyListener, TextWatcher,
+ DialpadKeyButton.OnPressedListener {
// Keys used with onSaveInstanceState().
private static final String LAST_NUMBER = "lastNumber";
@@ -287,9 +289,8 @@
private void setupKeypad() {
// Setup the listeners for the buttons
for (int id : DIALER_KEYS) {
- final View key = findViewById(id);
- key.setOnClickListener(this);
- key.setOnHoverListener(this);
+ final DialpadKeyButton key = (DialpadKeyButton) findViewById(id);
+ key.setOnPressedListener(this);
}
View view = findViewById(R.id.zero);
@@ -344,6 +345,30 @@
@Override
public void onClick(View view) {
switch (view.getId()) {
+ case R.id.deleteButton: {
+ keyPressed(KeyEvent.KEYCODE_DEL);
+ return;
+ }
+ case R.id.floating_action_button: {
+ mHaptic.vibrate(); // Vibrate here too, just like we do for the regular keys
+ placeCall();
+ return;
+ }
+ case R.id.digits: {
+ if (mDigits.length() != 0) {
+ mDigits.setCursorVisible(true);
+ }
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void onPressed(View view, boolean pressed) {
+ if (!pressed) {
+ return;
+ }
+ switch (view.getId()) {
case R.id.one: {
playTone(ToneGenerator.TONE_DTMF_1);
keyPressed(KeyEvent.KEYCODE_1);
@@ -404,59 +429,10 @@
keyPressed(KeyEvent.KEYCODE_STAR);
return;
}
- case R.id.deleteButton: {
- keyPressed(KeyEvent.KEYCODE_DEL);
- return;
- }
- case R.id.floating_action_button: {
- mHaptic.vibrate(); // Vibrate here too, just like we do for the regular keys
- placeCall();
- return;
- }
- case R.id.digits: {
- if (mDigits.length() != 0) {
- mDigits.setCursorVisible(true);
- }
- return;
- }
}
}
/**
- * Implemented for {@link android.view.View.OnHoverListener}. Handles touch
- * events for accessibility when touch exploration is enabled.
- */
- @Override
- public boolean onHover(View v, MotionEvent event) {
- // When touch exploration is turned on, lifting a finger while inside
- // the button's hover target bounds should perform a click action.
- if (mAccessibilityManager.isEnabled()
- && mAccessibilityManager.isTouchExplorationEnabled()) {
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_HOVER_ENTER:
- // Lift-to-type temporarily disables double-tap activation.
- v.setClickable(false);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- final int left = v.getPaddingLeft();
- final int right = (v.getWidth() - v.getPaddingRight());
- final int top = v.getPaddingTop();
- final int bottom = (v.getHeight() - v.getPaddingBottom());
- final int x = (int) event.getX();
- final int y = (int) event.getY();
- if ((x > left) && (x < right) && (y > top) && (y < bottom)) {
- v.performClick();
- }
- v.setClickable(true);
- break;
- }
- }
-
- return false;
- }
-
- /**
* called for long touch events
*/
@Override
diff --git a/src/com/android/phone/GsmUmtsOptions.java b/src/com/android/phone/GsmUmtsOptions.java
index 6791f27..8964cb5 100644
--- a/src/com/android/phone/GsmUmtsOptions.java
+++ b/src/com/android/phone/GsmUmtsOptions.java
@@ -16,12 +16,13 @@
package com.android.phone;
+import android.content.Intent;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.content.res.Resources;
-import com.android.internal.telephony.Phone;
+import android.provider.Settings;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
@@ -49,6 +50,7 @@
protected void create() {
mPrefActivity.addPreferencesFromResource(R.xml.gsm_umts_options);
mButtonAPNExpand = (PreferenceScreen) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+ boolean removedAPNExpand = false;
mButtonOperatorSelectionExpand =
(PreferenceScreen) mPrefScreen.findPreference(BUTTON_OPERATOR_SELECTION_EXPAND_KEY);
if (PhoneFactory.getDefaultPhone().getPhoneType() != PhoneConstants.PHONE_TYPE_GSM) {
@@ -62,9 +64,10 @@
// Determine which options to display, for GSM these are defaulted
// are defaulted to true in Phone/res/values/config.xml. But for
// some operators like verizon they maybe overriden in operator
- // specific resources or device specifc overlays.
- if (!res.getBoolean(R.bool.config_apn_expand)) {
- mPrefScreen.removePreference(mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY));
+ // specific resources or device specific overlays.
+ if (!res.getBoolean(R.bool.config_apn_expand) && mButtonAPNExpand != null) {
+ mPrefScreen.removePreference(mButtonAPNExpand);
+ removedAPNExpand = true;
}
if (!res.getBoolean(R.bool.config_operator_selection_expand)) {
mPrefScreen.removePreference(mPrefScreen
@@ -92,6 +95,22 @@
}
}
}
+ if (!removedAPNExpand) {
+ mButtonAPNExpand.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ // We need to build the Intent by hand as the Preference Framework
+ // does not allow to add an Intent with some extras into a Preference
+ // XML file
+ final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
+ // This will setup the Home and Search affordance
+ intent.putExtra(":settings:show_fragment_as_subsetting", true);
+ mPrefActivity.startActivity(intent);
+ return true;
+ }
+ });
+ }
}
public boolean preferenceTreeClick(Preference preference) {
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 637b429..89749ad 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -16,7 +16,6 @@
package com.android.phone;
-import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.ims.ImsException;
import com.android.internal.telephony.Phone;
@@ -24,8 +23,6 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
-import java.util.Map;
-
import android.app.ActionBar;
import android.app.AlertDialog;
import android.content.Context;
@@ -41,10 +38,8 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
-import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
@@ -199,13 +194,6 @@
}
}
- public boolean isIMSOn() {
- SharedPreferences imsPref =
- getSharedPreferences(ImsManager.IMS_SHARED_PREFERENCES, Context.MODE_WORLD_READABLE);
-
- return imsPref.getBoolean(ImsManager.KEY_IMS_ON, true);
- }
-
private void setIMS(boolean turnOn) {
SharedPreferences imsPref =
getSharedPreferences(ImsManager.IMS_SHARED_PREFERENCES, Context.MODE_WORLD_READABLE);
@@ -233,7 +221,7 @@
mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY);
mButton4glte.setOnPreferenceChangeListener(this);
- mButton4glte.setChecked(isIMSOn());
+ mButton4glte.setChecked(ImsManager.isEnhanced4gLteModeSettingEnabledByUser(this));
try {
Context con = createPackageContext("com.android.systemui", 0);
@@ -350,6 +338,13 @@
prefSet.removePreference(pref);
}
}
+ Preference pref = prefSet.findPreference(BUTTON_4G_LTE_KEY);
+ if (pref != null) {
+ if (!ImsManager.isEnhanced4gLteModeSettingEnabledByPlatform(this)) {
+ ((SwitchPreference)pref).setChecked(false);
+ pref.setEnabled(false);
+ }
+ }
ActionBar actionBar = getActionBar();
if (actionBar != null) {
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 39df173..6650892 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -341,7 +341,8 @@
.setContentTitle(notificationTitle)
.setContentText(notificationText)
.setContentIntent(pendingIntent)
- .setSound(ringtoneUri);
+ .setSound(ringtoneUri)
+ .setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
Notification notification = builder.getNotification();
CallFeaturesSetting.migrateVoicemailVibrationSettingsIfNeeded(prefs);
@@ -428,6 +429,7 @@
final Notification.Builder builder = new Notification.Builder(mContext);
builder.setSmallIcon(android.R.drawable.stat_sys_warning);
builder.setContentTitle(mContext.getText(R.string.roaming));
+ builder.setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
builder.setContentText(contentText);
builder.setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0));
diff --git a/src/com/android/phone/Ringer.java b/src/com/android/phone/Ringer.java
index 668f8dc..b542ede 100644
--- a/src/com/android/phone/Ringer.java
+++ b/src/com/android/phone/Ringer.java
@@ -36,6 +36,8 @@
import android.util.Log;
import com.android.internal.telephony.Phone;
+import com.android.phone.common.util.SettingsUtil;
+
/**
* Ringer manager for the Phone app.
*/
@@ -210,7 +212,7 @@
boolean shouldVibrate() {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
int ringerMode = audioManager.getRingerMode();
- if (CallFeaturesSetting.getVibrateWhenRinging(mContext)) {
+ if (SettingsUtil.getVibrateWhenRingingSetting(mContext)) {
return ringerMode != AudioManager.RINGER_MODE_SILENT;
} else {
return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
diff --git a/src/com/android/services/telephony/ConferenceConnection.java b/src/com/android/services/telephony/ConferenceConnection.java
deleted file mode 100644
index 33be0be..0000000
--- a/src/com/android/services/telephony/ConferenceConnection.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2014 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.services.telephony;
-
-import android.telecomm.Connection;
-import android.telephony.DisconnectCause;
-
-import com.android.internal.telephony.CallStateException;
-
-import java.util.List;
-
-/**
- * Manages state for a conference call.
- */
-final class ConferenceConnection extends Connection {
- @Override
- public void onChildrenChanged(List<Connection> children) {
- if (children.isEmpty()) {
- setDisconnected(DisconnectCause.LOCAL, "conference call disconnected.");
- destroy();
- }
- }
-
- /** ${inheritDoc} */
- @Override
- public void onDisconnect() {
- // For conference-level disconnects, we need to make sure we disconnect the entire call,
- // not just one of the connections. To do this, we go through the children and get a
- // reference to the telephony-Call object and call hangup().
- for (Connection connection : getChildConnections()) {
- if (connection instanceof TelephonyConnection) {
- com.android.internal.telephony.Connection origConnection =
- ((TelephonyConnection) connection).getOriginalConnection();
- if (origConnection != null && origConnection.getCall() != null) {
- try {
- // getCall() returns what is the parent call of all conferenced conections
- // so we only need to call hangup on the main call object. Break once we've
- // done that.
- origConnection.getCall().hangup();
- break;
- } catch (CallStateException e) {
- Log.e(this, e, "Call state exception in conference hangup.");
- }
- }
- }
- }
- }
-
- /** ${inheritDoc} */
- @Override
- public void onHold() {
- for (Connection connection : getChildConnections()) {
- if (connection instanceof TelephonyConnection) {
- ((TelephonyConnection) connection).onHold();
- // Hold only needs to be called on one of the children.
- break;
- }
- }
- }
-}
diff --git a/src/com/android/services/telephony/EmergencyCallHelper.java b/src/com/android/services/telephony/EmergencyCallHelper.java
index 5b3ebfc..c64a649 100644
--- a/src/com/android/services/telephony/EmergencyCallHelper.java
+++ b/src/com/android/services/telephony/EmergencyCallHelper.java
@@ -46,7 +46,7 @@
}
// Number of times to retry the call, and time between retry attempts.
- public static final int MAX_NUM_RETRIES = 6;
+ public static final int MAX_NUM_RETRIES = 5;
public static final long TIME_BETWEEN_RETRIES_MILLIS = 5000; // msec
// Handler message codes; see handleMessage()
@@ -180,9 +180,13 @@
private boolean isOkToCall(int serviceState, PhoneConstants.State phoneState) {
// Once we reach either STATE_IN_SERVICE or STATE_EMERGENCY_ONLY, it's finally OK to place
// the emergency call.
- return (phoneState == PhoneConstants.State.OFFHOOK)
+ return ((phoneState == PhoneConstants.State.OFFHOOK)
|| (serviceState == ServiceState.STATE_IN_SERVICE)
- || (serviceState == ServiceState.STATE_EMERGENCY_ONLY);
+ || (serviceState == ServiceState.STATE_EMERGENCY_ONLY)) ||
+
+ // Allow STATE_OUT_OF_SERVICE if we are at the max number of retries.
+ (mNumRetriesSoFar == MAX_NUM_RETRIES &&
+ serviceState == ServiceState.STATE_OUT_OF_SERVICE);
}
/**
diff --git a/src/com/android/services/telephony/GsmConference.java b/src/com/android/services/telephony/GsmConference.java
new file mode 100644
index 0000000..d8bc11b
--- /dev/null
+++ b/src/com/android/services/telephony/GsmConference.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014 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.services.telephony;
+
+import android.telecomm.PhoneCapabilities;
+import android.telecomm.Conference;
+import android.telecomm.Connection;
+import android.telecomm.PhoneAccountHandle;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+
+import java.util.List;
+
+/**
+ * GSM-based conference call.
+ */
+public class GsmConference extends Conference {
+
+ public GsmConference(PhoneAccountHandle phoneAccount) {
+ super(phoneAccount);
+ setCapabilities(
+ PhoneCapabilities.SUPPORT_HOLD |
+ PhoneCapabilities.HOLD |
+ PhoneCapabilities.MUTE |
+ PhoneCapabilities.SWAP_CALLS);
+ setActive();
+ }
+
+ /**
+ * Invoked when the Conference and all it's {@link Connection}s should be disconnected.
+ */
+ @Override
+ public void onDisconnect() {
+ for (Connection connection : getConnections()) {
+ Call call = getMultipartyCallForConnection(connection, "onDisconnect");
+ if (call != null) {
+ try {
+ call.hangup();
+ } catch (CallStateException e) {
+ Log.e(this, e, "Exception thrown trying to hangup conference");
+ }
+ }
+ }
+ }
+
+ /**
+ * Invoked when the specified {@link Connection} should be separated from the conference call.
+ *
+ * @param connection The connection to separate.
+ */
+ @Override
+ public void onSeparate(Connection connection) {
+ com.android.internal.telephony.Connection radioConnection =
+ getOriginalConnection(connection, "onSeparate");
+ try {
+ radioConnection.separate();
+ } catch (CallStateException e) {
+ Log.e(this, e, "Exception thrown trying to separate a conference call");
+ }
+ }
+
+ /**
+ * Invoked when the conference should be put on hold.
+ */
+ @Override
+ public void onHold() {
+ List<Connection> connections = getConnections();
+ if (connections.isEmpty()) {
+ return;
+ }
+ ((GsmConnection) connections.get(0)).performHold();
+ }
+
+ /**
+ * Invoked when the conference should be moved from hold to active.
+ */
+ @Override
+ public void onUnhold() {
+ List<Connection> connections = getConnections();
+ if (connections.isEmpty()) {
+ return;
+ }
+ ((GsmConnection) connections.get(0)).performUnhold();
+ }
+
+ private Call getMultipartyCallForConnection(Connection connection, String tag) {
+ com.android.internal.telephony.Connection radioConnection =
+ getOriginalConnection(connection, tag);
+ if (radioConnection != null) {
+ Call call = radioConnection.getCall();
+ if (call != null && call.isMultiparty()) {
+ return call;
+ }
+ }
+ return null;
+ }
+
+ private com.android.internal.telephony.Connection getOriginalConnection(
+ Connection connection, String tag) {
+
+ if (connection instanceof GsmConnection) {
+ return ((GsmConnection) connection).getOriginalConnection();
+ } else {
+ Log.e(this, null, "Non GSM connection found in a Gsm conference (%s)", tag);
+ return null;
+ }
+ }
+}
diff --git a/src/com/android/services/telephony/GsmConferenceController.java b/src/com/android/services/telephony/GsmConferenceController.java
index a69d1e6..e3d0bf5 100644
--- a/src/com/android/services/telephony/GsmConferenceController.java
+++ b/src/com/android/services/telephony/GsmConferenceController.java
@@ -17,82 +17,61 @@
package com.android.services.telephony;
import java.util.ArrayList;
-
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import android.telecomm.Conference;
import android.telecomm.Connection;
+import com.android.internal.telephony.Call;
+
/**
* Maintains a list of all the known GSM connections and implements GSM-specific conference
* call functionality.
*/
final class GsmConferenceController {
- private static GsmConferenceController sInstance;
-
private final Connection.Listener mConnectionListener = new Connection.Listener() {
@Override
public void onStateChanged(Connection c, int state) {
- // No need to recalculate for conference calls, just traditional calls.
- if (c != mGsmConferenceConnection) {
- recalculate();
- }
+ recalculate();
}
/** ${inheritDoc} */
@Override
public void onDisconnected(Connection c, int cause, String message) {
- // When a connection disconnects, make sure to release its parent reference
- // so that the parent can move to disconnected as well.
- c.setParentConnection(null);
+ recalculate();
}
};
/** The known GSM connections. */
private final List<GsmConnection> mGsmConnections = new ArrayList<>();
+ private final TelephonyConnectionService mConnectionService;
+
+ public GsmConferenceController(TelephonyConnectionService connectionService) {
+ mConnectionService = connectionService;
+ }
+
/** The GSM conference connection object. */
- private ConferenceConnection mGsmConferenceConnection;
+ private Conference mGsmConference;
- static void add(GsmConnection connection) {
- if (sInstance == null) {
- sInstance = new GsmConferenceController();
- }
- connection.addConnectionListener(sInstance.mConnectionListener);
- sInstance.mGsmConnections.add(connection);
- sInstance.recalculate();
+ void add(GsmConnection connection) {
+ mGsmConnections.add(connection);
+ connection.addConnectionListener(mConnectionListener);
+ recalculate();
}
- static void remove(GsmConnection connection) {
- if (sInstance != null) {
- connection.removeConnectionListener(sInstance.mConnectionListener);
- sInstance.mGsmConnections.remove(connection);
- sInstance.recalculate();
-
- if (sInstance.mGsmConnections.size() == 0 &&
- sInstance.mGsmConferenceConnection == null) {
- sInstance = null;
- }
- }
- }
-
- static ConferenceConnection createConferenceConnection(Connection rootConnection) {
- if (sInstance != null) {
- if (sInstance.mGsmConferenceConnection == null) {
- sInstance.mGsmConferenceConnection = new ConferenceConnection();
- Log.d(sInstance, "creating the conference connection: %s",
- sInstance.mGsmConferenceConnection);
- }
- if (rootConnection instanceof GsmConnection) {
- ((GsmConnection) rootConnection).performConference();
- }
- return sInstance.mGsmConferenceConnection;
- }
- return null;
+ void remove(GsmConnection connection) {
+ connection.removeConnectionListener(mConnectionListener);
+ mGsmConnections.remove(connection);
+ recalculate();
}
private void recalculate() {
recalculateConferenceable();
+ recalculateConference();
}
/**
@@ -141,5 +120,60 @@
for (Connection connection : backgroundConnections) {
connection.setConferenceableConnections(activeConnections);
}
+ // TODO: Do not allow conferencing of already conferenced connections.
+ }
+
+ private void recalculateConference() {
+ Set<GsmConnection> conferencedConnections = new HashSet<>();
+
+ for (GsmConnection connection : mGsmConnections) {
+ com.android.internal.telephony.Connection radioConnection =
+ connection.getOriginalConnection();
+
+ if (radioConnection != null) {
+ Call.State state = radioConnection.getState();
+ Call call = radioConnection.getCall();
+ if ((state == Call.State.ACTIVE || state == Call.State.HOLDING) &&
+ (call != null && call.isMultiparty())) {
+ conferencedConnections.add(connection);
+ }
+ }
+ }
+
+ Log.d(this, "Recalculate conference calls %s %s.",
+ mGsmConference, conferencedConnections);
+
+ if (conferencedConnections.size() < 2) {
+ Log.d(this, "less than two conference calls!");
+ // No more connections are conferenced, destroy any existing conference.
+ if (mGsmConference != null) {
+ Log.d(this, "with a conference to destroy!");
+ mGsmConference.destroy();
+ mGsmConference = null;
+ }
+ } else {
+ if (mGsmConference != null) {
+ List<Connection> existingConnections = mGsmConference.getConnections();
+ // Remove any that no longer exist
+ for (Connection connection : existingConnections) {
+ if (!conferencedConnections.contains(connection)) {
+ mGsmConference.removeConnection(connection);
+ }
+ }
+
+ // Add any new ones
+ for (Connection connection : conferencedConnections) {
+ if (!existingConnections.contains(connection)) {
+ mGsmConference.addConnection(connection);
+ }
+ }
+ } else {
+ mGsmConference = new GsmConference(null);
+ for (Connection connection : conferencedConnections) {
+ mGsmConference.addConnection(connection);
+ }
+ mConnectionService.addConference(mGsmConference);
+ }
+ }
}
}
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index 5140574..99f2cde 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -29,7 +29,6 @@
GsmConnection(Connection connection) {
super(connection);
- GsmConferenceController.add(this);
}
/** {@inheritDoc} */
@@ -55,10 +54,16 @@
}
}
- void performConference() {
+ @Override
+ public void performConference(TelephonyConnection otherConnection) {
Log.d(this, "performConference - %s", this);
if (getPhone() != null) {
try {
+ // We dont use the "other" connection because there is no concept of that in the
+ // implementation of calls inside telephony. Basically, you can "conference" and it
+ // will conference with the background call. We know that otherConnection is the
+ // background call because it would never have called setConferenceableConnections()
+ // otherwise.
getPhone().conference();
} catch (CallStateException e) {
Log.e(this, e, "Failed to conference call.");
@@ -81,6 +86,5 @@
@Override
void onRemovedFromCallService() {
super.onRemovedFromCallService();
- GsmConferenceController.remove(this);
}
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 7ddb6d0..adb430c 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -31,7 +31,6 @@
import com.android.internal.telephony.Phone;
import java.lang.Override;
-import java.util.List;
import java.util.Objects;
/**
@@ -204,51 +203,12 @@
@Override
public void onHold() {
- Log.v(this, "onHold");
- // TODO: Can dialing calls be put on hold as well since they take up the
- // foreground call slot?
- if (Call.State.ACTIVE == mOriginalConnectionState) {
- Log.v(this, "Holding active call");
- try {
- Phone phone = mOriginalConnection.getCall().getPhone();
- Call ringingCall = phone.getRingingCall();
-
- // Although the method says switchHoldingAndActive, it eventually calls a RIL method
- // called switchWaitingOrHoldingAndActive. What this means is that if we try to put
- // a call on hold while a call-waiting call exists, it'll end up accepting the
- // call-waiting call, which is bad if that was not the user's intention. We are
- // cheating here and simply skipping it because we know any attempt to hold a call
- // while a call-waiting call is happening is likely a request from Telecomm prior to
- // accepting the call-waiting call.
- // TODO: Investigate a better solution. It would be great here if we
- // could "fake" hold by silencing the audio and microphone streams for this call
- // instead of actually putting it on hold.
- if (ringingCall.getState() != Call.State.WAITING) {
- phone.switchHoldingAndActive();
- }
-
- // TODO: Cdma calls are slightly different.
- } catch (CallStateException e) {
- Log.e(this, e, "Exception occurred while trying to put call on hold.");
- }
- } else {
- Log.w(this, "Cannot put a call that is not currently active on hold.");
- }
+ performHold();
}
@Override
public void onUnhold() {
- Log.v(this, "onUnhold");
- if (Call.State.HOLDING == mOriginalConnectionState) {
- try {
- // TODO: This doesn't handle multiple calls across connection services yet
- mOriginalConnection.getCall().getPhone().switchHoldingAndActive();
- } catch (CallStateException e) {
- Log.e(this, e, "Exception occurred while trying to release call from hold.");
- }
- } else {
- Log.w(this, "Cannot release a call that is not already on hold from hold.");
- }
+ performUnhold();
}
@Override
@@ -288,15 +248,59 @@
}
@Override
- public void onChildrenChanged(List<Connection> children) {
- Log.v(this, "onChildrenChanged, children: " + children);
- }
-
- @Override
public void onPhoneAccountClicked() {
Log.v(this, "onPhoneAccountClicked");
}
+ public void performHold() {
+ Log.v(this, "performHold");
+ // TODO: Can dialing calls be put on hold as well since they take up the
+ // foreground call slot?
+ if (Call.State.ACTIVE == mOriginalConnectionState) {
+ Log.v(this, "Holding active call");
+ try {
+ Phone phone = mOriginalConnection.getCall().getPhone();
+ Call ringingCall = phone.getRingingCall();
+
+ // Although the method says switchHoldingAndActive, it eventually calls a RIL method
+ // called switchWaitingOrHoldingAndActive. What this means is that if we try to put
+ // a call on hold while a call-waiting call exists, it'll end up accepting the
+ // call-waiting call, which is bad if that was not the user's intention. We are
+ // cheating here and simply skipping it because we know any attempt to hold a call
+ // while a call-waiting call is happening is likely a request from Telecomm prior to
+ // accepting the call-waiting call.
+ // TODO: Investigate a better solution. It would be great here if we
+ // could "fake" hold by silencing the audio and microphone streams for this call
+ // instead of actually putting it on hold.
+ if (ringingCall.getState() != Call.State.WAITING) {
+ phone.switchHoldingAndActive();
+ }
+
+ // TODO: Cdma calls are slightly different.
+ } catch (CallStateException e) {
+ Log.e(this, e, "Exception occurred while trying to put call on hold.");
+ }
+ } else {
+ Log.w(this, "Cannot put a call that is not currently active on hold.");
+ }
+ }
+
+ public void performUnhold() {
+ Log.v(this, "performUnhold");
+ if (Call.State.HOLDING == mOriginalConnectionState) {
+ try {
+ // TODO: This doesn't handle multiple calls across connection services yet
+ mOriginalConnection.getCall().getPhone().switchHoldingAndActive();
+ } catch (CallStateException e) {
+ Log.e(this, e, "Exception occurred while trying to release call from hold.");
+ }
+ } else {
+ Log.w(this, "Cannot release a call that is not already on hold from hold.");
+ }
+ }
+
+ public void performConference(TelephonyConnection otherConnection) {}
+
protected abstract int buildCallCapabilities();
protected final void updateCallCapabilities() {
@@ -356,19 +360,15 @@
private void hangup(int disconnectCause) {
if (mOriginalConnection != null) {
try {
- Call call = mOriginalConnection.getCall();
- if (call != null && !call.isMultiparty()) {
- call.hangup();
- } else {
- mOriginalConnection.hangup();
- }
- // Set state deliberately since we are going to close() and will no longer be
- // listening to state updates from mOriginalConnection
- setDisconnected(disconnectCause, null);
+ mOriginalConnection.hangup();
} catch (CallStateException e) {
Log.e(this, e, "Call to Connection.hangup failed with exception");
}
}
+
+ // Set state deliberately since we are going to close() and will no longer be
+ // listening to state updates from mOriginalConnection
+ setDisconnected(disconnectCause, null);
close();
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index bfae89e..7c4d1ae 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -47,6 +47,8 @@
public class TelephonyConnectionService extends ConnectionService {
static String SCHEME_TEL = "tel";
+ private final GsmConferenceController mGsmConferenceController =
+ new GsmConferenceController(this);
private ComponentName mExpectedComponentName = null;
private EmergencyCallHelper mEmergencyCallHelper;
@@ -93,8 +95,14 @@
"Phone is null");
}
- if (!isEmergencyNumber) {
- int state = phone.getServiceState().getState();
+ int state = phone.getServiceState().getState();
+ boolean useEmergencyCallHelper = false;
+
+ if (isEmergencyNumber) {
+ if (state == ServiceState.STATE_POWER_OFF) {
+ useEmergencyCallHelper = true;
+ }
+ } else {
switch (state) {
case ServiceState.STATE_IN_SERVICE:
case ServiceState.STATE_EMERGENCY_ONLY:
@@ -119,10 +127,9 @@
}
connection.setHandle(handle, PhoneConstants.PRESENTATION_ALLOWED);
connection.setInitializing();
+ connection.setVideoState(request.getVideoState());
- if (isEmergencyNumber) {
- Log.d(this, "onCreateOutgoingConnection, doing startTurnOnRadioSequence for " +
- "emergency number");
+ if (useEmergencyCallHelper) {
if (mEmergencyCallHelper == null) {
mEmergencyCallHelper = new EmergencyCallHelper(this);
}
@@ -130,13 +137,16 @@
new EmergencyCallHelper.Callback() {
@Override
public void onComplete(boolean isRadioReady) {
- if (isRadioReady) {
+ if (connection.getState() == Connection.STATE_DISCONNECTED) {
+ // If the connection has already been disconnected, do nothing.
+ } else if (isRadioReady) {
connection.setInitialized();
placeOutgoingConnection(connection, phone, request);
} else {
Log.d(this, "onCreateOutgoingConnection, failed to turn on radio");
- connection.setFailed(DisconnectCause.POWER_OFF,
+ connection.setDisconnected(DisconnectCause.POWER_OFF,
"Failed to turn on radio.");
+ connection.destroy();
}
}
});
@@ -149,20 +159,6 @@
}
@Override
- public void onCreateConferenceConnection(
- String token,
- Connection connection,
- Response<String, Connection> response) {
- Log.v(this, "onCreateConferenceConnection, connection: " + connection);
- if (connection instanceof GsmConnection || connection instanceof ConferenceConnection) {
- if ((connection.getCallCapabilities() & PhoneCapabilities.MERGE_CALLS) != 0) {
- response.onResult(token,
- GsmConferenceController.createConferenceConnection(connection));
- }
- }
- }
-
- @Override
public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
ConnectionRequest request) {
@@ -195,6 +191,30 @@
}
}
+ @Override
+ public void onConference(Connection connection1, Connection connection2) {
+ if (connection1 instanceof TelephonyConnection &&
+ connection2 instanceof TelephonyConnection) {
+ ((TelephonyConnection) connection1).performConference(
+ (TelephonyConnection) connection2);
+ }
+
+ }
+
+ @Override
+ public void onConnectionAdded(Connection connection) {
+ if (connection instanceof GsmConnection) {
+ mGsmConferenceController.add((GsmConnection) connection);
+ }
+ }
+
+ @Override
+ public void onConnectionRemoved(Connection connection) {
+ if (connection instanceof GsmConnection) {
+ mGsmConferenceController.remove((GsmConnection) connection);
+ }
+ }
+
private void placeOutgoingConnection(
TelephonyConnection connection, Phone phone, ConnectionRequest request) {
String number = connection.getHandle().getSchemeSpecificPart();
@@ -204,7 +224,7 @@
originalConnection = phone.dial(number, request.getVideoState());
} catch (CallStateException e) {
Log.e(this, e, "placeOutgoingConnection, phone.dial exception: " + e);
- connection.setFailed(DisconnectCause.OUTGOING_FAILURE, e.getMessage());
+ connection.setDisconnected(DisconnectCause.OUTGOING_FAILURE, e.getMessage());
return;
}
@@ -221,7 +241,7 @@
startActivity(intent);
}
Log.d(this, "placeOutgoingConnection, phone.dial returned null");
- connection.setFailed(disconnectCause, "Connection is null");
+ connection.setDisconnected(disconnectCause, "Connection is null");
} else {
connection.setOriginalConnection(originalConnection);
}