Merge changes I5b45f043,I1ebe7fc3 into nyc-mr1-dev
* changes:
Remove NOOP in VVM connection
Set message count to 0 while clearing MWI
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 26b0c7a..ddc2dbe 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -541,12 +541,6 @@
</activity>
<!-- Start SIP -->
- <service android:name="com.android.services.telephony.sip.SipCallServiceProvider"
- android:singleUser="true" >
- <intent-filter>
- <action android:name="android.telecom.CallServiceProvider" />
- </intent-filter>
- </service>
<service android:name="com.android.services.telephony.sip.SipConnectionService"
android:label="@string/sip_connection_service_label"
android:singleUser="true"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0fbd08d..a18ee87 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1011,6 +1011,8 @@
<string name="incall_error_supp_service_hold">Can\'t hold calls.</string>
<!-- In-call screen: call failure message displayed in an error dialog when WFC is enabled, is wifi-only, and not connected to a wireless network. [CHAR_LIMIT=NONE] -->
<string name="incall_error_wfc_only_no_wireless_network">Connect to a wireless network to make a call.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog when the user is connected to a wireless network, but wifi calling is turned off. [CHAR_LIMIT=NONE] -->
+ <string name="incall_error_promote_wfc">Enable Wi-Fi calling to make a call.</string>
<!-- Dialog title for the "radio enable" UI for emergency calls -->
<string name="emergency_enable_radio_dialog_title">Emergency call</string>
diff --git a/sip/res/values/strings.xml b/sip/res/values/strings.xml
index 6ac7c8d..d515736 100644
--- a/sip/res/values/strings.xml
+++ b/sip/res/values/strings.xml
@@ -115,8 +115,12 @@
<!-- Help text of the auth_username field. [CHAR LIMIT=NONE] -->
<string name="auth_username_summary">Username used for authentication</string>
- <!-- Initial status of the preferences is '<Not set>'. [CHAR LIMIT=NONE] -->
- <string name="default_preference_summary"><Not set></string>
+ <!-- Initial status of the username preference is '<Not set>'. [CHAR LIMIT=NONE] -->
+ <string name="default_preference_summary_username"><Not set></string>
+ <!-- Initial status of the password preference is '<Not set>'. [CHAR LIMIT=NONE] -->
+ <string name="default_preference_summary_password"><Not set></string>
+ <!-- Initial status of the domain address preference is '<Not set>'. [CHAR LIMIT=NONE] -->
+ <string name="default_preference_summary_domain_address"><Not set></string>
<!-- Default value for the display-name preference summary. [CHAR LIMIT=NONE] -->
<string name="display_name_summary"><Same as username></string>
<!-- Default value for the outbound-proxy-address preference summary. [CHAR LIMIT=NONE] -->
diff --git a/sip/res/xml/sip_edit.xml b/sip/res/xml/sip_edit.xml
index 15e5ce1..58a8a92 100644
--- a/sip/res/xml/sip_edit.xml
+++ b/sip/res/xml/sip_edit.xml
@@ -22,7 +22,7 @@
android:key="@string/username"
android:title="@string/username_title"
android:dialogTitle="@string/username_title"
- android:summary="@string/default_preference_summary"
+ android:summary="@string/default_preference_summary_username"
android:persistent="false"
android:singleLine="true"
android:inputType="textNoSuggestions"/>
@@ -32,7 +32,7 @@
android:title="@string/password_title"
android:dialogTitle="@string/password_title"
android:password="true"
- android:summary="@string/default_preference_summary"
+ android:summary="@string/default_preference_summary_password"
android:persistent="false"
android:singleLine="true"/>
@@ -40,7 +40,7 @@
android:key="@string/domain_address"
android:title="@string/domain_address_title"
android:dialogTitle="@string/domain_address_title"
- android:summary="@string/default_preference_summary"
+ android:summary="@string/default_preference_summary_domain_address"
android:persistent="false"
android:singleLine="true"
android:inputType="textNoSuggestions"/>
diff --git a/sip/src/com/android/services/telephony/sip/SipEditor.java b/sip/src/com/android/services/telephony/sip/SipEditor.java
index 8bc7734..f6e9c22 100644
--- a/sip/src/com/android/services/telephony/sip/SipEditor.java
+++ b/sip/src/com/android/services/telephony/sip/SipEditor.java
@@ -68,9 +68,10 @@
private SipAccountRegistry mSipAccountRegistry;
enum PreferenceKey {
- Username(R.string.username, 0, R.string.default_preference_summary),
- Password(R.string.password, 0, R.string.default_preference_summary),
- DomainAddress(R.string.domain_address, 0, R.string.default_preference_summary),
+ Username(R.string.username, 0, R.string.default_preference_summary_username),
+ Password(R.string.password, 0, R.string.default_preference_summary_password),
+ DomainAddress(R.string.domain_address, 0,
+ R.string.default_preference_summary_domain_address),
DisplayName(R.string.display_name, 0, R.string.display_name_summary),
ProxyAddress(R.string.proxy_address, 0, R.string.optional_summary),
Port(R.string.port, R.string.default_port, R.string.default_port),
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index 868a0f1..4c9089f 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -17,6 +17,9 @@
package com.android.phone;
import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.telephony.CarrierConfigManager;
import android.util.Log;
import com.android.ims.ImsConfig;
@@ -66,4 +69,31 @@
if (DBG) Log.d(LOG_TAG, "isWfcModeWifiOnly :: isWifiOnlyMode" + isWifiOnlyMode);
return isWfcEnabled(context) && isWifiOnlyMode;
}
+
+ /**
+ * When a call cannot be placed, determines if the use of WFC should be promoted, per the
+ * carrier config. Use of WFC is promoted to the user if the device is connected to a WIFI
+ * network, WFC is disabled, and the carrier config indicates that the features should be
+ * promoted.
+ *
+ * @return {@code true} if use of WFC should be promoted, {@code false} otherwise.
+ */
+ public static boolean shouldPromoteWfc(Context context) {
+ CarrierConfigManager cfgManager = (CarrierConfigManager) context
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (cfgManager == null || !cfgManager.getConfig()
+ .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) {
+ return false;
+ }
+
+ ConnectivityManager cm =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (cm != null) {
+ NetworkInfo ni = cm.getActiveNetworkInfo();
+ if (ni != null && ni.isConnected()) {
+ return ni.getType() == ConnectivityManager.TYPE_WIFI && !isWfcEnabled(context);
+ }
+ }
+ return false;
+ }
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 546f0f2..d050576 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -3308,4 +3308,28 @@
}
DumpsysHandler.dump(mPhone.getContext(), fd, writer, args);
}
+
+ /**
+ * Get aggregated video call data usage from all subscriptions since boot.
+ * @return total data usage in bytes
+ * {@hide}
+ */
+ @Override
+ public long getVtDataUsage() {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
+ null);
+
+ // NetworkStatsService keeps tracking the active network interface and identity. It will
+ // record the delta with the corresponding network identity. What we need to do here is
+ // returning total video call data usage from all subscriptions since boot.
+
+ // TODO: Add sub id support in the future. We'll need it when we support DSDA and
+ // simultaneous VT calls.
+ final Phone[] phones = PhoneFactory.getPhones();
+ long total = 0;
+ for (Phone phone : phones) {
+ total += phone.getVtDataUsage();
+ }
+ return total;
+ }
}
diff --git a/src/com/android/phone/common/mail/store/ImapConnection.java b/src/com/android/phone/common/mail/store/ImapConnection.java
index 0360e3e..6945b94 100644
--- a/src/com/android/phone/common/mail/store/ImapConnection.java
+++ b/src/com/android/phone/common/mail/store/ImapConnection.java
@@ -30,6 +30,7 @@
import com.android.phone.common.mail.store.imap.ImapUtility;
import com.android.phone.common.mail.utils.LogUtils;
import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.IOException;
import java.util.ArrayList;
@@ -110,7 +111,7 @@
// The server should greet us with something like
// * OK IMAP4rev1 Server
// consume the response before doing anything else.
- ImapResponse response = mParser.readResponse();
+ ImapResponse response = mParser.readResponse(false);
if (!response.isOk()) {
mImapStore.getImapHelper()
.handleEvent(OmtpEvents.DATA_INVALID_INITIAL_SERVER_RESPONSE);
@@ -138,11 +139,26 @@
}
}
+ void logout() {
+ try {
+ sendCommand(ImapConstants.LOGOUT, false);
+ if (!mParser.readResponse(true).is(0, ImapConstants.BYE)) {
+ VvmLog.e(TAG, "Server did not respond LOGOUT with BYE");
+ }
+ if (!mParser.readResponse(false).isOk()) {
+ VvmLog.e(TAG, "Server did not respond OK after LOGOUT");
+ }
+ } catch (IOException | MessagingException e) {
+ VvmLog.e(TAG, "Error while logging out:" + e);
+ }
+ }
+
/**
* Closes the connection and releases all resources. This connection can not be used again
* until {@link #setStore(ImapStore)} is called.
*/
void close() {
+ logout();
if (mTransport != null) {
mTransport.close();
mTransport = null;
@@ -323,7 +339,7 @@
}
public ImapResponse readResponse() throws IOException, MessagingException {
- return mParser.readResponse();
+ return mParser.readResponse(false);
}
public List<ImapResponse> executeSimpleCommand(String command)
@@ -377,11 +393,12 @@
* @throws IOException
* @throws MessagingException
*/
- List<ImapResponse> getCommandResponses() throws IOException, MessagingException {
+ List<ImapResponse> getCommandResponses()
+ throws IOException, MessagingException {
final List<ImapResponse> responses = new ArrayList<ImapResponse>();
ImapResponse response;
do {
- response = mParser.readResponse();
+ response = mParser.readResponse(false);
responses.add(response);
} while (!(response.isTagged() || response.isContinuationRequest()));
diff --git a/src/com/android/phone/common/mail/store/ImapFolder.java b/src/com/android/phone/common/mail/store/ImapFolder.java
index cfbb1bc..4abb7f5 100644
--- a/src/com/android/phone/common/mail/store/ImapFolder.java
+++ b/src/com/android/phone/common/mail/store/ImapFolder.java
@@ -145,7 +145,6 @@
}
mMessageCount = -1;
synchronized (this) {
- mStore.closeConnection();
mConnection = null;
}
}
diff --git a/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java b/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
index a6d2df6..6fc5abe 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
@@ -136,10 +136,12 @@
* is stored in the internal storage. When the {@link ImapResponse} is no longer used
* {@link #destroyResponses} should be called to destroy all the responses in the array.
*
+ * @param byeExpected is a untagged BYE response expected? If not proper cleanup will be done
+ * and {@link ByeException} will be thrown.
* @return the parsed {@link ImapResponse} object.
- * @exception ByeException when detects BYE.
+ * @exception ByeException when detects BYE and <code>byeExpected</code> is false.
*/
- public ImapResponse readResponse() throws IOException, MessagingException {
+ public ImapResponse readResponse(boolean byeExpected) throws IOException, MessagingException {
ImapResponse response = null;
try {
response = parseResponse();
@@ -154,7 +156,7 @@
}
// Handle this outside of try-catch. We don't have to dump protocol log when getting BYE.
- if (response.is(0, ImapConstants.BYE)) {
+ if (!byeExpected && response.is(0, ImapConstants.BYE)) {
Log.w(TAG, ByeException.MESSAGE);
response.destroy();
throw new ByeException();
diff --git a/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java b/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java
index e4230ff..3411228 100644
--- a/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java
+++ b/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java
@@ -175,8 +175,7 @@
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
- ImapHelper helper = new ImapHelper(getContext(), mPhoneAccountHandle, network);
- try {
+ try (ImapHelper helper = new ImapHelper(getContext(), mPhoneAccountHandle, network)) {
@ChangePinResult int result =
helper.changePin(mOldPin.getText().toString(),
mNewPin.getText().toString());
diff --git a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
index fe3911c..d267e68 100644
--- a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
+++ b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
@@ -159,19 +159,21 @@
try {
while (mRetryCount > 0) {
VvmLog.i(TAG, "fetching voicemail, retry count=" + mRetryCount);
- ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount, network);
- if (!imapHelper.isSuccessfullyInitialized()) {
- VvmLog.w(TAG, "Can't retrieve Imap credentials.");
- return;
- }
+ try (ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount,
+ network)) {
+ if (!imapHelper.isSuccessfullyInitialized()) {
+ VvmLog.w(TAG, "Can't retrieve Imap credentials.");
+ return;
+ }
- boolean success = imapHelper.fetchVoicemailPayload(
- new VoicemailFetchedCallback(mContext, mUri), mUid);
- if (!success && mRetryCount > 0) {
- VvmLog.i(TAG, "fetch voicemail failed, retrying");
- mRetryCount--;
- } else {
- return;
+ boolean success = imapHelper.fetchVoicemailPayload(
+ new VoicemailFetchedCallback(mContext, mUri), mUid);
+ if (!success && mRetryCount > 0) {
+ VvmLog.i(TAG, "fetch voicemail failed, retrying");
+ mRetryCount--;
+ } else {
+ return;
+ }
}
}
} finally {
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index 216b6a4..908d0f7 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -57,6 +57,7 @@
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -66,7 +67,7 @@
/**
* A helper interface to abstract commands sent across IMAP interface for a given account.
*/
-public class ImapHelper {
+public class ImapHelper implements Closeable {
private static final String TAG = "ImapHelper";
@@ -126,6 +127,11 @@
VoicemailContract.Status.QUOTA_UNAVAILABLE);
}
+ @Override
+ public void close() {
+ mImapStore.closeConnection();
+ }
+
/**
* If mImapStore is null, this means that there was a missing or badly formatted port number,
* which means there aren't sufficient credentials for login. If mImapStore is succcessfully
diff --git a/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java b/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
index 306006d..b238c8d 100644
--- a/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
+++ b/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
@@ -148,9 +148,7 @@
super.onAvailable(network);
VvmLog.i(TAG, "new user: network available");
ImapHelper helper = new ImapHelper(mContext, mPhoneAccount, network);
-
try {
-
// VVM3 has inconsistent error language code to OMTP. Just issue a raw command
// here.
// TODO(b/29082671): use LocaleList
@@ -176,7 +174,10 @@
} catch (MessagingException | IOException e) {
helper.handleEvent(OmtpEvents.VVM3_NEW_USER_SETUP_FAILED);
VvmLog.e(TAG, e.toString());
+ } finally {
+ helper.close();
}
+
}
private boolean setPin(ImapHelper helper) throws IOException, MessagingException {
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 74b1f66..9884e9d 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -235,35 +235,36 @@
int retryCount = NETWORK_RETRY_COUNT;
try {
while (retryCount > 0) {
- ImapHelper imapHelper = new ImapHelper(this, phoneAccount, network);
- if (!imapHelper.isSuccessfullyInitialized()) {
- VvmLog.w(TAG, "Can't retrieve Imap credentials.");
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
- phoneAccount);
- return;
- }
+ try (ImapHelper imapHelper = new ImapHelper(this, phoneAccount, network)) {
+ if (!imapHelper.isSuccessfullyInitialized()) {
+ VvmLog.w(TAG, "Can't retrieve Imap credentials.");
+ VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
+ phoneAccount);
+ return;
+ }
- boolean success = true;
- if (voicemail == null) {
- success = syncAll(action, imapHelper, phoneAccount);
- } else {
- success = syncOne(imapHelper, voicemail, phoneAccount);
- }
- imapHelper.updateQuota();
+ boolean success = true;
+ if (voicemail == null) {
+ success = syncAll(action, imapHelper, phoneAccount);
+ } else {
+ success = syncOne(imapHelper, voicemail, phoneAccount);
+ }
+ imapHelper.updateQuota();
- // Need to check again for whether visual voicemail is enabled because it could have
- // been disabled while waiting for the response from the network.
- if (VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(this, phoneAccount) &&
- !success) {
- retryCount--;
- VvmLog.v(TAG, "Retrying " + action);
- } else {
- // Nothing more to do here, just exit.
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
- phoneAccount);
+ // Need to check again for whether visual voicemail is enabled because it could
+ // have been disabled while waiting for the response from the network.
+ if (VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(this, phoneAccount) &&
+ !success) {
+ retryCount--;
+ VvmLog.v(TAG, "Retrying " + action);
+ } else {
+ // Nothing more to do here, just exit.
+ VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
+ phoneAccount);
- imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED);
- return;
+ imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED);
+ return;
+ }
}
}
} finally {
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index f8fd918..2965968 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -125,6 +125,7 @@
case android.telephony.DisconnectCause.DIAL_MODIFIED_TO_SS:
case android.telephony.DisconnectCause.DIAL_MODIFIED_TO_DIAL:
case android.telephony.DisconnectCause.ERROR_UNSPECIFIED:
+ case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
return DisconnectCause.ERROR;
case android.telephony.DisconnectCause.DIALED_MMI:
@@ -140,6 +141,9 @@
case android.telephony.DisconnectCause.CALL_PULLED:
return DisconnectCause.CALL_PULLED;
+ case android.telephony.DisconnectCause.ANSWERED_ELSEWHERE:
+ return DisconnectCause.ANSWERED_ELSEWHERE;
+
default:
Log.w("DisconnectCauseUtil.toTelecomDisconnectCauseCode",
"Unrecognized Telephony DisconnectCause "
@@ -220,6 +224,9 @@
case android.telephony.DisconnectCause.CALL_PULLED:
resourceId = R.string.callEnded_pulled;
+ case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
+ resourceId = R.string.callFailed_maximum_reached;
+
default:
break;
}
@@ -287,7 +294,9 @@
// TODO: Offer the option to turn the radio on, and automatically retry the call
// once network registration is complete.
- if (ImsUtil.isWfcModeWifiOnly(context)) {
+ if (ImsUtil.shouldPromoteWfc(context)) {
+ resourceId = R.string.incall_error_promote_wfc;
+ } else if (ImsUtil.isWfcModeWifiOnly(context)) {
resourceId = R.string.incall_error_wfc_only_no_wireless_network;
} else if (ImsUtil.isWfcEnabled(context)) {
resourceId = R.string.incall_error_power_off_wfc;
@@ -309,7 +318,9 @@
case android.telephony.DisconnectCause.OUT_OF_SERVICE:
// No network connection.
- if (ImsUtil.isWfcModeWifiOnly(context)) {
+ if (ImsUtil.shouldPromoteWfc(context)) {
+ resourceId = R.string.incall_error_promote_wfc;
+ } else if (ImsUtil.isWfcModeWifiOnly(context)) {
resourceId = R.string.incall_error_wfc_only_no_wireless_network;
} else if (ImsUtil.isWfcEnabled(context)) {
resourceId = R.string.incall_error_out_of_service_wfc;
@@ -339,6 +350,9 @@
resourceId = R.string.callEnded_pulled;
break;
+ case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
+ resourceId = R.string.callFailed_maximum_reached;
+
case android.telephony.DisconnectCause.OUTGOING_CANCELED:
// We don't want to show any dialog for the canceled case since the call was
// either canceled by the user explicitly (end-call button pushed immediately)
diff --git a/src/com/android/services/telephony/EmergencyCallStateListener.java b/src/com/android/services/telephony/EmergencyCallStateListener.java
index 2346a7f..036872d 100644
--- a/src/com/android/services/telephony/EmergencyCallStateListener.java
+++ b/src/com/android/services/telephony/EmergencyCallStateListener.java
@@ -24,6 +24,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
+import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.SubscriptionController;
@@ -159,30 +160,19 @@
onComplete(true);
cleanup();
} else {
- // The service state changed, but we're still not ready to call yet. (This probably was
- // the transition from STATE_POWER_OFF to STATE_OUT_OF_SERVICE, which happens
- // immediately after powering-on the radio.)
- //
- // So just keep waiting; we'll probably get to either STATE_IN_SERVICE or
- // STATE_EMERGENCY_ONLY very shortly. (Or even if that doesn't happen, we'll at least do
- // another retry when the RETRY_TIMEOUT event fires.)
+ // The service state changed, but we're still not ready to call yet.
Log.d(this, "onServiceStateChanged: not ready to call yet, keep waiting.");
}
}
+ /**
+ * We currently only look to make sure that the radio is on before dialing. We should be able to
+ * make emergency calls at any time after the radio has been powered on and isn't in the
+ * UNAVAILABLE state, even if it is reporting the OUT_OF_SERVICE state.
+ */
private boolean isOkToCall(int serviceState) {
- // Once we reach either STATE_IN_SERVICE or STATE_EMERGENCY_ONLY, it's finally OK to place
- // the emergency call.
- return ((mPhone.getState() == PhoneConstants.State.OFFHOOK)
- || (serviceState == ServiceState.STATE_IN_SERVICE)
- || (serviceState == ServiceState.STATE_EMERGENCY_ONLY))
- // STATE_EMERGENCY_ONLY currently is not used, so we must also check the service
- // state for emergency only calling.
- || (serviceState == ServiceState.STATE_OUT_OF_SERVICE &&
- mPhone.getServiceState().isEmergencyOnly())
- // Allow STATE_OUT_OF_SERVICE if we are at the max number of retries.
- || (mNumRetriesSoFar == MAX_NUM_RETRIES &&
- serviceState == ServiceState.STATE_OUT_OF_SERVICE);
+ return (mPhone.getState() == PhoneConstants.State.OFFHOOK) ||
+ mPhone.getServiceStateTracker().isRadioOn();
}
/**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 62bbfe2..fcee589 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -571,8 +571,12 @@
mConferenceHost.addConnectionListener(mConferenceHostListener);
mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
- setState(mConferenceHost.getState());
+ setConnectionCapabilities(applyHostCapabilities(getConnectionCapabilities(),
+ mConferenceHost.getConnectionCapabilities()));
+ setConnectionProperties(applyHostProperties(getConnectionProperties(),
+ mConferenceHost.getConnectionProperties()));
+ setState(mConferenceHost.getState());
updateStatusHints();
}
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index a874674..d75481b 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -117,6 +117,13 @@
* @param connection
*/
void add(TelephonyConnection connection) {
+ // DO NOT add external calls; we don't want to consider them as a potential conference
+ // member.
+ if ((connection.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) ==
+ Connection.PROPERTY_IS_EXTERNAL_CALL) {
+ return;
+ }
+
// Note: Wrap in Log.VERBOSE to avoid calling connection.toString if we are not going to be
// outputting the value.
if (Log.VERBOSE) {
@@ -134,6 +141,12 @@
* @param connection
*/
void remove(Connection connection) {
+ // External calls are not part of the conference controller, so don't remove them.
+ if ((connection.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) ==
+ Connection.PROPERTY_IS_EXTERNAL_CALL) {
+ return;
+ }
+
if (Log.VERBOSE) {
Log.v(this, "remove connection: %s", connection);
}
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index b5b23b4..a90bc02 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -60,6 +60,7 @@
// This icon is the one that is used when the Slot ID that we have for a particular SIM
// is not supported, i.e. SubscriptionManager.INVALID_SLOT_ID or the 5th SIM in a phone.
private final static int DEFAULT_SIM_ICON = R.drawable.ic_multi_sim;
+ private final static String GROUP_PREFIX = "group_";
final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
private final Phone mPhone;
@@ -101,6 +102,7 @@
// Populate the phone account data.
int subId = mPhone.getSubId();
+ String subscriberId = mPhone.getSubscriberId();
int color = PhoneAccount.NO_HIGHLIGHT_COLOR;
int slotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
String line1Number = mTelephonyManager.getLine1Number(subId);
@@ -216,6 +218,23 @@
icon = Icon.createWithBitmap(bitmap);
}
+ // Check to see if the newly registered account should replace the old account.
+ String groupId = "";
+ String[] mergedImsis = mTelephonyManager.getMergedSubscriberIds();
+ boolean isMergedSim = false;
+ if (mergedImsis != null && subscriberId != null && !isEmergency) {
+ for (String imsi : mergedImsis) {
+ if (imsi.equals(subscriberId)) {
+ isMergedSim = true;
+ break;
+ }
+ }
+ }
+ if(isMergedSim) {
+ groupId = GROUP_PREFIX + line1Number;
+ Log.i(this, "Adding Merged Account with group: " + Log.pii(groupId));
+ }
+
PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
.setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
.setSubscriptionAddress(
@@ -227,6 +246,7 @@
.setSupportedUriSchemes(Arrays.asList(
PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
.setExtras(instantLetteringExtras)
+ .setGroupId(groupId)
.build();
// Register with Telecom and put into the account entry.
@@ -622,7 +642,9 @@
for (Phone phone : phones) {
int subscriptionId = phone.getSubId();
Log.d(this, "Phone with subscription id %d", subscriptionId);
- if (subscriptionId >= 0) {
+ // setupAccounts can be called multiple times during service changes. Don't add an
+ // account if the Icc has not been set yet.
+ if (subscriptionId >= 0 && phone.getFullIccSerialNumber() != null) {
mAccounts.add(new AccountEntry(phone, false /* emergency */,
false /* isDummy */));
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 07cd7b5..c14208f 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -34,6 +34,7 @@
import android.telephony.PhoneNumberUtils;
import android.util.Pair;
+import com.android.ims.ImsCall;
import com.android.ims.ImsCallProfile;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
@@ -44,6 +45,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
@@ -137,6 +139,7 @@
if (isMultiParty) {
notifyConferenceStarted();
}
+ break;
case MSG_CONFERENCE_MERGE_FAILED:
notifyConferenceMergeFailed();
break;
@@ -164,8 +167,9 @@
setVideoState(videoState);
// A change to the video state of the call can influence whether or not it
- // can be part of a conference.
+ // can be part of a conference and whether another call can be added.
refreshConferenceSupported();
+ refreshDisableAddCall();
break;
case MSG_SET_VIDEO_PROVIDER:
@@ -779,10 +783,10 @@
extrasToRemove.add(Connection.EXTRA_ANSWERING_DROPS_FG_CALL);
}
- if (!mOriginalConnection.shouldAllowAddCallDuringVideoCall()) {
- extrasToPut.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL_DURING_VIDEO_CALL, true);
+ if (shouldSetDisableAddCallExtra()) {
+ extrasToPut.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
} else {
- extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL_DURING_VIDEO_CALL);
+ extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL);
}
putExtras(extrasToPut);
removeExtras(extrasToRemove);
@@ -807,6 +811,48 @@
}
}
+ private void refreshDisableAddCall() {
+ if (shouldSetDisableAddCallExtra()) {
+ putExtra(Connection.EXTRA_DISABLE_ADD_CALL, true);
+ } else {
+ removeExtras(Connection.EXTRA_DISABLE_ADD_CALL);
+ }
+ }
+
+ private boolean shouldSetDisableAddCallExtra() {
+ boolean carrierShouldAllowAddCall = mOriginalConnection.shouldAllowAddCallDuringVideoCall();
+ if (carrierShouldAllowAddCall) {
+ return false;
+ }
+ Phone phone = getPhone();
+ if (phone == null) {
+ return false;
+ }
+ boolean isCurrentVideoCall = false;
+ boolean wasVideoCall = false;
+ boolean isWifiCall = false;
+ boolean isVowifiEnabled = false;
+ if (phone instanceof ImsPhone) {
+ ImsPhone imsPhone = (ImsPhone) phone;
+ if (imsPhone.getForegroundCall() != null
+ && imsPhone.getForegroundCall().getImsCall() != null) {
+ ImsCall call = imsPhone.getForegroundCall().getImsCall();
+ isCurrentVideoCall = call.isVideoCall();
+ wasVideoCall = call.wasVideoCall();
+ isWifiCall = call.isWifiCall();
+ }
+
+ isVowifiEnabled = ((ImsPhoneCallTracker) imsPhone.getCallTracker()).isVowifiEnabled();
+ }
+
+ if (isCurrentVideoCall) {
+ return true;
+ } else if (wasVideoCall && isWifiCall && !isVowifiEnabled) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Whether the connection should be treated as an emergency.
* @return {@code true} if the connection should be treated as an emergency call based
@@ -1047,7 +1093,11 @@
break;
case DIALING:
case ALERTING:
- setDialing();
+ if (mOriginalConnection != null && mOriginalConnection.isPulledCall()) {
+ setPulling();
+ } else {
+ setDialing();
+ }
break;
case INCOMING:
case WAITING: