Merge "PhoneCapability cleanup"
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
old mode 100755
new mode 100644
index 835b2b4..0d6ef2c
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -43,6 +43,8 @@
public abstract class Connection {
private static final String TAG = "Connection";
+ public static final String ADHOC_CONFERENCE_ADDRESS = "tel:conf-factory";
+
public interface PostDialListener {
void onPostDialWait();
void onPostDialChar(char c);
@@ -185,6 +187,8 @@
protected String mAddress; // MAY BE NULL!!!
@UnsupportedAppUsage
protected String mDialString; // outgoing calls only
+ protected String[] mParticipantsToDial;// outgoing calls only
+ protected boolean mIsAdhocConference;
@UnsupportedAppUsage
protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
@UnsupportedAppUsage
@@ -314,6 +318,20 @@
}
/**
+ * Gets the participants address (e.g. phone number) associated with connection.
+ *
+ * @return address or null if unavailable
+ */
+ public String[] getParticipantsToDial() {
+ return mParticipantsToDial;
+ }
+
+ // return whether connection is AdhocConference or not
+ public boolean isAdhocConference() {
+ return mIsAdhocConference;
+ }
+
+ /**
* Gets CNAP name associated with connection.
* @return cnap name or null if unavailable
*/
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 1cc5a08..7edb451 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -213,12 +213,6 @@
}
@Override
- public void notifyOemHookRawEventForSubscriber(Phone sender, byte[] rawData) {
- mTelephonyRegistryMgr.notifyOemHookRawEventForSubscriber(sender.getSubId(),
- sender.getPhoneId(), rawData);
- }
-
- @Override
public void notifyPhoneCapabilityChanged(PhoneCapability capability) {
mTelephonyRegistryMgr.notifyPhoneCapabilityChanged(capability);
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 65310d0..85e69d0 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -1222,6 +1222,38 @@
ringingCallState.isAlive());
}
+ private boolean useImsForCall(DialArgs dialArgs) {
+ return isImsUseEnabled()
+ && mImsPhone != null
+ && (mImsPhone.isVolteEnabled() || mImsPhone.isWifiCallingEnabled() ||
+ (mImsPhone.isVideoEnabled() && VideoProfile.isVideo(dialArgs.videoState)))
+ && (mImsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
+ }
+
+ @Override
+ public Connection startConference(String[] participantsToDial, DialArgs dialArgs)
+ throws CallStateException {
+ Phone imsPhone = mImsPhone;
+ boolean useImsForCall = useImsForCall(dialArgs);
+ logd("useImsForCall=" + useImsForCall);
+ if (useImsForCall) {
+ try {
+ if (DBG) logd("Trying IMS PS Conference call");
+ return imsPhone.startConference(participantsToDial, dialArgs);
+ } catch (CallStateException e) {
+ if (DBG) logd("IMS PS conference call exception " + e +
+ "useImsForCall =" + useImsForCall + ", imsPhone =" + imsPhone);
+ CallStateException ce = new CallStateException(e.getError(), e.getMessage());
+ ce.setStackTrace(e.getStackTrace());
+ throw ce;
+ }
+ } else {
+ throw new CallStateException(
+ CallStateException.ERROR_OUT_OF_SERVICE,
+ "cannot dial conference call in out of service");
+ }
+ }
+
@Override
public Connection dial(String dialString, @NonNull DialArgs dialArgs)
throws CallStateException {
@@ -1242,11 +1274,7 @@
boolean allowWpsOverIms = configManager.getConfigForSubId(getSubId())
.getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL);
- boolean useImsForCall = isImsUseEnabled()
- && imsPhone != null
- && (imsPhone.isVolteEnabled() || imsPhone.isWifiCallingEnabled() ||
- (imsPhone.isVideoEnabled() && VideoProfile.isVideo(dialArgs.videoState)))
- && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
+ boolean useImsForCall = useImsForCall(dialArgs)
&& (isWpsCall ? allowWpsOverIms : true);
boolean useImsForEmergency = imsPhone != null
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index b4a4042..e8bd32a 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -703,13 +703,7 @@
break;
case EVENT_UNSOL_OEM_HOOK_RAW:
- ar = (AsyncResult)msg.obj;
- if (ar.exception == null) {
- byte[] data = (byte[])ar.result;
- mNotifier.notifyOemHookRawEventForSubscriber(this, data);
- } else {
- Rlog.e(LOG_TAG, "OEM hook raw exception: " + ar.exception);
- }
+ // deprecated, ignore
break;
case EVENT_CONFIG_LCE:
diff --git a/src/java/com/android/internal/telephony/PhoneInternalInterface.java b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
index 4d94270..757cd8e 100644
--- a/src/java/com/android/internal/telephony/PhoneInternalInterface.java
+++ b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
@@ -438,6 +438,21 @@
Connection dial(String dialString, @NonNull DialArgs dialArgs) throws CallStateException;
/**
+ * Initiate a new conference connection. This happens asynchronously, so you
+ * cannot assume the audio path is connected (or a call index has been
+ * assigned) until PhoneStateChanged notification has occurred.
+ *
+ * @param participantsToDial The participants to dial.
+ * @param dialArgs Parameters to perform the start conference with.
+ * @exception CallStateException if a new outgoing call is not currently
+ * possible because no more call slots exist or a call exists
+ * that is dialing, alerting, ringing, or waiting. Other
+ * errors are handled asynchronously.
+ */
+ Connection startConference(String[] participantsToDial, @NonNull DialArgs dialArgs)
+ throws CallStateException;
+
+ /**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
* without SEND (so <code>dial</code> is not appropriate).
*
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index a762951..aa6c4bc 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -86,9 +86,6 @@
/** Send a notification that the users mobile data setting has changed */
void notifyUserMobileDataStateChanged(Phone sender, boolean state);
- /** Send a notification with an OEM hook payload */
- void notifyOemHookRawEventForSubscriber(Phone sender, byte[] rawData);
-
/** Send a notification that the phone capability has changed */
void notifyPhoneCapabilityChanged(PhoneCapability capability);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index ba718e6..a363003 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -863,6 +863,18 @@
}
@Override
+ public Connection startConference(String[] participantsToDial, DialArgs dialArgs)
+ throws CallStateException {
+ ImsDialArgs.Builder imsDialArgsBuilder;
+ if (!(dialArgs instanceof ImsDialArgs)) {
+ imsDialArgsBuilder = ImsDialArgs.Builder.from(dialArgs);
+ } else {
+ imsDialArgsBuilder = ImsDialArgs.Builder.from((ImsDialArgs) dialArgs);
+ }
+ return mCT.startConference(participantsToDial, imsDialArgsBuilder.build());
+ }
+
+ @Override
public Connection dial(String dialString, DialArgs dialArgs) throws CallStateException {
return dialInternal(dialString, dialArgs, null);
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index da471ec..34994b8f 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -810,6 +810,91 @@
}
}
+ private boolean prepareForDialing(ImsPhone.ImsDialArgs dialArgs) throws CallStateException {
+ boolean holdBeforeDial = false;
+ // note that this triggers call state changed notif
+ clearDisconnected();
+ if (mImsManager == null) {
+ throw new CallStateException("service not available");
+ }
+ // See if there are any issues which preclude placing a call; throw a CallStateException
+ // if there is.
+ checkForDialIssues();
+ int videoState = dialArgs.videoState;
+ if (!canAddVideoCallDuringImsAudioCall(videoState)) {
+ throw new CallStateException("cannot dial in current state");
+ }
+
+ // The new call must be assigned to the foreground call.
+ // That call must be idle, so place anything that's
+ // there on hold
+ if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
+ if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
+ //we should have failed in checkForDialIssues above before we get here
+ throw new CallStateException(CallStateException.ERROR_TOO_MANY_CALLS,
+ "Already too many ongoing calls.");
+ }
+ // foreground call is empty for the newly dialed connection
+ holdBeforeDial = true;
+ mPendingCallVideoState = videoState;
+ mPendingIntentExtras = dialArgs.intentExtras;
+ holdActiveCallForPendingMo();
+ }
+
+ ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
+ ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
+
+ synchronized (mSyncHold) {
+ if (holdBeforeDial) {
+ fgState = mForegroundCall.getState();
+ bgState = mBackgroundCall.getState();
+ //holding foreground call failed
+ if (fgState == ImsPhoneCall.State.ACTIVE) {
+ throw new CallStateException("cannot dial in current state");
+ }
+ //holding foreground call succeeded
+ if (bgState == ImsPhoneCall.State.HOLDING) {
+ holdBeforeDial = false;
+ }
+ }
+ }
+ return holdBeforeDial;
+ }
+
+ public Connection startConference(String[] participantsToDial, ImsPhone.ImsDialArgs dialArgs)
+ throws CallStateException {
+
+ int clirMode = dialArgs.clirMode;
+ int videoState = dialArgs.videoState;
+
+ if (DBG) log("dial clirMode=" + clirMode);
+ boolean holdBeforeDial = prepareForDialing(dialArgs);
+
+ mClirMode = clirMode;
+
+ synchronized (mSyncHold) {
+ mLastDialArgs = dialArgs;
+ mPendingMO = new ImsPhoneConnection(mPhone,
+ participantsToDial, this, mForegroundCall,
+ false);
+ mPendingMO.setVideoState(videoState);
+ if (dialArgs.rttTextStream != null) {
+ log("startConference: setting RTT stream on mPendingMO");
+ mPendingMO.setCurrentRttTextStream(dialArgs.rttTextStream);
+ }
+ }
+ addConnection(mPendingMO);
+
+ if (!holdBeforeDial) {
+ dialInternal(mPendingMO, clirMode, videoState, dialArgs.intentExtras);
+ }
+
+ updatePhoneState();
+ mPhone.notifyPreciseCallStateChanged();
+
+ return mPendingMO;
+ }
+
@UnsupportedAppUsage
public Connection dial(String dialString, int videoState, Bundle intentExtras) throws
CallStateException {
@@ -845,20 +930,8 @@
dialString = convertNumberIfNecessary(mPhone, dialString);
}
- // note that this triggers call state changed notif
- clearDisconnected();
-
- if (mImsManager == null) {
- throw new CallStateException("service not available");
- }
-
- // See if there are any issues which preclude placing a call; throw a CallStateException
- // if there is.
- checkForDialIssues();
-
- if (!canAddVideoCallDuringImsAudioCall(videoState)) {
- throw new CallStateException("cannot dial in current state");
- }
+ mClirMode = clirMode;
+ boolean holdBeforeDial = prepareForDialing(dialArgs);
if (isPhoneInEcmMode && isEmergencyNumber) {
handleEcmTimer(ImsPhone.CANCEL_ECM_TIMER);
@@ -872,46 +945,10 @@
videoState = VideoProfile.STATE_AUDIO_ONLY;
}
- boolean holdBeforeDial = false;
-
- // The new call must be assigned to the foreground call.
- // That call must be idle, so place anything that's
- // there on hold
- if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
- if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
- //we should have failed in checkForDialIssues above before we get here
- throw new CallStateException(CallStateException.ERROR_TOO_MANY_CALLS,
- "Already too many ongoing calls.");
- }
- // foreground call is empty for the newly dialed connection
- holdBeforeDial = true;
- // Cache the video state for pending MO call.
- mPendingCallVideoState = videoState;
- mPendingIntentExtras = dialArgs.intentExtras;
- holdActiveCallForPendingMo();
- }
-
- ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
- ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
-
- mClirMode = clirMode;
+ // Cache the video state for pending MO call.
+ mPendingCallVideoState = videoState;
synchronized (mSyncHold) {
- if (holdBeforeDial) {
- fgState = mForegroundCall.getState();
- bgState = mBackgroundCall.getState();
-
- //holding foreground call failed
- if (fgState == ImsPhoneCall.State.ACTIVE) {
- throw new CallStateException("cannot dial in current state");
- }
-
- //holding foreground call succeeded
- if (bgState == ImsPhoneCall.State.HOLDING) {
- holdBeforeDial = false;
- }
- }
-
mLastDialString = dialString;
mLastDialArgs = dialArgs;
mPendingMO = new ImsPhoneConnection(mPhone,
@@ -1122,8 +1159,9 @@
return;
}
- if (conn.getAddress()== null || conn.getAddress().length() == 0
- || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
+ if (!conn.isAdhocConference() &&
+ (conn.getAddress()== null || conn.getAddress().length() == 0
+ || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0)) {
// Phone number is invalid
conn.setDisconnectCause(DisconnectCause.INVALID_NUMBER);
sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
@@ -1142,6 +1180,9 @@
try {
String[] callees = new String[] { conn.getAddress() };
ImsCallProfile profile = mImsManager.createCallProfile(serviceType, callType);
+ if (conn.isAdhocConference()) {
+ profile.setCallExtraBoolean(ImsCallProfile.EXTRA_CONFERENCE, true);
+ }
profile.setCallExtraInt(ImsCallProfile.EXTRA_OIR, clirMode);
if (isEmergencyCall) {
@@ -1181,7 +1222,9 @@
// being sent to the lower layers/to the network.
}
- ImsCall imsCall = mImsManager.makeCall(profile, callees, mImsCallListener);
+ ImsCall imsCall = mImsManager.makeCall(profile,
+ conn.isAdhocConference() ? conn.getParticipantsToDial() : callees,
+ mImsCallListener);
conn.setImsCall(imsCall);
mMetrics.writeOnImsCallStart(mPhone.getPhoneId(),
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
index 0a6c215..f87876d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -186,6 +186,7 @@
mHandler = new MyHandler(mOwner.getLooper());
mHandlerMessenger = new Messenger(mHandler);
mImsCall = imsCall;
+ mIsAdhocConference = isMultiparty();
if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
@@ -261,6 +262,37 @@
}
}
+ /** This is an MO conference call, created when dialing */
+ public ImsPhoneConnection(Phone phone, String[] participantsToDial, ImsPhoneCallTracker ct,
+ ImsPhoneCall parent, boolean isEmergency) {
+ super(PhoneConstants.PHONE_TYPE_IMS);
+ createWakeLock(phone.getContext());
+ acquireWakeLock();
+
+ mOwner = ct;
+ mHandler = new MyHandler(mOwner.getLooper());
+ mHandlerMessenger = new Messenger(mHandler);
+
+ mDialString = mAddress = Connection.ADHOC_CONFERENCE_ADDRESS;
+ mParticipantsToDial = participantsToDial;
+ mIsAdhocConference = true;
+
+ mIsIncoming = false;
+ mCnapName = null;
+ mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
+ mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
+ mCreateTime = System.currentTimeMillis();
+
+ mParent = parent;
+ parent.attachFake(this, ImsPhoneCall.State.DIALING);
+
+ if (phone.getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
+ setAudioModeIsVoip(true);
+ }
+ }
+
+
public void dispose() {
}
@@ -1280,6 +1312,8 @@
sb.append(getTelecomCallId());
sb.append(" address: ");
sb.append(Rlog.pii(LOG_TAG, getAddress()));
+ sb.append(" isAdhocConf: ");
+ sb.append(isAdhocConference() ? "Y" : "N");
sb.append(" ImsCall: ");
synchronized (this) {
if (mImsCall == null) {
diff --git a/src/java/com/android/internal/telephony/sip/SipPhone.java b/src/java/com/android/internal/telephony/sip/SipPhone.java
index 72fd9da..8e85e9a 100644
--- a/src/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhone.java
@@ -186,6 +186,12 @@
}
@Override
+ public Connection startConference(String[] participantsToDial, DialArgs dialArgs)
+ throws CallStateException {
+ throw new CallStateException("startConference: not supported");
+ }
+
+ @Override
public Connection dial(String dialString, DialArgs dialArgs) throws CallStateException {
synchronized (SipPhone.class) {
return dialInternal(dialString, dialArgs.videoState);