Merge "Reorganize phone account settings." into lmp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 09c3aae..e779771 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -511,12 +511,6 @@
android:configChanges="orientation|screenSize|keyboardHidden"
android:uiOptions="splitActionBarWhenNarrow">
</activity>
- <activity android:name="com.android.services.telephony.sip.SipProfileChooserDialogs"
- android:theme="@style/SipCallOptionHandlerTheme"
- android:screenOrientation="nosensor"
- android:configChanges="orientation|screenSize|keyboardHidden"
- android:excludeFromRecents="true">
- </activity>
<!-- End SIP -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 291cfc5..bc77128 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -277,10 +277,6 @@
<item name="*android:windowAnimationStyle">@style/OutgoingAnimationStyle</item>
</style>
- <style name="SipCallOptionHandlerTheme" parent="@android:style/Theme.Holo.NoActionBar">
- <item name="android:windowBackground">@android:color/black</item>
- </style>
-
<style name="DialtactsDigitsTextAppearance">
<item name="android:maxLines">1</item>
<item name="android:textSize">@dimen/dialpad_digits_text_size</item>
diff --git a/sip/res/values/array.xml b/sip/res/values/array.xml
index 02940e8..1f33204 100644
--- a/sip/res/values/array.xml
+++ b/sip/res/values/array.xml
@@ -36,11 +36,6 @@
<item>@string/sip_address_only</item>
</string-array>
- <string-array translatable="false" name="phone_type_values">
- <item>@string/pstn_phone</item>
- <item>@string/internet_phone</item>
- </string-array>
-
<string-array translatable="true" name="sip_send_keepalive_options">
<item>@string/sip_system_decide</item>
<item>@string/sip_always_send_keepalive</item>
diff --git a/sip/res/values/strings.xml b/sip/res/values/strings.xml
index 0163a31..b220d17 100644
--- a/sip/res/values/strings.xml
+++ b/sip/res/values/strings.xml
@@ -38,31 +38,6 @@
<!-- Item of the SIP call (Wi-Fi only) option dialog: for routing all outgoing calls via SIP. [CHAR LIMIT=NONE] -->
<string name="sip_call_options_wifi_only_entry_1">For all calls</string>
- <!-- Title of the dialog to select the phone type for the outgoing call. [CHAR LIMIT=NONE] -->
- <string name ="pick_outgoing_call_phone_type">Place call</string>
-
- <!-- Title of the dialog to select the phone among the list of phones for the outgoing call. [CHAR LIMIT=NONE] -->
- <string name ="pick_outgoing_sip_phone">Use SIP account:</string>
-
- <!-- Text of checkbox to remember the sip phone for all outbound calls. [CHAR LIMIT=NONE] -->
- <string name ="remember_my_choice">Always use to place SIP calls</string>
-
- <!-- Help text of checkbox to unset the default sip phone for all outbound calls. [CHAR LIMIT=NONE] -->
- <string name ="reset_my_choice_hint">You can change which SIP account to use by default from the Phone > Settings > SIP call settings > Accounts screen.</string>
-
- <!-- Item of the dialog to select the phone type for outgoing call. [CHAR LIMIT=NONE] -->
- <string name ="pstn_phone">Cell phone call</string>
-
- <!-- Item of the dialog to select the phone type for outgoing call. [CHAR LIMIT=NONE] -->
- <string name ="internet_phone">SIP call</string>
-
- <!-- Title of the dialog to redirect the user to SIP settings. [CHAR LIMIT=NONE] -->
- <string name ="no_sip_account_found_title">No SIP account</string>
- <!-- Message of the dialog to redirect the user to SIP settings. [CHAR LIMIT=NONE] -->
- <string name ="no_sip_account_found">There are no SIP accounts on this phone. Do you want to add one now?</string>
- <!-- Menu item for no sip account found dialog -->
- <string name="sip_menu_add">Add</string>
-
<!-- Title for the button to add a new sip account. [CHAR LIMIT=NONE] -->
<string name="add_sip_account">Add account</string>
<!-- Title for the button to remove a sip account. [CHAR LIMIT=NONE] -->
@@ -163,15 +138,11 @@
<!-- Showing that port number is out of range in an alert dialog. [CHAR LIMIT=NONE] -->
<string name="not_a_valid_port">Port number should be within 1000 and 65534.</string>
- <!-- Title of the alert dialog to notify user that there is no Internet connectivity. [CHAR LIMIT=40] -->
- <string name="no_internet_available_title">No Internet connection</string>
- <!-- Title of the alert dialog to notify user that there is no Wi-Fi connectivity. [CHAR LIMIT=40] -->
- <string name="no_wifi_available_title">No Wi-Fi connection</string>
<!-- Message of the alert dialog to notify user that there is no Internet connectivity. [CHAR LIMIT=NONE] -->
<string name="no_internet_available">To place a SIP call, check your Internet connection first.</string>
<!-- Message of the alert dialog to notify user that there is no Wi-Fi connectivity. [CHAR LIMIT=NONE] -->
<string name="no_wifi_available">You need to be connected to a Wi-Fi network for SIP calls (use the Wireless & Network settings).</string>
- <!-- Title of the alert dialog to notify user that SIP call is not supported. [CHAR LIMIT=40] -->
+ <!-- Message of the alert dialog to notify user that SIP call is not supported. [CHAR LIMIT=NONE] -->
<string name="no_voip">SIP calling not supported</string>
<!-- Option for whether the SIP service should send keepalive messages. [CHAR LIMIT=40] -->
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index a53a336..ae21d73 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -89,25 +89,21 @@
boolean attemptCall = true;
if (!SipUtil.isVoipSupported(this)) {
- SipProfileChooserDialogs.showNoVoip(this, new ResultReceiver(mHandler) {
- @Override
- protected void onReceiveResult(int choice, Bundle resultData) {
- connection.setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
- DisconnectCause.ERROR_UNSPECIFIED, "VoIP unsupported"));
- }
- });
+ final CharSequence description = getString(R.string.no_voip);
+ connection.setDisconnected(new android.telecom.DisconnectCause(
+ android.telecom.DisconnectCause.ERROR, null, description,
+ "VoIP unsupported"));
attemptCall = false;
}
if (attemptCall && !isNetworkConnected()) {
if (VERBOSE) log("start, network not connected, dropping call");
- SipProfileChooserDialogs.showNoInternetError(this, new ResultReceiver(mHandler) {
- @Override
- protected void onReceiveResult(int choice, Bundle resultData) {
- connection.setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
- DisconnectCause.OUT_OF_SERVICE, "Network not connected."));
- }
- });
+ final boolean wifiOnly = SipManager.isSipWifiOnly(this);
+ final CharSequence description = getString(wifiOnly ? R.string.no_wifi_available
+ : R.string.no_internet_available);
+ connection.setDisconnected(new android.telecom.DisconnectCause(
+ android.telecom.DisconnectCause.ERROR, null, description,
+ "Network not connected"));
attemptCall = false;
}
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java b/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java
deleted file mode 100644
index 4eb9762..0000000
--- a/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java
+++ /dev/null
@@ -1,266 +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.sip;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.sip.SipManager;
-import android.net.sip.SipProfile;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.TextView;
-
-import java.util.List;
-
-public final class SipProfileChooserDialogs extends Activity
- implements DialogInterface.OnClickListener,
- DialogInterface.OnCancelListener, CompoundButton.OnCheckedChangeListener {
- private static final String PREFIX = "[SipProfileChooserDialogs] ";
- private static final boolean VERBOSE = false; /* STOP SHIP if true */
-
- private static final String EXTRA_RESULT_RECEIVER = "result_receiver";
- private static final String EXTRA_DIALOG_ID = "dialog_id";
- private static final String EXTRA_PROFILE_NAMES = "profile_names";
- private static final String EXTRA_MAKE_PRIMARY = "make_primary";
-
- private static final int DIALOG_SELECT_PHONE_TYPE = 0;
- private static final int DIALOG_SELECT_PROFILE = 1;
- private static final int DIALOG_START_SIP_SETTINGS = 2;
- private static final int DIALOG_NO_INTERNET_ERROR = 3;
- private static final int DIALOG_NO_VOIP = 4;
-
- private TextView mUnsetPriamryHint;
- private boolean mMakePrimary;
-
- static void showSelectPhoneType(Context context, ResultReceiver resultReceiver) {
- show(context, DIALOG_SELECT_PHONE_TYPE, null, resultReceiver);
- }
-
- static void showSelectProfile(Context context, List<SipProfile> profiles,
- ResultReceiver resultReceiver) {
- show(context, DIALOG_SELECT_PROFILE, profiles, resultReceiver);
- }
-
- static void showStartSipSettings(Context context, ResultReceiver resultReceiver) {
- show(context, DIALOG_START_SIP_SETTINGS, null, resultReceiver);
- }
-
- static void showNoInternetError(Context context, ResultReceiver resultReceiver) {
- show(context, DIALOG_NO_INTERNET_ERROR, null, resultReceiver);
- }
-
- static void showNoVoip(Context context, ResultReceiver resultReceiver) {
- show(context, DIALOG_NO_VOIP, null, resultReceiver);
- }
-
- static boolean isSelectedPhoneTypeSip(Context context, int choice) {
- String[] phoneTypes = context.getResources().getStringArray(R.array.phone_type_values);
- if (choice >= 0 && choice < phoneTypes.length) {
- return phoneTypes[choice].equals(context.getString(R.string.internet_phone));
- }
- return false;
- }
-
- static boolean shouldMakeSelectedProflePrimary(Context context, Bundle extras) {
- return extras.getBoolean(EXTRA_MAKE_PRIMARY);
- }
-
- static private void show(final Context context, final int dialogId,
- final List<SipProfile> profiles,
- final ResultReceiver resultReceiver) {
- if (VERBOSE) log("show, starting delayed show, dialogId: " + dialogId);
-
- // Wait for 1 second before showing the dialog. The sometimes prevents the InCallUI from
- // popping up on top of the dialog. See http://b/16184268
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- if (VERBOSE) log("show, starting activity");
- Intent intent = new Intent(context, SipProfileChooserDialogs.class)
- .putExtra(EXTRA_RESULT_RECEIVER, resultReceiver)
- .putExtra(EXTRA_DIALOG_ID, dialogId)
- .putExtra(EXTRA_PROFILE_NAMES, getProfileNames(profiles))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- context.startActivity(intent);
- }
- }, 1000);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- int dialogId = getIntent().getIntExtra(EXTRA_DIALOG_ID, 0);
- if (VERBOSE) log("onCreate, dialogId: " + dialogId);
-
- // Allow this activity to be visible in front of the keyguard. (This is only necessary for
- // obscure scenarios like the user initiating a call and then immediately pressing the Power
- // button.)
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
-
- showDialog(dialogId);
- }
-
- @Override
- protected Dialog onCreateDialog(int id, Bundle args) {
- Dialog dialog;
- switch(id) {
- case DIALOG_SELECT_PHONE_TYPE:
- dialog = new AlertDialog.Builder(this)
- .setTitle(R.string.pick_outgoing_call_phone_type)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setSingleChoiceItems(R.array.phone_type_values, -1, this)
- .setNegativeButton(android.R.string.cancel, this)
- .setOnCancelListener(this)
- .create();
- break;
- case DIALOG_SELECT_PROFILE:
- String[] profileNames = getIntent().getStringArrayExtra(EXTRA_PROFILE_NAMES);
- dialog = new AlertDialog.Builder(this)
- .setTitle(R.string.pick_outgoing_sip_phone)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setSingleChoiceItems(profileNames, -1, this)
- .setNegativeButton(android.R.string.cancel, this)
- .setOnCancelListener(this)
- .create();
- addMakeDefaultCheckBox(dialog);
- break;
- case DIALOG_START_SIP_SETTINGS:
- dialog = new AlertDialog.Builder(this)
- .setTitle(R.string.no_sip_account_found_title)
- .setMessage(R.string.no_sip_account_found)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setPositiveButton(R.string.sip_menu_add, this)
- .setNegativeButton(android.R.string.cancel, this)
- .setOnCancelListener(this)
- .create();
- break;
- case DIALOG_NO_INTERNET_ERROR:
- boolean wifiOnly = SipManager.isSipWifiOnly(this);
- dialog = new AlertDialog.Builder(this)
- .setTitle(wifiOnly ? R.string.no_wifi_available_title
- : R.string.no_internet_available_title)
- .setMessage(wifiOnly ? R.string.no_wifi_available
- : R.string.no_internet_available)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setPositiveButton(android.R.string.ok, this)
- .setOnCancelListener(this)
- .create();
- break;
- case DIALOG_NO_VOIP:
- dialog = new AlertDialog.Builder(this)
- .setTitle(R.string.no_voip)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setPositiveButton(android.R.string.ok, this)
- .setOnCancelListener(this)
- .create();
- break;
- default:
- dialog = null;
- }
- if (dialog != null) {
- //mDialogs[id] = dialog;
- }
- return dialog;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (VERBOSE) log("onPause");
- }
-
- @Override
- public void finish() {
- if (VERBOSE) log("finish");
- super.finish();
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (VERBOSE) log("onCheckedChanged, isChecked: " + isChecked);
- mMakePrimary = isChecked;
- if (isChecked) {
- mUnsetPriamryHint.setVisibility(View.VISIBLE);
- } else {
- mUnsetPriamryHint.setVisibility(View.INVISIBLE);
- }
- }
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- if (VERBOSE) log("onClick, id: " + id);
- onChoiceMade(id);
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- if (VERBOSE) log("onCancel");
- onChoiceMade(DialogInterface.BUTTON_NEGATIVE);
- }
-
- private void onChoiceMade(int choice) {
- ResultReceiver resultReceiver = getIntent().getParcelableExtra(EXTRA_RESULT_RECEIVER);
- if (resultReceiver != null) {
- Bundle extras = new Bundle();
- extras.putBoolean(EXTRA_MAKE_PRIMARY, mMakePrimary);
- resultReceiver.send(choice, extras);
- }
- finish();
- }
-
- private void addMakeDefaultCheckBox(Dialog dialog) {
- LayoutInflater inflater = (LayoutInflater) getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
- CheckBox makePrimaryCheckBox =
- (CheckBox) view.findViewById(com.android.internal.R.id.alwaysUse);
- makePrimaryCheckBox.setText(R.string.remember_my_choice);
- makePrimaryCheckBox.setOnCheckedChangeListener(this);
- mUnsetPriamryHint = (TextView)view.findViewById(com.android.internal.R.id.clearDefaultHint);
- mUnsetPriamryHint.setText(R.string.reset_my_choice_hint);
- mUnsetPriamryHint.setVisibility(View.GONE);
- ((AlertDialog)dialog).setView(view);
- }
-
- static private String[] getProfileNames(List<SipProfile> profiles) {
- if (profiles == null) {
- return null;
- }
-
- String[] entries = new String[profiles.size()];
- int i = 0;
- for (SipProfile p : profiles) {
- entries[i++] = p.getProfileName();
- }
- return entries;
- }
-
- private static void log(String msg) {
- Log.d(SipUtil.LOG_TAG, PREFIX + msg);
- }
-}
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 5380fa5..be1e3b2 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -91,10 +91,6 @@
private static final int DISPLAYINFO_NOTIFICATION_DONE = 24;
private static final int UPDATE_IN_CALL_NOTIFICATION = 27;
- // Emergency call related defines:
- private static final int EMERGENCY_TONE_OFF = 0;
- private static final int EMERGENCY_TONE_ALERT = 1;
- private static final int EMERGENCY_TONE_VIBRATE = 2;
private PhoneGlobals mApplication;
private CallManager mCM;
@@ -111,14 +107,6 @@
private boolean mVoicePrivacyState = false;
private boolean mIsCdmaRedialCall = false;
- // Emergency call tone and vibrate:
- private int mIsEmergencyToneOn;
- private int mCurrentEmergencyToneState = EMERGENCY_TONE_OFF;
- private EmergencyTonePlayerVibrator mEmergencyTonePlayerVibrator;
-
- // Ringback tone player
- private InCallTonePlayer mInCallRingbackTonePlayer;
-
// Cached AudioManager
private AudioManager mAudioManager;
@@ -253,11 +241,6 @@
}
break;
- case CallStateMonitor.PHONE_RINGBACK_TONE:
- // DISABLED. The Telecom and new ConnectionService layers are now responsible.
- // onRingbackTone((AsyncResult) msg.obj);
- break;
-
default:
// super.handleMessage(msg);
}
@@ -481,59 +464,11 @@
// make sure audio is in in-call mode now
PhoneUtils.setAudioMode(mCM);
}
-
- if (fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
- Connection c = fgPhone.getForegroundCall().getLatestConnection();
- if ((c != null) && (PhoneNumberUtils.isLocalEmergencyNumber(mApplication,
- c.getAddress()))) {
- if (VDBG) log("onPhoneStateChanged: it is an emergency call.");
- Call.State callState = fgPhone.getForegroundCall().getState();
- if (mEmergencyTonePlayerVibrator == null) {
- mEmergencyTonePlayerVibrator = new EmergencyTonePlayerVibrator();
- }
-
- if (callState == Call.State.DIALING || callState == Call.State.ALERTING) {
- mIsEmergencyToneOn = Settings.Global.getInt(
- mApplication.getContentResolver(),
- Settings.Global.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
- if (mIsEmergencyToneOn != EMERGENCY_TONE_OFF &&
- mCurrentEmergencyToneState == EMERGENCY_TONE_OFF) {
- if (mEmergencyTonePlayerVibrator != null) {
- mEmergencyTonePlayerVibrator.start();
- }
- }
- } else if (callState == Call.State.ACTIVE) {
- if (mCurrentEmergencyToneState != EMERGENCY_TONE_OFF) {
- if (mEmergencyTonePlayerVibrator != null) {
- mEmergencyTonePlayerVibrator.stop();
- }
- }
- }
- }
- }
-
- if (fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM
- || fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_SIP
- || fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS
- || fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_THIRD_PARTY) {
- Call.State callState = mCM.getActiveFgCallState();
- if (!callState.isDialing()) {
- // If call gets activated or disconnected before the ringback
- // tone stops, we have to stop it to prevent disturbing.
- if (mInCallRingbackTonePlayer != null) {
- mInCallRingbackTonePlayer.stopTone();
- mInCallRingbackTonePlayer = null;
- }
- }
- }
}
void updateCallNotifierRegistrationsAfterRadioTechnologyChange() {
if (DBG) Log.d(LOG_TAG, "updateCallNotifierRegistrationsAfterRadioTechnologyChange...");
- // Clear ringback tone player
- mInCallRingbackTonePlayer = null;
-
// Instantiate mSignalInfoToneGenerator
createSignalInfoToneGenerator();
}
@@ -614,15 +549,6 @@
final boolean isEmergencyNumber =
PhoneNumberUtils.isLocalEmergencyNumber(mApplication, number);
- if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
- if ((isEmergencyNumber)
- && (mCurrentEmergencyToneState != EMERGENCY_TONE_OFF)) {
- if (mEmergencyTonePlayerVibrator != null) {
- mEmergencyTonePlayerVibrator.stop();
- }
- }
- }
-
// Possibly play a "post-disconnect tone" thru the earpiece.
// We do this here, rather than from the InCallScreen
// activity, since we need to do this even if you're not in
@@ -750,7 +676,6 @@
public static final int TONE_OUT_OF_SERVICE = 9;
public static final int TONE_REDIAL = 10;
public static final int TONE_OTA_CALL_END = 11;
- public static final int TONE_RING_BACK = 12;
public static final int TONE_UNOBTAINABLE_NUMBER = 13;
// The tone volume relative to other sounds in the stream
@@ -855,12 +780,6 @@
toneVolume = TONE_RELATIVE_VOLUME_LOPRI;
toneLengthMillis = 5000;
break;
- case TONE_RING_BACK:
- toneType = ToneGenerator.TONE_SUP_RINGTONE;
- toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
- // Call ring back tone is stopped by stopTone() method
- toneLengthMillis = Integer.MAX_VALUE - TONE_TIMEOUT_BUFFER;
- break;
case TONE_UNOBTAINABLE_NUMBER:
toneType = ToneGenerator.TONE_SUP_ERROR;
toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
@@ -1107,78 +1026,7 @@
return mIsCdmaRedialCall;
}
- /**
- * Inner class to handle emergency call tone and vibrator
- */
- private class EmergencyTonePlayerVibrator {
- private final int EMG_VIBRATE_LENGTH = 1000; // ms.
- private final int EMG_VIBRATE_PAUSE = 1000; // ms.
- private final long[] mVibratePattern =
- new long[] { EMG_VIBRATE_LENGTH, EMG_VIBRATE_PAUSE };
-
- private ToneGenerator mToneGenerator;
- // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure this vibrator
- // object will be isolated from others.
- private Vibrator mEmgVibrator = new SystemVibrator();
- private int mInCallVolume;
-
- /**
- * constructor
- */
- public EmergencyTonePlayerVibrator() {
- }
-
- /**
- * Start the emergency tone or vibrator.
- */
- private void start() {
- if (VDBG) log("call startEmergencyToneOrVibrate.");
- int ringerMode = mAudioManager.getRingerMode();
-
- if ((mIsEmergencyToneOn == EMERGENCY_TONE_ALERT) &&
- (ringerMode == AudioManager.RINGER_MODE_NORMAL)) {
- log("EmergencyTonePlayerVibrator.start(): emergency tone...");
- mToneGenerator = new ToneGenerator (AudioManager.STREAM_VOICE_CALL,
- InCallTonePlayer.TONE_RELATIVE_VOLUME_EMERGENCY);
- if (mToneGenerator != null) {
- mInCallVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
- mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
- mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
- 0);
- mToneGenerator.startTone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK);
- mCurrentEmergencyToneState = EMERGENCY_TONE_ALERT;
- }
- } else if (mIsEmergencyToneOn == EMERGENCY_TONE_VIBRATE) {
- log("EmergencyTonePlayerVibrator.start(): emergency vibrate...");
- if (mEmgVibrator != null) {
- mEmgVibrator.vibrate(mVibratePattern, 0, VIBRATION_ATTRIBUTES);
- mCurrentEmergencyToneState = EMERGENCY_TONE_VIBRATE;
- }
- }
- }
-
- /**
- * If the emergency tone is active, stop the tone or vibrator accordingly.
- */
- private void stop() {
- if (VDBG) log("call stopEmergencyToneOrVibrate.");
-
- if ((mCurrentEmergencyToneState == EMERGENCY_TONE_ALERT)
- && (mToneGenerator != null)) {
- mToneGenerator.stopTone();
- mToneGenerator.release();
- mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
- mInCallVolume,
- 0);
- } else if ((mCurrentEmergencyToneState == EMERGENCY_TONE_VIBRATE)
- && (mEmgVibrator != null)) {
- mEmgVibrator.cancel();
- }
- mCurrentEmergencyToneState = EMERGENCY_TONE_OFF;
- }
- }
-
- private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
+ private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
@@ -1190,27 +1038,6 @@
}
};
- private void onRingbackTone(AsyncResult r) {
- boolean playTone = (Boolean)(r.result);
-
- if (playTone == true) {
- // Only play when foreground call is in DIALING or ALERTING.
- // to prevent a late coming playtone after ALERTING.
- // Don't play ringback tone if it is in play, otherwise it will cut
- // the current tone and replay it
- if (mCM.getActiveFgCallState().isDialing() &&
- mInCallRingbackTonePlayer == null) {
- mInCallRingbackTonePlayer = new InCallTonePlayer(InCallTonePlayer.TONE_RING_BACK);
- mInCallRingbackTonePlayer.start();
- }
- } else {
- if (mInCallRingbackTonePlayer != null) {
- mInCallRingbackTonePlayer.stopTone();
- mInCallRingbackTonePlayer = null;
- }
- }
- }
-
private void log(String msg) {
Log.d(LOG_TAG, msg);
}
diff --git a/src/com/android/services/telephony/CdmaConference.java b/src/com/android/services/telephony/CdmaConference.java
index e0fa41a..c77557f 100644
--- a/src/com/android/services/telephony/CdmaConference.java
+++ b/src/com/android/services/telephony/CdmaConference.java
@@ -31,13 +31,11 @@
*/
public class CdmaConference extends Conference {
- private int mCapabilities =
- PhoneCapabilities.MUTE |
- PhoneCapabilities.MERGE_CONFERENCE;
+ private int mCapabilities = PhoneCapabilities.MUTE;
- public CdmaConference(PhoneAccountHandle phoneAccount) {
+ public CdmaConference(PhoneAccountHandle phoneAccount, int capabilities) {
super(phoneAccount);
- updateCapabilities();
+ setCapabilities(mCapabilities | capabilities);
setActive();
}
diff --git a/src/com/android/services/telephony/CdmaConferenceController.java b/src/com/android/services/telephony/CdmaConferenceController.java
index 19b0430..ab126ca 100644
--- a/src/com/android/services/telephony/CdmaConferenceController.java
+++ b/src/com/android/services/telephony/CdmaConferenceController.java
@@ -19,6 +19,7 @@
import android.os.Handler;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
+import android.telecom.PhoneCapabilities;
import java.util.ArrayList;
import java.util.List;
@@ -136,7 +137,15 @@
// 1) Create a new conference connection if it doesn't exist.
if (mConference == null) {
Log.i(this, "Creating new Cdma conference call");
- mConference = new CdmaConference(null);
+ CdmaConnection newConnection = mCdmaConnections.get(mCdmaConnections.size() - 1);
+ if (newConnection.isOutgoing()) {
+ // Only an outgoing call can be merged with an ongoing call.
+ mConference = new CdmaConference(null, PhoneCapabilities.MERGE_CONFERENCE);
+ } else {
+ // If the most recently added connection was an incoming call, enable
+ // swap instead of merge.
+ mConference = new CdmaConference(null, PhoneCapabilities.SWAP_CONFERENCE);
+ }
isNewlyCreated = true;
}
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index a56205a..5d470ab 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -22,10 +22,12 @@
import android.provider.Settings;
import android.telecom.PhoneCapabilities;
import android.telephony.DisconnectCause;
+import android.telephony.PhoneNumberUtils;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.Phone;
import com.android.phone.Constants;
import java.util.LinkedList;
@@ -66,13 +68,20 @@
private final boolean mIsOutgoing;
// Queue of pending short-DTMF characters.
private final Queue<Character> mDtmfQueue = new LinkedList<>();
+ private final EmergencyTonePlayer mEmergencyTonePlayer;
// Indicates that the DTMF confirmation from telephony is pending.
private boolean mDtmfBurstConfirmationPending = false;
private boolean mIsCallWaiting;
- CdmaConnection(Connection connection, boolean allowMute, boolean isOutgoing) {
+ CdmaConnection(
+ Connection connection,
+ EmergencyTonePlayer emergencyTonePlayer,
+ boolean allowMute,
+ boolean isOutgoing) {
+
super(connection);
+ mEmergencyTonePlayer = emergencyTonePlayer;
mAllowMute = allowMute;
mIsOutgoing = isOutgoing;
mIsCallWaiting = connection != null && connection.getState() == Call.State.WAITING;
@@ -133,6 +142,16 @@
Connection originalConnection = getOriginalConnection();
mIsCallWaiting = originalConnection != null &&
originalConnection.getState() == Call.State.WAITING;
+
+ if (state == android.telecom.Connection.STATE_DIALING) {
+ if (isEmergency()) {
+ mEmergencyTonePlayer.start();
+ }
+ } else {
+ // No need to check if it is an emergency call, since it is a no-op if it isn't started.
+ mEmergencyTonePlayer.stop();
+ }
+
super.onStateChanged(state);
}
@@ -231,4 +250,11 @@
}
}
}
+
+ private boolean isEmergency() {
+ Phone phone = getPhone();
+ return phone != null &&
+ PhoneNumberUtils.isLocalEmergencyNumber(
+ phone.getContext(), getAddress().getSchemeSpecificPart());
+ }
}
diff --git a/src/com/android/services/telephony/EmergencyTonePlayer.java b/src/com/android/services/telephony/EmergencyTonePlayer.java
new file mode 100644
index 0000000..aaec24f
--- /dev/null
+++ b/src/com/android/services/telephony/EmergencyTonePlayer.java
@@ -0,0 +1,133 @@
+/*
+ * 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.content.Context;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.ToneGenerator;
+import android.os.SystemVibrator;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+/**
+ * Plays an emergency tone when placing emergency calls on CDMA devices.
+ */
+class EmergencyTonePlayer {
+
+ private static final int EMERGENCY_TONE_OFF = 0;
+ private static final int EMERGENCY_TONE_ALERT = 1;
+ private static final int EMERGENCY_TONE_VIBRATE = 2;
+
+ private static final int ALERT_RELATIVE_VOLUME_PERCENT = 100;
+
+ private static final int VIBRATE_LENGTH_MILLIS = 1000;
+ private static final int VIBRATE_PAUSE_MILLIS = 1000;
+ private static final long[] VIBRATE_PATTERN =
+ new long[] { VIBRATE_LENGTH_MILLIS, VIBRATE_PAUSE_MILLIS};
+
+ private static final AudioAttributes VIBRATION_ATTRIBUTES =
+ new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
+ .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
+ .build();
+
+ // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure that this vibrator
+ // object will be isolated from others.
+ private final Vibrator mVibrator = new SystemVibrator();
+ private final Context mContext;
+ private final AudioManager mAudioManager;
+
+ private ToneGenerator mToneGenerator;
+ private int mSavedInCallVolume;
+ private boolean mIsVibrating = false;
+
+ EmergencyTonePlayer(Context context) {
+ mContext = context;
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ }
+
+ public void start() {
+ switch (getToneSetting()) {
+ case EMERGENCY_TONE_VIBRATE:
+ startVibrate();
+ break;
+ case EMERGENCY_TONE_ALERT:
+ // Only start if we are not in silent mode.
+ int ringerMode = mAudioManager.getRingerMode();
+ if (ringerMode == AudioManager.RINGER_MODE_NORMAL) {
+ startAlert();
+ }
+ break;
+ case EMERGENCY_TONE_OFF:
+ // nothing;
+ break;
+ }
+ }
+
+ public void stop() {
+ stopVibrate();
+ stopAlert();
+ }
+
+ private void startVibrate() {
+ if (!mIsVibrating) {
+ mVibrator.vibrate(VIBRATE_PATTERN, 0, VIBRATION_ATTRIBUTES);
+ mIsVibrating = true;
+ }
+ }
+
+ private void stopVibrate() {
+ if (mIsVibrating) {
+ mVibrator.cancel();
+ mIsVibrating = false;
+ }
+ }
+
+ private void startAlert() {
+ if (mToneGenerator == null) {
+ mToneGenerator = new ToneGenerator(
+ AudioManager.STREAM_VOICE_CALL, ALERT_RELATIVE_VOLUME_PERCENT);
+
+ // Set the volume to max and save the old volume setting.
+ mSavedInCallVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
+ mAudioManager.setStreamVolume(
+ AudioManager.STREAM_VOICE_CALL,
+ mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
+ 0);
+ mToneGenerator.startTone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK);
+ } else {
+ Log.d(this, "An alert is already running.");
+ }
+ }
+
+ private void stopAlert() {
+ if (mToneGenerator != null) {
+ mToneGenerator.stopTone();
+ mToneGenerator.release();
+ mToneGenerator = null;
+
+ mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, mSavedInCallVolume, 0);
+ mSavedInCallVolume = 0;
+ }
+ }
+
+ private int getToneSetting() {
+ return Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
+ }
+}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 5935765..cb7894c 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -52,11 +52,13 @@
new CdmaConferenceController(this);
private ComponentName mExpectedComponentName = null;
private EmergencyCallHelper mEmergencyCallHelper;
+ private EmergencyTonePlayer mEmergencyTonePlayer;
@Override
public void onCreate() {
super.onCreate();
mExpectedComponentName = new ComponentName(this, this.getClass());
+ mEmergencyTonePlayer = new EmergencyTonePlayer(this);
}
@Override
@@ -290,8 +292,8 @@
return connection;
} else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
boolean allowMute = allowMute(phone);
- CdmaConnection connection =
- new CdmaConnection(originalConnection, allowMute, isOutgoing);
+ CdmaConnection connection = new CdmaConnection(
+ originalConnection, mEmergencyTonePlayer, allowMute, isOutgoing);
mCdmaConferenceController.add(connection);
return connection;
} else {