summaryrefslogtreecommitdiffstats
path: root/telephony
diff options
context:
space:
mode:
authorChung-yih Wang <cywang@google.com>2010-08-05 14:19:30 +0800
committerChung-yih Wang <cywang@google.com>2010-08-05 14:21:19 +0800
commitccd0b6953f5f77d1da5f540a3ba5ea71116e14f0 (patch)
treefde81ddc550d35c1ab436e503a0dd6651c38ec55 /telephony
parentcde66df44240cfe5a7bec12ac52464c3bf26c14f (diff)
downloadframeworks_base-ccd0b6953f5f77d1da5f540a3ba5ea71116e14f0.zip
frameworks_base-ccd0b6953f5f77d1da5f540a3ba5ea71116e14f0.tar.gz
frameworks_base-ccd0b6953f5f77d1da5f540a3ba5ea71116e14f0.tar.bz2
Revert "Revert "Move SIP telephony related codes to framework.""
This reverts commit cde66df44240cfe5a7bec12ac52464c3bf26c14f. Change-Id: I87da883b45350ec8f7da71e9bd392b075ea30ca7
Diffstat (limited to 'telephony')
-rw-r--r--telephony/java/com/android/internal/telephony/SipPhoneNotifier.java236
-rw-r--r--telephony/java/com/android/internal/telephony/sip/CallFailCause.java50
-rw-r--r--telephony/java/com/android/internal/telephony/sip/CallProxy.java114
-rw-r--r--telephony/java/com/android/internal/telephony/sip/SipCallBase.java103
-rw-r--r--telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java373
-rw-r--r--telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java246
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhone.java760
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhoneBase.java558
-rw-r--r--telephony/java/com/android/internal/telephony/sip/SipPhoneFactory.java67
-rw-r--r--telephony/java/com/android/internal/telephony/sip/SipPhoneProxy.java749
10 files changed, 3256 insertions, 0 deletions
diff --git a/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java b/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java
new file mode 100644
index 0000000..81e151e
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.telephony.ITelephonyRegistry;
+
+/**
+ * Temporary. Will be removed after integrating with CallManager.
+ * 100% copy from DefaultPhoneNotifier. Cannot access its package level
+ * constructor; thus the copy.
+ * @hide
+ */
+public class SipPhoneNotifier implements PhoneNotifier {
+
+ static final String LOG_TAG = "GSM";
+ private static final boolean DBG = true;
+ private ITelephonyRegistry mRegistry;
+
+ public SipPhoneNotifier() {
+ mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
+ "telephony.registry"));
+ }
+
+ public void notifyPhoneState(Phone sender) {
+ Call ringingCall = sender.getRingingCall();
+ String incomingNumber = "";
+ if (ringingCall != null && ringingCall.getEarliestConnection() != null){
+ incomingNumber = ringingCall.getEarliestConnection().getAddress();
+ }
+ try {
+ mRegistry.notifyCallState(convertCallState(sender.getState()), incomingNumber);
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyServiceState(Phone sender) {
+ try {
+ mRegistry.notifyServiceState(sender.getServiceState());
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifySignalStrength(Phone sender) {
+ try {
+ mRegistry.notifySignalStrength(sender.getSignalStrength());
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyMessageWaitingChanged(Phone sender) {
+ try {
+ mRegistry.notifyMessageWaitingChanged(sender.getMessageWaitingIndicator());
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyCallForwardingChanged(Phone sender) {
+ try {
+ mRegistry.notifyCallForwardingChanged(sender.getCallForwardingIndicator());
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyDataActivity(Phone sender) {
+ try {
+ mRegistry.notifyDataActivity(convertDataActivityState(sender.getDataActivityState()));
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyDataConnection(Phone sender, String reason) {
+ TelephonyManager telephony = TelephonyManager.getDefault();
+ try {
+ mRegistry.notifyDataConnection(
+ convertDataState(sender.getDataConnectionState()),
+ sender.isDataConnectivityPossible(), reason,
+ sender.getActiveApn(),
+ sender.getActiveApnTypes(),
+ sender.getInterfaceName(null),
+ ((telephony!=null) ? telephony.getNetworkType() :
+ TelephonyManager.NETWORK_TYPE_UNKNOWN));
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyDataConnectionFailed(Phone sender, String reason) {
+ try {
+ mRegistry.notifyDataConnectionFailed(reason);
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ public void notifyCellLocation(Phone sender) {
+ Bundle data = new Bundle();
+ sender.getCellLocation().fillInNotifierBundle(data);
+ try {
+ mRegistry.notifyCellLocation(data);
+ } catch (RemoteException ex) {
+ // system process is dead
+ }
+ }
+
+ private void log(String s) {
+ Log.d(LOG_TAG, "[PhoneNotifier] " + s);
+ }
+
+ /**
+ * Convert the {@link State} enum into the TelephonyManager.CALL_STATE_* constants
+ * for the public API.
+ */
+ public static int convertCallState(Phone.State state) {
+ switch (state) {
+ case RINGING:
+ return TelephonyManager.CALL_STATE_RINGING;
+ case OFFHOOK:
+ return TelephonyManager.CALL_STATE_OFFHOOK;
+ default:
+ return TelephonyManager.CALL_STATE_IDLE;
+ }
+ }
+
+ /**
+ * Convert the TelephonyManager.CALL_STATE_* constants into the {@link State} enum
+ * for the public API.
+ */
+ public static Phone.State convertCallState(int state) {
+ switch (state) {
+ case TelephonyManager.CALL_STATE_RINGING:
+ return Phone.State.RINGING;
+ case TelephonyManager.CALL_STATE_OFFHOOK:
+ return Phone.State.OFFHOOK;
+ default:
+ return Phone.State.IDLE;
+ }
+ }
+
+ /**
+ * Convert the {@link DataState} enum into the TelephonyManager.DATA_* constants
+ * for the public API.
+ */
+ public static int convertDataState(Phone.DataState state) {
+ switch (state) {
+ case CONNECTING:
+ return TelephonyManager.DATA_CONNECTING;
+ case CONNECTED:
+ return TelephonyManager.DATA_CONNECTED;
+ case SUSPENDED:
+ return TelephonyManager.DATA_SUSPENDED;
+ default:
+ return TelephonyManager.DATA_DISCONNECTED;
+ }
+ }
+
+ /**
+ * Convert the TelephonyManager.DATA_* constants into {@link DataState} enum
+ * for the public API.
+ */
+ public static Phone.DataState convertDataState(int state) {
+ switch (state) {
+ case TelephonyManager.DATA_CONNECTING:
+ return Phone.DataState.CONNECTING;
+ case TelephonyManager.DATA_CONNECTED:
+ return Phone.DataState.CONNECTED;
+ case TelephonyManager.DATA_SUSPENDED:
+ return Phone.DataState.SUSPENDED;
+ default:
+ return Phone.DataState.DISCONNECTED;
+ }
+ }
+
+ /**
+ * Convert the {@link DataState} enum into the TelephonyManager.DATA_* constants
+ * for the public API.
+ */
+ public static int convertDataActivityState(Phone.DataActivityState state) {
+ switch (state) {
+ case DATAIN:
+ return TelephonyManager.DATA_ACTIVITY_IN;
+ case DATAOUT:
+ return TelephonyManager.DATA_ACTIVITY_OUT;
+ case DATAINANDOUT:
+ return TelephonyManager.DATA_ACTIVITY_INOUT;
+ case DORMANT:
+ return TelephonyManager.DATA_ACTIVITY_DORMANT;
+ default:
+ return TelephonyManager.DATA_ACTIVITY_NONE;
+ }
+ }
+
+ /**
+ * Convert the TelephonyManager.DATA_* constants into the {@link DataState} enum
+ * for the public API.
+ */
+ public static Phone.DataActivityState convertDataActivityState(int state) {
+ switch (state) {
+ case TelephonyManager.DATA_ACTIVITY_IN:
+ return Phone.DataActivityState.DATAIN;
+ case TelephonyManager.DATA_ACTIVITY_OUT:
+ return Phone.DataActivityState.DATAOUT;
+ case TelephonyManager.DATA_ACTIVITY_INOUT:
+ return Phone.DataActivityState.DATAINANDOUT;
+ case TelephonyManager.DATA_ACTIVITY_DORMANT:
+ return Phone.DataActivityState.DORMANT;
+ default:
+ return Phone.DataActivityState.NONE;
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/CallFailCause.java b/telephony/java/com/android/internal/telephony/sip/CallFailCause.java
new file mode 100644
index 0000000..58fb408
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/CallFailCause.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+/**
+ * Call fail causes from TS 24.008 .
+ * These are mostly the cause codes we need to distinguish for the UI.
+ * See 22.001 Annex F.4 for mapping of cause codes to local tones.
+ *
+ * {@hide}
+ *
+ */
+public interface CallFailCause {
+ static final int NORMAL_CLEARING = 16;
+ // Busy Tone
+ static final int USER_BUSY = 17;
+
+ // No Tone
+ static final int NUMBER_CHANGED = 22;
+ static final int STATUS_ENQUIRY = 30;
+ static final int NORMAL_UNSPECIFIED = 31;
+
+ // Congestion Tone
+ static final int NO_CIRCUIT_AVAIL = 34;
+ static final int TEMPORARY_FAILURE = 41;
+ static final int SWITCHING_CONGESTION = 42;
+ static final int CHANNEL_NOT_AVAIL = 44;
+ static final int QOS_NOT_AVAIL = 49;
+ static final int BEARER_NOT_AVAIL = 58;
+
+ // others
+ static final int ACM_LIMIT_EXCEEDED = 68;
+ static final int CALL_BARRED = 240;
+ static final int FDN_BLOCKED = 241;
+ static final int ERROR_UNSPECIFIED = 0xffff;
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/CallProxy.java b/telephony/java/com/android/internal/telephony/sip/CallProxy.java
new file mode 100644
index 0000000..fad9663
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/CallProxy.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import com.android.internal.telephony.*;
+import java.util.List;
+
+// TODO: remove this class after integrating with CallManager
+class CallProxy extends Call {
+ private Call mTarget;
+
+ void setTarget(Call target) {
+ mTarget = target;
+ }
+
+ @Override
+ public List<Connection> getConnections() {
+ return mTarget.getConnections();
+ }
+
+ @Override
+ public Phone getPhone() {
+ return mTarget.getPhone();
+ }
+
+ @Override
+ public boolean isMultiparty() {
+ return mTarget.isMultiparty();
+ }
+
+ @Override
+ public void hangup() throws CallStateException {
+ mTarget.hangup();
+ }
+
+ @Override
+ public boolean hasConnection(Connection c) {
+ return mTarget.hasConnection(c);
+ }
+
+ @Override
+ public boolean hasConnections() {
+ return mTarget.hasConnections();
+ }
+
+ @Override
+ public State getState() {
+ return mTarget.getState();
+ }
+
+ @Override
+ public boolean isIdle() {
+ return mTarget.isIdle();
+ }
+
+ @Override
+ public Connection getEarliestConnection() {
+ return mTarget.getEarliestConnection();
+ }
+
+ @Override
+ public long getEarliestCreateTime() {
+ return mTarget.getEarliestCreateTime();
+ }
+
+ @Override
+ public long getEarliestConnectTime() {
+ return mTarget.getEarliestConnectTime();
+ }
+
+ @Override
+ public boolean isDialingOrAlerting() {
+ return mTarget.isDialingOrAlerting();
+ }
+
+ @Override
+ public boolean isRinging() {
+ return mTarget.isRinging();
+ }
+
+ @Override
+ public Connection getLatestConnection() {
+ return mTarget.getLatestConnection();
+ }
+
+ @Override
+ public boolean isGeneric() {
+ return mTarget.isGeneric();
+ }
+
+ @Override
+ public void setGeneric(boolean generic) {
+ mTarget.setGeneric(generic);
+ }
+
+ @Override
+ public void hangupIfAlive() {
+ mTarget.hangupIfAlive();
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipCallBase.java b/telephony/java/com/android/internal/telephony/sip/SipCallBase.java
new file mode 100644
index 0000000..e7eda4f
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipCallBase.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.Phone;
+
+import android.net.sip.SipManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.sip.SipException;
+
+abstract class SipCallBase extends Call {
+ private static final int MAX_CONNECTIONS_PER_CALL = 5;
+
+ protected List<Connection> connections = new ArrayList<Connection>();
+
+ protected abstract void setState(State newState);
+
+ public void dispose() {
+ }
+
+ public List<Connection> getConnections() {
+ // FIXME should return Collections.unmodifiableList();
+ return connections;
+ }
+
+ public boolean isMultiparty() {
+ return connections.size() > 1;
+ }
+
+ public String toString() {
+ return state.toString();
+ }
+
+ /**
+ * Called by SipConnection when it has disconnected
+ */
+ void connectionDisconnected(Connection conn) {
+ if (state != State.DISCONNECTED) {
+ /* If only disconnected connections remain, we are disconnected*/
+
+ boolean hasOnlyDisconnectedConnections = true;
+
+ for (int i = 0, s = connections.size() ; i < s; i ++) {
+ if (connections.get(i).getState()
+ != State.DISCONNECTED
+ ) {
+ hasOnlyDisconnectedConnections = false;
+ break;
+ }
+ }
+
+ if (hasOnlyDisconnectedConnections) {
+ state = State.DISCONNECTED;
+ }
+ }
+ }
+
+
+ /*package*/ void detach(Connection conn) {
+ connections.remove(conn);
+
+ if (connections.size() == 0) {
+ state = State.IDLE;
+ }
+ }
+
+ /**
+ * @return true if there's no space in this call for additional
+ * connections to be added via "conference"
+ */
+ /*package*/ boolean isFull() {
+ return connections.size() == MAX_CONNECTIONS_PER_CALL;
+ }
+
+ void clearDisconnected() {
+ for (Iterator<Connection> it = connections.iterator(); it.hasNext(); ) {
+ Connection c = it.next();
+ if (c.getState() == State.DISCONNECTED) it.remove();
+ }
+
+ if (connections.isEmpty()) setState(State.IDLE);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
new file mode 100644
index 0000000..33c89f8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.UUSInfo;
+import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
+
+/**
+ * SIP doesn't need CommandsInterface. The class does nothing but made to work
+ * with PhoneBase's constructor.
+ */
+class SipCommandInterface extends BaseCommands implements CommandsInterface {
+ SipCommandInterface(Context context) {
+ super(context);
+ }
+
+ @Override public void setOnNITZTime(Handler h, int what, Object obj) {
+ }
+
+ public void getIccCardStatus(Message result) {
+ }
+
+ public void supplyIccPin(String pin, Message result) {
+ }
+
+ public void supplyIccPuk(String puk, String newPin, Message result) {
+ }
+
+ public void supplyIccPin2(String pin, Message result) {
+ }
+
+ public void supplyIccPuk2(String puk, String newPin2, Message result) {
+ }
+
+ public void changeIccPin(String oldPin, String newPin, Message result) {
+ }
+
+ public void changeIccPin2(String oldPin2, String newPin2, Message result) {
+ }
+
+ public void changeBarringPassword(String facility, String oldPwd,
+ String newPwd, Message result) {
+ }
+
+ public void supplyNetworkDepersonalization(String netpin, Message result) {
+ }
+
+ public void getCurrentCalls(Message result) {
+ }
+
+ @Deprecated public void getPDPContextList(Message result) {
+ }
+
+ public void getDataCallList(Message result) {
+ }
+
+ public void dial(String address, int clirMode, Message result) {
+ }
+
+ public void dial(String address, int clirMode, UUSInfo uusInfo,
+ Message result) {
+ }
+
+ public void getIMSI(Message result) {
+ }
+
+ public void getIMEI(Message result) {
+ }
+
+ public void getIMEISV(Message result) {
+ }
+
+
+ public void hangupConnection (int gsmIndex, Message result) {
+ }
+
+ public void hangupWaitingOrBackground (Message result) {
+ }
+
+ public void hangupForegroundResumeBackground (Message result) {
+ }
+
+ public void switchWaitingOrHoldingAndActive (Message result) {
+ }
+
+ public void conference (Message result) {
+ }
+
+
+ public void setPreferredVoicePrivacy(boolean enable, Message result) {
+ }
+
+ public void getPreferredVoicePrivacy(Message result) {
+ }
+
+ public void separateConnection (int gsmIndex, Message result) {
+ }
+
+ public void acceptCall (Message result) {
+ }
+
+ public void rejectCall (Message result) {
+ }
+
+ public void explicitCallTransfer (Message result) {
+ }
+
+ public void getLastCallFailCause (Message result) {
+ }
+
+ /** @deprecated */
+ public void getLastPdpFailCause (Message result) {
+ }
+
+ public void getLastDataCallFailCause (Message result) {
+ }
+
+ public void setMute (boolean enableMute, Message response) {
+ }
+
+ public void getMute (Message response) {
+ }
+
+ public void getSignalStrength (Message result) {
+ }
+
+ public void getRegistrationState (Message result) {
+ }
+
+ public void getGPRSRegistrationState (Message result) {
+ }
+
+ public void getOperator(Message result) {
+ }
+
+ public void sendDtmf(char c, Message result) {
+ }
+
+ public void startDtmf(char c, Message result) {
+ }
+
+ public void stopDtmf(Message result) {
+ }
+
+ public void sendBurstDtmf(String dtmfString, int on, int off,
+ Message result) {
+ }
+
+ public void sendSMS (String smscPDU, String pdu, Message result) {
+ }
+
+ public void sendCdmaSms(byte[] pdu, Message result) {
+ }
+
+ public void deleteSmsOnSim(int index, Message response) {
+ }
+
+ public void deleteSmsOnRuim(int index, Message response) {
+ }
+
+ public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
+ }
+
+ public void writeSmsToRuim(int status, String pdu, Message response) {
+ }
+
+ public void setupDefaultPDP(String apn, String user, String password,
+ Message result) {
+ }
+
+ public void deactivateDefaultPDP(int cid, Message result) {
+ }
+
+ public void setupDataCall(String radioTechnology, String profile,
+ String apn, String user, String password, String authType,
+ Message result) {
+ }
+
+ public void deactivateDataCall(int cid, Message result) {
+ }
+
+ public void setRadioPower(boolean on, Message result) {
+ }
+
+ public void setSuppServiceNotifications(boolean enable, Message result) {
+ }
+
+ public void acknowledgeLastIncomingGsmSms(boolean success, int cause,
+ Message result) {
+ }
+
+ public void acknowledgeLastIncomingCdmaSms(boolean success, int cause,
+ Message result) {
+ }
+
+
+ public void iccIO (int command, int fileid, String path, int p1, int p2,
+ int p3, String data, String pin2, Message result) {
+ }
+
+ public void getCLIR(Message result) {
+ }
+
+ public void setCLIR(int clirMode, Message result) {
+ }
+
+ public void queryCallWaiting(int serviceClass, Message response) {
+ }
+
+ public void setCallWaiting(boolean enable, int serviceClass,
+ Message response) {
+ }
+
+ public void setNetworkSelectionModeAutomatic(Message response) {
+ }
+
+ public void setNetworkSelectionModeManual(
+ String operatorNumeric, Message response) {
+ }
+
+ public void getNetworkSelectionMode(Message response) {
+ }
+
+ public void getAvailableNetworks(Message response) {
+ }
+
+ public void setCallForward(int action, int cfReason, int serviceClass,
+ String number, int timeSeconds, Message response) {
+ }
+
+ public void queryCallForwardStatus(int cfReason, int serviceClass,
+ String number, Message response) {
+ }
+
+ public void queryCLIP(Message response) {
+ }
+
+ public void getBasebandVersion (Message response) {
+ }
+
+ public void queryFacilityLock (String facility, String password,
+ int serviceClass, Message response) {
+ }
+
+ public void setFacilityLock (String facility, boolean lockState,
+ String password, int serviceClass, Message response) {
+ }
+
+ public void sendUSSD (String ussdString, Message response) {
+ }
+
+ public void cancelPendingUssd (Message response) {
+ }
+
+ public void resetRadio(Message result) {
+ }
+
+ public void invokeOemRilRequestRaw(byte[] data, Message response) {
+ }
+
+ public void invokeOemRilRequestStrings(String[] strings, Message response) {
+ }
+
+ public void setBandMode (int bandMode, Message response) {
+ }
+
+ public void queryAvailableBandMode (Message response) {
+ }
+
+ public void sendTerminalResponse(String contents, Message response) {
+ }
+
+ public void sendEnvelope(String contents, Message response) {
+ }
+
+ public void handleCallSetupRequestFromSim(
+ boolean accept, Message response) {
+ }
+
+ public void setPreferredNetworkType(int networkType , Message response) {
+ }
+
+ public void getPreferredNetworkType(Message response) {
+ }
+
+ public void getNeighboringCids(Message response) {
+ }
+
+ public void setLocationUpdates(boolean enable, Message response) {
+ }
+
+ public void getSmscAddress(Message result) {
+ }
+
+ public void setSmscAddress(String address, Message result) {
+ }
+
+ public void reportSmsMemoryStatus(boolean available, Message result) {
+ }
+
+ public void reportStkServiceIsRunning(Message result) {
+ }
+
+ public void getGsmBroadcastConfig(Message response) {
+ }
+
+ public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) {
+ }
+
+ public void setGsmBroadcastActivation(boolean activate, Message response) {
+ }
+
+
+ // ***** Methods for CDMA support
+ public void getDeviceIdentity(Message response) {
+ }
+
+ public void getCDMASubscription(Message response) {
+ }
+
+ public void setPhoneType(int phoneType) { //Set by CDMAPhone and GSMPhone constructor
+ }
+
+ public void queryCdmaRoamingPreference(Message response) {
+ }
+
+ public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+ }
+
+ public void setCdmaSubscription(int cdmaSubscription , Message response) {
+ }
+
+ public void queryTTYMode(Message response) {
+ }
+
+ public void setTTYMode(int ttyMode, Message response) {
+ }
+
+ public void sendCDMAFeatureCode(String FeatureCode, Message response) {
+ }
+
+ public void getCdmaBroadcastConfig(Message response) {
+ }
+
+ public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) {
+ }
+
+ public void setCdmaBroadcastActivation(boolean activate, Message response) {
+ }
+
+ public void exitEmergencyCallbackMode(Message response) {
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
new file mode 100644
index 0000000..d48f94a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import android.content.Context;
+import android.net.sip.SipAudioCall;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.SystemClock;
+import android.util.Log;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
+
+import com.android.internal.telephony.*;
+
+abstract class SipConnectionBase extends Connection {
+ //***** Event Constants
+ private static final int EVENT_DTMF_DONE = 1;
+ private static final int EVENT_PAUSE_DONE = 2;
+ private static final int EVENT_NEXT_POST_DIAL = 3;
+ private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
+
+ //***** Constants
+ private static final int PAUSE_DELAY_FIRST_MILLIS = 100;
+ private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
+ private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
+
+ private static final String LOG_TAG = "SIP_CONN";
+
+ private SipAudioCall mSipAudioCall;
+
+ private String dialString; // outgoing calls only
+ private String postDialString; // outgoing calls only
+ private int nextPostDialChar; // index into postDialString
+ private boolean isIncoming;
+ private boolean disconnected;
+
+ int index; // index in SipCallTracker.connections[], -1 if unassigned
+ // The Sip index is 1 + this
+
+ /*
+ * These time/timespan values are based on System.currentTimeMillis(),
+ * i.e., "wall clock" time.
+ */
+ private long createTime;
+ private long connectTime;
+ private long disconnectTime;
+
+ /*
+ * These time/timespan values are based on SystemClock.elapsedRealTime(),
+ * i.e., time since boot. They are appropriate for comparison and
+ * calculating deltas.
+ */
+ private long connectTimeReal;
+ private long duration;
+ private long holdingStartTime; // The time when the Connection last transitioned
+ // into HOLDING
+
+ private DisconnectCause mCause = DisconnectCause.NOT_DISCONNECTED;
+ private PostDialState postDialState = PostDialState.NOT_STARTED;
+
+ SipConnectionBase(String calleeSipUri) {
+ dialString = calleeSipUri;
+
+ postDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
+
+ isIncoming = false;
+ createTime = System.currentTimeMillis();
+ }
+
+ protected void setState(Call.State state) {
+ switch (state) {
+ case ACTIVE:
+ connectTimeReal = SystemClock.elapsedRealtime();
+ connectTime = System.currentTimeMillis();
+ break;
+ case DISCONNECTED:
+ duration = SystemClock.elapsedRealtime() - connectTimeReal;
+ disconnectTime = System.currentTimeMillis();
+ break;
+ case HOLDING:
+ holdingStartTime = SystemClock.elapsedRealtime();
+ break;
+ }
+ }
+
+ @Override
+ public long getCreateTime() {
+ return createTime;
+ }
+
+ @Override
+ public long getConnectTime() {
+ return connectTime;
+ }
+
+ @Override
+ public long getDisconnectTime() {
+ return disconnectTime;
+ }
+
+ @Override
+ public long getDurationMillis() {
+ if (connectTimeReal == 0) {
+ return 0;
+ } else if (duration == 0) {
+ return SystemClock.elapsedRealtime() - connectTimeReal;
+ } else {
+ return duration;
+ }
+ }
+
+ @Override
+ public long getHoldDurationMillis() {
+ if (getState() != Call.State.HOLDING) {
+ // If not holding, return 0
+ return 0;
+ } else {
+ return SystemClock.elapsedRealtime() - holdingStartTime;
+ }
+ }
+
+ @Override
+ public DisconnectCause getDisconnectCause() {
+ return mCause;
+ }
+
+ void setDisconnectCause(DisconnectCause cause) {
+ mCause = cause;
+ }
+
+ @Override
+ public PostDialState getPostDialState() {
+ return postDialState;
+ }
+
+ @Override
+ public void proceedAfterWaitChar() {
+ // TODO
+ }
+
+ @Override
+ public void proceedAfterWildChar(String str) {
+ // TODO
+ }
+
+ @Override
+ public void cancelPostDial() {
+ // TODO
+ }
+
+ protected abstract Phone getPhone();
+
+ DisconnectCause disconnectCauseFromCode(int causeCode) {
+ /**
+ * See 22.001 Annex F.4 for mapping of cause codes
+ * to local tones
+ */
+
+ switch (causeCode) {
+ case CallFailCause.USER_BUSY:
+ return DisconnectCause.BUSY;
+
+ case CallFailCause.NO_CIRCUIT_AVAIL:
+ case CallFailCause.TEMPORARY_FAILURE:
+ case CallFailCause.SWITCHING_CONGESTION:
+ case CallFailCause.CHANNEL_NOT_AVAIL:
+ case CallFailCause.QOS_NOT_AVAIL:
+ case CallFailCause.BEARER_NOT_AVAIL:
+ return DisconnectCause.CONGESTION;
+
+ case CallFailCause.ACM_LIMIT_EXCEEDED:
+ return DisconnectCause.LIMIT_EXCEEDED;
+
+ case CallFailCause.CALL_BARRED:
+ return DisconnectCause.CALL_BARRED;
+
+ case CallFailCause.FDN_BLOCKED:
+ return DisconnectCause.FDN_BLOCKED;
+
+ case CallFailCause.ERROR_UNSPECIFIED:
+ case CallFailCause.NORMAL_CLEARING:
+ default:
+ Phone phone = getPhone();
+ int serviceState = phone.getServiceState().getState();
+ if (serviceState == ServiceState.STATE_POWER_OFF) {
+ return DisconnectCause.POWER_OFF;
+ } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
+ || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
+ return DisconnectCause.OUT_OF_SERVICE;
+ } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
+ return DisconnectCause.ERROR_UNSPECIFIED;
+ } else if (causeCode == CallFailCause.NORMAL_CLEARING) {
+ return DisconnectCause.NORMAL;
+ } else {
+ // If nothing else matches, report unknown call drop reason
+ // to app, not NORMAL call end.
+ return DisconnectCause.ERROR_UNSPECIFIED;
+ }
+ }
+ }
+
+ @Override
+ public String getRemainingPostDialString() {
+ if (postDialState == PostDialState.CANCELLED
+ || postDialState == PostDialState.COMPLETE
+ || postDialString == null
+ || postDialString.length() <= nextPostDialChar) {
+ return "";
+ }
+
+ return postDialString.substring(nextPostDialChar);
+ }
+
+ private void log(String msg) {
+ Log.d(LOG_TAG, "[SipConn] " + msg);
+ }
+
+ @Override
+ public int getNumberPresentation() {
+ // TODO: add PRESENTATION_URL
+ return Connection.PRESENTATION_ALLOWED;
+ }
+
+ /*
+ @Override
+ public UUSInfo getUUSInfo() {
+ // FIXME: what's this for SIP?
+ return null;
+ }
+ */
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
new file mode 100755
index 0000000..4e61d30
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -0,0 +1,760 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.net.rtp.AudioGroup;
+import android.net.sip.SipAudioCall;
+import android.net.sip.SipManager;
+import android.net.sip.SipProfile;
+import android.net.sip.SipSessionState;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
+import android.preference.PreferenceManager;
+import android.provider.Telephony;
+import android.telephony.CellLocation;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.PhoneSubInfo;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.UUSInfo;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sip.SipException;
+
+/**
+ * {@hide}
+ */
+public class SipPhone extends SipPhoneBase {
+ private static final String LOG_TAG = "SipPhone";
+ private static final boolean LOCAL_DEBUG = true;
+
+ //private List<SipConnection> connections = new ArrayList<SipConnection>();
+
+ // A call that is ringing or (call) waiting
+ private SipCall ringingCall = new SipCall();
+ private SipCall foregroundCall = new SipCall();
+ private SipCall backgroundCall = new SipCall();
+
+ private SipManager mSipManager;
+ private SipProfile mProfile;
+
+ SipPhone (Context context, PhoneNotifier notifier, SipProfile profile) {
+ super(context, notifier);
+
+ Log.v(LOG_TAG, " +++++++++++++++++++++ new SipPhone: " + profile.getUriString());
+ ringingCall = new SipCall();
+ foregroundCall = new SipCall();
+ backgroundCall = new SipCall();
+ mProfile = profile;
+ mSipManager = SipManager.getInstance(context);
+
+ // FIXME: what's this for SIP?
+ //Change the system property
+ //SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
+ // new Integer(Phone.PHONE_TYPE_GSM).toString());
+ }
+
+ public String getPhoneName() {
+ return mProfile.getProfileName();
+ }
+
+ public boolean canTake(Object incomingCall) {
+ synchronized (SipPhone.class) {
+ if (!(incomingCall instanceof SipAudioCall)) return false;
+ if (ringingCall.getState().isAlive()) return false;
+
+ // FIXME: is it true that we cannot take any incoming call if
+ // both foreground and background are active
+ if (foregroundCall.getState().isAlive()
+ && backgroundCall.getState().isAlive()) {
+ return false;
+ }
+
+ SipAudioCall sipAudioCall = (SipAudioCall) incomingCall;
+ Log.v(LOG_TAG, " ++++++ taking call from: "
+ + sipAudioCall.getPeerProfile().getUriString());
+ String localUri = sipAudioCall.getLocalProfile().getUriString();
+ if (localUri.equals(mProfile.getUriString())) {
+ boolean makeCallWait = foregroundCall.getState().isAlive();
+ ringingCall.initIncomingCall(sipAudioCall, makeCallWait);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public void acceptCall() throws CallStateException {
+ synchronized (SipPhone.class) {
+ // FIXME if SWITCH fails, should retry with ANSWER
+ // in case the active/holding call disappeared and this
+ // is no longer call waiting
+
+ if (ringingCall.getState() == Call.State.INCOMING) {
+ Log.v(LOG_TAG, "acceptCall");
+ // Always unmute when answering a new call
+ setMute(false);
+ // make ringingCall foreground
+ foregroundCall.switchWith(ringingCall);
+ foregroundCall.acceptCall();
+ } else if (ringingCall.getState() == Call.State.WAITING) {
+ setMute(false);
+ switchHoldingAndActive();
+ // make ringingCall foreground
+ foregroundCall.switchWith(ringingCall);
+ foregroundCall.acceptCall();
+ } else {
+ throw new CallStateException("phone not ringing");
+ }
+ }
+ }
+
+ public void rejectCall() throws CallStateException {
+ synchronized (SipPhone.class) {
+ if (ringingCall.getState().isRinging()) {
+ Log.v(LOG_TAG, "rejectCall");
+ ringingCall.rejectCall();
+ } else {
+ throw new CallStateException("phone not ringing");
+ }
+ }
+ }
+
+ public Connection dial(String dialString, UUSInfo uusinfo) throws CallStateException {
+ return dial(dialString);
+ }
+
+ public Connection dial(String dialString) throws CallStateException {
+ synchronized (SipPhone.class) {
+ return dialInternal(dialString);
+ }
+ }
+
+ private Connection dialInternal(String dialString)
+ throws CallStateException {
+ // TODO: parse SIP URL?
+ // Need to make sure dialString gets parsed properly
+ //String newDialString = PhoneNumberUtils.stripSeparators(dialString);
+ //return mCT.dial(newDialString);
+ clearDisconnected();
+
+ if (!canDial()) {
+ throw new CallStateException("cannot dial in current state");
+ }
+ if (foregroundCall.getState() == SipCall.State.ACTIVE) {
+ switchHoldingAndActive();
+ }
+ if (foregroundCall.getState() != SipCall.State.IDLE) {
+ //we should have failed in !canDial() above before we get here
+ throw new CallStateException("cannot dial in current state");
+ }
+
+ setMute(false);
+ //cm.dial(pendingMO.address, clirMode, obtainCompleteMessage());
+ try {
+ Connection c = foregroundCall.dial(dialString);
+ return c;
+ } catch (SipException e) {
+ Log.e(LOG_TAG, "dial()", e);
+ throw new CallStateException("dial error: " + e);
+ }
+ }
+
+ public void switchHoldingAndActive() throws CallStateException {
+ Log.v(LOG_TAG, " ~~~~~~ switch fg and bg");
+ synchronized (SipPhone.class) {
+ foregroundCall.switchWith(backgroundCall);
+ if (backgroundCall.getState().isAlive()) backgroundCall.hold();
+ if (foregroundCall.getState().isAlive()) foregroundCall.unhold();
+ }
+ }
+
+ public boolean canConference() {
+ return true;
+ }
+
+ public void conference() throws CallStateException {
+ // TODO
+ }
+
+ public boolean canTransfer() {
+ return false;
+ }
+
+ public void explicitCallTransfer() throws CallStateException {
+ //mCT.explicitCallTransfer();
+ }
+
+ public void clearDisconnected() {
+ ringingCall.clearDisconnected();
+ foregroundCall.clearDisconnected();
+ backgroundCall.clearDisconnected();
+
+ updatePhoneState();
+ notifyPreciseCallStateChanged();
+ }
+
+ public void sendDtmf(char c) {
+ if (!PhoneNumberUtils.is12Key(c)) {
+ Log.e(LOG_TAG,
+ "sendDtmf called with invalid character '" + c + "'");
+ } else if (foregroundCall.getState().isAlive()) {
+ foregroundCall.sendDtmf(c);
+ }
+ }
+
+ public void startDtmf(char c) {
+ if (!PhoneNumberUtils.is12Key(c)) {
+ Log.e(LOG_TAG,
+ "startDtmf called with invalid character '" + c + "'");
+ } else {
+ sendDtmf(c);
+ }
+ }
+
+ public void stopDtmf() {
+ // no op
+ }
+
+ public void sendBurstDtmf(String dtmfString) {
+ Log.e(LOG_TAG, "[SipPhone] sendBurstDtmf() is a CDMA method");
+ }
+
+ public void getOutgoingCallerIdDisplay(Message onComplete) {
+ // FIXME: what to reply?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
+ Message onComplete) {
+ // FIXME: what's this for SIP?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void getCallWaiting(Message onComplete) {
+ // FIXME: what to reply?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void setCallWaiting(boolean enable, Message onComplete) {
+ // FIXME: what to reply?
+ Log.e(LOG_TAG, "call waiting not supported");
+ }
+
+ public void setMute(boolean muted) {
+ foregroundCall.setMute(muted);
+ }
+
+ public boolean getMute() {
+ return foregroundCall.getMute();
+ }
+
+ public Call getForegroundCall() {
+ return foregroundCall;
+ }
+
+ public Call getBackgroundCall() {
+ return backgroundCall;
+ }
+
+ public Call getRingingCall() {
+ return ringingCall;
+ }
+
+ public ServiceState getServiceState() {
+ // FIXME: we may need to provide this when data connectivity is lost
+ // or when server is down
+ return super.getServiceState();
+ }
+
+ private String getUriString(SipProfile p) {
+ // SipProfile.getUriString() may contain "SIP:" and port
+ return p.getUserName() + "@" + getSipDomain(p);
+ }
+
+ private String getSipDomain(SipProfile p) {
+ String domain = p.getSipDomain();
+ // TODO: move this to SipProfile
+ if (domain.endsWith(":5060")) {
+ return domain.substring(0, domain.length() - 5);
+ } else {
+ return domain;
+ }
+ }
+
+ private class SipCall extends SipCallBase {
+ void switchWith(SipCall that) {
+ synchronized (SipPhone.class) {
+ SipCall tmp = new SipCall();
+ tmp.takeOver(this);
+ this.takeOver(that);
+ that.takeOver(tmp);
+ }
+ }
+
+ private void takeOver(SipCall that) {
+ connections = that.connections;
+ state = that.state;
+ for (Connection c : connections) {
+ ((SipConnection) c).changeOwner(this);
+ }
+ }
+
+ @Override
+ public Phone getPhone() {
+ return SipPhone.this;
+ }
+
+ @Override
+ public List<Connection> getConnections() {
+ synchronized (SipPhone.class) {
+ // FIXME should return Collections.unmodifiableList();
+ return connections;
+ }
+ }
+
+ private CallerInfo getCallerInfo(String number) {
+ CallerInfo info = CallerInfo.getCallerInfo(mContext, number);
+ if ((info == null) || (info.name == null)) return null;
+ Log.v(LOG_TAG, "++******++ got info from contact:");
+ Log.v(LOG_TAG, " name: " + info.name);
+ Log.v(LOG_TAG, " numb: " + info.phoneNumber);
+ Log.v(LOG_TAG, " pres: " + info.numberPresentation);
+ return info;
+ }
+
+ Connection dial(String calleeSipUri) throws SipException {
+ CallerInfo info = getCallerInfo(calleeSipUri);
+ if (!calleeSipUri.contains("@")) {
+ calleeSipUri += "@" + getSipDomain(mProfile);
+ if (info != null) info.phoneNumber = calleeSipUri;
+ }
+ try {
+ SipProfile callee =
+ new SipProfile.Builder(calleeSipUri).build();
+ SipConnection c = new SipConnection(this, callee, info);
+ connections.add(c);
+ c.dial();
+ setState(Call.State.DIALING);
+ return c;
+ } catch (ParseException e) {
+ // TODO: notify someone
+ throw new SipException("dial", e);
+ }
+ }
+
+ @Override
+ public void hangup() throws CallStateException {
+ Log.v(LOG_TAG, "hang up call: " + getState() + ": " + this
+ + " on phone " + getPhone());
+ CallStateException excp = null;
+ for (Connection c : connections) {
+ try {
+ c.hangup();
+ } catch (CallStateException e) {
+ excp = e;
+ }
+ }
+ if (excp != null) throw excp;
+ setState(State.DISCONNECTING);
+ }
+
+ void initIncomingCall(SipAudioCall sipAudioCall, boolean makeCallWait) {
+ SipProfile callee = sipAudioCall.getPeerProfile();
+ CallerInfo info = getCallerInfo(getUriString(callee));
+ if (info == null) info = getCallerInfo(callee.getUserName());
+ if (info == null) info = getCallerInfo(callee.getDisplayName());
+ SipConnection c = new SipConnection(this, callee, info);
+ connections.add(c);
+
+ Call.State newState = makeCallWait ? State.WAITING : State.INCOMING;
+ c.initIncomingCall(sipAudioCall, newState);
+
+ setState(newState);
+ notifyNewRingingConnectionP(c);
+ }
+
+ void rejectCall() throws CallStateException {
+ hangup();
+ }
+
+ void acceptCall() throws CallStateException {
+ if (this != foregroundCall) {
+ throw new CallStateException("acceptCall() in a non-fg call");
+ }
+ if (connections.size() != 1) {
+ throw new CallStateException("acceptCall() in a conf call");
+ }
+ ((SipConnection) connections.get(0)).acceptCall();
+ }
+
+ void hold() throws CallStateException {
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup == null) return;
+ audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+ setState(State.HOLDING);
+ for (Connection c : connections) ((SipConnection) c).hold();
+ }
+
+ void unhold() throws CallStateException {
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup == null) return;
+ audioGroup.setMode(AudioGroup.MODE_NORMAL);
+ setState(State.ACTIVE);
+ for (Connection c : connections) ((SipConnection) c).unhold();
+ }
+
+ void setMute(boolean muted) {
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup == null) return;
+ audioGroup.setMode(
+ muted ? AudioGroup.MODE_MUTED : AudioGroup.MODE_NORMAL);
+ }
+
+ boolean getMute() {
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup == null) return false;
+ return (audioGroup.getMode() == AudioGroup.MODE_MUTED);
+ }
+
+ void sendDtmf(char c) {
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup == null) return;
+ audioGroup.sendDtmf(convertDtmf(c));
+ }
+
+ private int convertDtmf(char c) {
+ int code = c - '0';
+ if ((code < 0) || (code > 9)) {
+ switch (c) {
+ case '*': return 10;
+ case '#': return 11;
+ case 'A': return 12;
+ case 'B': return 13;
+ case 'C': return 14;
+ case 'D': return 15;
+ default:
+ throw new IllegalArgumentException(
+ "invalid DTMF char: " + (int) c);
+ }
+ }
+ return code;
+ }
+
+ @Override
+ protected void setState(State newState) {
+ if (state != newState) {
+ Log.v(LOG_TAG, "++******++ call state changed: " + state
+ + " --> " + newState + ": " + this + ": on phone "
+ + getPhone() + " " + connections.size());
+
+ if (newState == Call.State.ALERTING) {
+ state = newState; // need in ALERTING to enable ringback
+ SipPhone.this.startRingbackTone();
+ } else if (state == Call.State.ALERTING) {
+ SipPhone.this.stopRingbackTone();
+ }
+ state = newState;
+ updatePhoneState();
+ notifyPreciseCallStateChanged();
+ }
+ }
+
+ void onConnectionStateChanged(SipConnection conn) {
+ // this can be called back when a conf call is formed
+ if (state != State.ACTIVE) {
+ setState(conn.getState());
+ }
+ }
+
+ void onConnectionEnded(SipConnection conn) {
+ // set state to DISCONNECTED only when all conns are disconnected
+ if (state != State.DISCONNECTED) {
+ boolean allConnectionsDisconnected = true;
+ for (Connection c : connections) {
+ if (c.getState() != State.DISCONNECTED) {
+ allConnectionsDisconnected = false;
+ break;
+ }
+ }
+ if (allConnectionsDisconnected) setState(State.DISCONNECTED);
+ }
+ notifyDisconnectP(conn);
+ }
+
+ private AudioGroup getAudioGroup() {
+ if (connections.isEmpty()) return null;
+ return ((SipConnection) connections.get(0)).getAudioGroup();
+ }
+ }
+
+ private class SipConnection extends SipConnectionBase {
+ private SipCall mOwner;
+ private SipAudioCall mSipAudioCall;
+ private Call.State mState = Call.State.IDLE;
+ private SipProfile mPeer;
+ private boolean mIncoming = false;
+
+ private SipAudioCallAdapter mAdapter = new SipAudioCallAdapter() {
+ @Override
+ protected void onCallEnded(DisconnectCause cause) {
+ if (getDisconnectCause() != DisconnectCause.LOCAL) {
+ setDisconnectCause(cause);
+ }
+ synchronized (SipPhone.class) {
+ setState(Call.State.DISCONNECTED);
+ mOwner.onConnectionEnded(SipConnection.this);
+ Log.v(LOG_TAG, "-------- connection ended: "
+ + mPeer.getUriString() + ": "
+ + mSipAudioCall.getState() + ", cause: "
+ + getDisconnectCause() + ", on phone "
+ + getPhone());
+ }
+ }
+
+ @Override
+ public void onChanged(SipAudioCall call) {
+ synchronized (SipPhone.class) {
+ Call.State newState = getCallStateFrom(call);
+ if (mState == newState) return;
+ if (newState == Call.State.INCOMING) {
+ setState(mOwner.getState()); // INCOMING or WAITING
+ } else {
+ setState(newState);
+ }
+ mOwner.onConnectionStateChanged(SipConnection.this);
+ Log.v(LOG_TAG, "++******++ connection state changed: "
+ + mPeer.getUriString() + ": " + mState
+ + " on phone " + getPhone());
+ }
+ }
+
+ @Override
+ protected void onError(String errorMessage) {
+ Log.w(LOG_TAG, "SIP error: " + errorMessage);
+ if (mSipAudioCall.isInCall()) {
+ // Don't end the call when in call.
+ // TODO: how to deliver the error to PhoneApp
+ return;
+ }
+
+ // FIXME: specify error
+ onCallEnded(DisconnectCause.ERROR_UNSPECIFIED);
+ }
+ };
+
+ public SipConnection(SipCall owner, SipProfile callee,
+ CallerInfo info) {
+ super(getUriString(callee));
+ mOwner = owner;
+ mPeer = callee;
+ if (info == null) info = createCallerInfo();
+ setUserData(info);
+ }
+
+ private CallerInfo createCallerInfo() {
+ SipProfile p = mPeer;
+ String name = p.getDisplayName();
+ if (TextUtils.isEmpty(name)) name = p.getUserName();
+ CallerInfo info = new CallerInfo();
+ info.name = name;
+ info.phoneNumber = getUriString(p);
+ return info;
+ }
+
+ void initIncomingCall(SipAudioCall sipAudioCall, Call.State newState) {
+ setState(newState);
+ mSipAudioCall = sipAudioCall;
+ sipAudioCall.setListener(mAdapter); // call back to set state
+ mIncoming = true;
+ }
+
+ void acceptCall() throws CallStateException {
+ try {
+ mSipAudioCall.answerCall();
+ } catch (SipException e) {
+ throw new CallStateException("acceptCall(): " + e);
+ }
+ }
+
+ void changeOwner(SipCall owner) {
+ mOwner = owner;
+ }
+
+ AudioGroup getAudioGroup() {
+ if (mSipAudioCall == null) return null;
+ return mSipAudioCall.getAudioGroup();
+ }
+
+ void dial() throws SipException {
+ setState(Call.State.DIALING);
+ mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile,
+ mPeer, null);
+ mSipAudioCall.setRingbackToneEnabled(false);
+ mSipAudioCall.setListener(mAdapter);
+ }
+
+ void hold() throws CallStateException {
+ try {
+ mSipAudioCall.holdCall();
+ } catch (SipException e) {
+ throw new CallStateException("hold(): " + e);
+ }
+ }
+
+ void unhold() throws CallStateException {
+ try {
+ mSipAudioCall.continueCall();
+ } catch (SipException e) {
+ throw new CallStateException("unhold(): " + e);
+ }
+ }
+
+ @Override
+ protected void setState(Call.State state) {
+ if (state == mState) return;
+ super.setState(state);
+ mState = state;
+ }
+
+ @Override
+ public Call.State getState() {
+ return mState;
+ }
+
+ @Override
+ public boolean isIncoming() {
+ return mIncoming;
+ }
+
+ @Override
+ public String getAddress() {
+ return getUriString(mPeer);
+ }
+
+ @Override
+ public SipCall getCall() {
+ return mOwner;
+ }
+
+ @Override
+ protected Phone getPhone() {
+ return mOwner.getPhone();
+ }
+
+ @Override
+ public void hangup() throws CallStateException {
+ Log.v(LOG_TAG, "hangup conn: " + mPeer.getUriString() + ": "
+ + ": on phone " + getPhone());
+ try {
+ mSipAudioCall.endCall();
+ setState(Call.State.DISCONNECTING);
+ setDisconnectCause(DisconnectCause.LOCAL);
+ } catch (SipException e) {
+ throw new CallStateException("hangup(): " + e);
+ }
+ }
+
+ @Override
+ public void separate() throws CallStateException {
+ // TODO: what's this for SIP?
+ /*
+ if (!disconnected) {
+ owner.separate(this);
+ } else {
+ throw new CallStateException ("disconnected");
+ }
+ */
+ }
+
+ @Override
+ public UUSInfo getUUSInfo() {
+ return null;
+ }
+ }
+
+ private static Call.State getCallStateFrom(SipAudioCall sipAudioCall) {
+ if (sipAudioCall.isOnHold()) return Call.State.HOLDING;
+ SipSessionState sessionState = sipAudioCall.getState();
+ switch (sessionState) {
+ case READY_TO_CALL: return Call.State.IDLE;
+ case INCOMING_CALL:
+ case INCOMING_CALL_ANSWERING: return Call.State.INCOMING;
+ case OUTGOING_CALL: return Call.State.DIALING;
+ case OUTGOING_CALL_RING_BACK: return Call.State.ALERTING;
+ case OUTGOING_CALL_CANCELING: return Call.State.DISCONNECTING;
+ case IN_CALL: return Call.State.ACTIVE;
+ default:
+ Log.w(LOG_TAG, "illegal connection state: " + sessionState);
+ return Call.State.DISCONNECTED;
+ }
+ }
+
+ private abstract class SipAudioCallAdapter extends SipAudioCall.Adapter {
+ protected abstract void onCallEnded(Connection.DisconnectCause cause);
+ protected abstract void onError(String errorMessage);
+
+ @Override
+ public void onCallEnded(SipAudioCall call) {
+ onCallEnded(Connection.DisconnectCause.NORMAL);
+ }
+
+ @Override
+ public void onCallBusy(SipAudioCall call) {
+ onCallEnded(Connection.DisconnectCause.BUSY);
+ }
+
+ @Override
+ public void onError(SipAudioCall call, String errorMessage) {
+ onError(errorMessage);
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
new file mode 100755
index 0000000..36d65db
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -0,0 +1,558 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
+import android.preference.PreferenceManager;
+import android.provider.Telephony;
+import android.telephony.CellLocation;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.text.TextUtils;
+import android.util.Log;
+
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.PhoneSubInfo;
+import com.android.internal.telephony.TelephonyProperties;
+//import com.android.internal.telephony.UUSInfo;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+abstract class SipPhoneBase extends PhoneBase {
+ // NOTE that LOG_TAG here is "Sip", which means that log messages
+ // from this file will go into the radio log rather than the main
+ // log. (Use "adb logcat -b radio" to see them.)
+ static final String LOG_TAG = "SipPhone";
+ private static final boolean LOCAL_DEBUG = true;
+
+ //SipCallTracker mCT;
+ PhoneSubInfo mSubInfo;
+
+ Registrant mPostDialHandler;
+
+ final RegistrantList mRingbackRegistrants = new RegistrantList();
+
+ private State state = State.IDLE;
+
+ public SipPhoneBase(Context context, PhoneNotifier notifier) {
+ super(notifier, context, new SipCommandInterface(context), false);
+
+ // FIXME: what's this for SIP?
+ //Change the system property
+ //SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
+ // new Integer(Phone.PHONE_TYPE_GSM).toString());
+ }
+
+ public abstract Call getForegroundCall();
+
+ public abstract Call getBackgroundCall();
+
+ public abstract Call getRingingCall();
+
+ /*
+ public Connection dial(String dialString, UUSInfo uusInfo)
+ throws CallStateException {
+ // ignore UUSInfo
+ return dial(dialString);
+ }
+ */
+
+ void migrateFrom(SipPhoneBase from) {
+ migrate(mRingbackRegistrants, from.mRingbackRegistrants);
+ migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
+ migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
+ migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
+ migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
+ migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
+ migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
+ migrate(mMmiRegistrants, from.mMmiRegistrants);
+ migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
+ migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
+ }
+
+ static void migrate(RegistrantList to, RegistrantList from) {
+ from.removeCleared();
+ for (int i = 0, n = from.size(); i < n; i++) {
+ to.add((Registrant) from.get(i));
+ }
+ }
+
+ @Override
+ public void registerForRingbackTone(Handler h, int what, Object obj) {
+ mRingbackRegistrants.addUnique(h, what, obj);
+ }
+
+ @Override
+ public void unregisterForRingbackTone(Handler h) {
+ mRingbackRegistrants.remove(h);
+ }
+
+ protected void startRingbackTone() {
+ AsyncResult result = new AsyncResult(null, new Boolean(true), null);
+ mRingbackRegistrants.notifyRegistrants(result);
+ }
+
+ protected void stopRingbackTone() {
+ AsyncResult result = new AsyncResult(null, new Boolean(false), null);
+ mRingbackRegistrants.notifyRegistrants(result);
+ }
+
+ public void dispose() {
+ mIsTheCurrentActivePhone = false;
+ mSubInfo.dispose();
+ }
+
+ public void removeReferences() {
+ mSubInfo = null;
+ }
+
+ public ServiceState getServiceState() {
+ // FIXME: we may need to provide this when data connectivity is lost
+ // or when server is down
+ ServiceState s = new ServiceState();
+ s.setState(ServiceState.STATE_IN_SERVICE);
+ return s;
+ }
+
+ public CellLocation getCellLocation() {
+ return null; //mSST.cellLoc;
+ }
+
+ public State getState() {
+ return state;
+ }
+
+ public String getPhoneName() {
+ return "SIP";
+ }
+
+ public int getPhoneType() {
+ // FIXME: add SIP phone type
+ return Phone.PHONE_TYPE_GSM;
+ }
+
+ public SignalStrength getSignalStrength() {
+ return new SignalStrength();
+ }
+
+ public boolean getMessageWaitingIndicator() {
+ return false;
+ }
+
+ public boolean getCallForwardingIndicator() {
+ return false;
+ }
+
+ public List<? extends MmiCode> getPendingMmiCodes() {
+ return new ArrayList<MmiCode>(0);
+ }
+
+ public DataState getDataConnectionState() {
+ return DataState.DISCONNECTED;
+ }
+
+ public DataState getDataConnectionState(String apnType) {
+ return DataState.DISCONNECTED;
+ }
+
+ public DataActivityState getDataActivityState() {
+ return DataActivityState.NONE;
+ }
+
+ /**
+ * Notify any interested party of a Phone state change {@link Phone.State}
+ */
+ void notifyPhoneStateChanged() {
+ mNotifier.notifyPhoneState(this);
+ }
+
+ /**
+ * Notify registrants of a change in the call state. This notifies changes in {@link Call.State}
+ * Use this when changes in the precise call state are needed, else use notifyPhoneStateChanged.
+ */
+ void notifyPreciseCallStateChanged() {
+ /* we'd love it if this was package-scoped*/
+ super.notifyPreciseCallStateChangedP();
+ }
+
+ void notifyNewRingingConnection(Connection c) {
+ /* we'd love it if this was package-scoped*/
+ super.notifyNewRingingConnectionP(c);
+ }
+
+ void notifyDisconnect(Connection cn) {
+ mDisconnectRegistrants.notifyResult(cn);
+ }
+
+ void notifyUnknownConnection() {
+ mUnknownConnectionRegistrants.notifyResult(this);
+ }
+
+ void notifySuppServiceFailed(SuppService code) {
+ mSuppServiceFailedRegistrants.notifyResult(code);
+ }
+
+ void notifyServiceStateChanged(ServiceState ss) {
+ super.notifyServiceStateChangedP(ss);
+ }
+
+ public void notifyCallForwardingIndicator() {
+ mNotifier.notifyCallForwardingChanged(this);
+ }
+
+ public boolean canDial() {
+ int serviceState = getServiceState().getState();
+ Log.v(LOG_TAG, "canDial(): serviceState = " + serviceState);
+ if (serviceState == ServiceState.STATE_POWER_OFF) return false;
+
+ String disableCall = SystemProperties.get(
+ TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
+ Log.v(LOG_TAG, "canDial(): disableCall = " + disableCall);
+ if (disableCall.equals("true")) return false;
+
+ Log.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState());
+ Log.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState());
+ Log.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState());
+ return !getRingingCall().isRinging()
+ && (!getForegroundCall().getState().isAlive()
+ || !getBackgroundCall().getState().isAlive());
+ }
+
+ public boolean handleInCallMmiCommands(String dialString)
+ throws CallStateException {
+ return false;
+ }
+
+ boolean isInCall() {
+ Call.State foregroundCallState = getForegroundCall().getState();
+ Call.State backgroundCallState = getBackgroundCall().getState();
+ Call.State ringingCallState = getRingingCall().getState();
+
+ return (foregroundCallState.isAlive() || backgroundCallState.isAlive()
+ || ringingCallState.isAlive());
+ }
+
+ public boolean handlePinMmi(String dialString) {
+ return false;
+ }
+
+ public void sendUssdResponse(String ussdMessge) {
+ }
+
+ public void registerForSuppServiceNotification(
+ Handler h, int what, Object obj) {
+ }
+
+ public void unregisterForSuppServiceNotification(Handler h) {
+ }
+
+ public void setRadioPower(boolean power) {
+ }
+
+ public String getVoiceMailNumber() {
+ return null;
+ }
+
+ public String getVoiceMailAlphaTag() {
+ return null;
+ }
+
+ public String getDeviceId() {
+ return null;
+ }
+
+ public String getDeviceSvn() {
+ return null;
+ }
+
+ public String getEsn() {
+ Log.e(LOG_TAG, "[SipPhone] getEsn() is a CDMA method");
+ return "0";
+ }
+
+ public String getMeid() {
+ Log.e(LOG_TAG, "[SipPhone] getMeid() is a CDMA method");
+ return "0";
+ }
+
+ public String getSubscriberId() {
+ return null;
+ }
+
+ public String getIccSerialNumber() {
+ return null;
+ }
+
+ public String getLine1Number() {
+ return null;
+ }
+
+ public String getLine1AlphaTag() {
+ return null;
+ }
+
+ public void setLine1Number(String alphaTag, String number, Message onComplete) {
+ // FIXME: what to reply for SIP?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void setVoiceMailNumber(String alphaTag, String voiceMailNumber,
+ Message onComplete) {
+ // FIXME: what to reply for SIP?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ private boolean isValidCommandInterfaceCFReason(int commandInterfaceCFReason) {
+ switch (commandInterfaceCFReason) {
+ case CF_REASON_UNCONDITIONAL:
+ case CF_REASON_BUSY:
+ case CF_REASON_NO_REPLY:
+ case CF_REASON_NOT_REACHABLE:
+ case CF_REASON_ALL:
+ case CF_REASON_ALL_CONDITIONAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
+ switch (commandInterfaceCFAction) {
+ case CF_ACTION_DISABLE:
+ case CF_ACTION_ENABLE:
+ case CF_ACTION_REGISTRATION:
+ case CF_ACTION_ERASURE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected boolean isCfEnable(int action) {
+ return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
+ }
+
+ public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
+ if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
+ // FIXME: what to reply?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+ }
+
+ public void setCallForwardingOption(int commandInterfaceCFAction,
+ int commandInterfaceCFReason, String dialingNumber,
+ int timerSeconds, Message onComplete) {
+ if (isValidCommandInterfaceCFAction(commandInterfaceCFAction)
+ && isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
+ // FIXME: what to reply?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+ }
+
+ public void getOutgoingCallerIdDisplay(Message onComplete) {
+ // FIXME: what to reply?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
+ Message onComplete) {
+ // FIXME: what's this for SIP?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void getCallWaiting(Message onComplete) {
+ // FIXME: what to reply?
+ AsyncResult.forMessage(onComplete, null, null);
+ onComplete.sendToTarget();
+ }
+
+ public void setCallWaiting(boolean enable, Message onComplete) {
+ // FIXME: what to reply?
+ Log.e(LOG_TAG, "call waiting not supported");
+ }
+
+ public boolean getIccRecordsLoaded() {
+ return false;
+ }
+
+ public IccCard getIccCard() {
+ return null;
+ }
+
+ public void getAvailableNetworks(Message response) {
+ // FIXME: what to reply?
+ }
+
+ public void setNetworkSelectionModeAutomatic(Message response) {
+ // FIXME: what to reply?
+ }
+
+ public void selectNetworkManually(
+ com.android.internal.telephony.gsm.NetworkInfo network,
+ Message response) {
+ // FIXME: what to reply?
+ }
+
+ public void getNeighboringCids(Message response) {
+ // FIXME: what to reply?
+ }
+
+ public void setOnPostDialCharacter(Handler h, int what, Object obj) {
+ mPostDialHandler = new Registrant(h, what, obj);
+ }
+
+ public void getDataCallList(Message response) {
+ // FIXME: what to reply?
+ }
+
+ public List<DataConnection> getCurrentDataConnectionList () {
+ return null;
+ }
+
+ public void updateServiceLocation() {
+ }
+
+ public void enableLocationUpdates() {
+ }
+
+ public void disableLocationUpdates() {
+ }
+
+ public boolean getDataRoamingEnabled() {
+ return false;
+ }
+
+ public void setDataRoamingEnabled(boolean enable) {
+ }
+
+ public boolean enableDataConnectivity() {
+ return false;
+ }
+
+ public boolean disableDataConnectivity() {
+ return false;
+ }
+
+ public boolean isDataConnectivityPossible() {
+ return false;
+ }
+
+ boolean updateCurrentCarrierInProvider() {
+ return false;
+ }
+
+ public void saveClirSetting(int commandInterfaceCLIRMode) {
+ // FIXME: what's this for SIP?
+ }
+
+ /**
+ * Retrieves the PhoneSubInfo of the SipPhone
+ */
+ public PhoneSubInfo getPhoneSubInfo(){
+ return mSubInfo;
+ }
+
+ /** {@inheritDoc} */
+ public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ public IccFileHandler getIccFileHandler(){
+ return null;
+ }
+
+ public void activateCellBroadcastSms(int activate, Message response) {
+ Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
+ }
+
+ public void getCellBroadcastSmsConfig(Message response) {
+ Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
+ }
+
+ public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
+ Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
+ }
+
+ void updatePhoneState() {
+ State oldState = state;
+
+ if (getRingingCall().isRinging()) {
+ state = State.RINGING;
+ } else if (getForegroundCall().isIdle()
+ && getBackgroundCall().isIdle()) {
+ state = State.IDLE;
+ } else {
+ state = State.OFFHOOK;
+ }
+ Log.e(LOG_TAG, " ^^^^^^ new phone state: " + state);
+
+ if (state != oldState) {
+ notifyPhoneStateChanged();
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneFactory.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneFactory.java
new file mode 100644
index 0000000..c9e9762
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneNotifier;
+
+import android.content.Context;
+import android.net.sip.SipProfile;
+import android.util.Log;
+
+import java.text.ParseException;
+
+/**
+ * @hide
+ */
+public class SipPhoneFactory {
+ private static PhoneNotifier sPhoneNotifier = makeDefaultPhoneNotifier();
+ private static Context sContext;
+
+ public static void makeDefaultPhones(Context context) {
+ makeDefaultPhone(context);
+ }
+
+ public static void makeDefaultPhone(Context context) {
+ sContext = context;
+ SipPhoneProxy.getInstance().setPhone(
+ makePhone("sip:anonymous@localhost"));
+ }
+
+ public static Phone getDefaultPhone() {
+ return SipPhoneProxy.getInstance();
+ }
+
+ public static SipPhone makePhone(String sipProfileUri) {
+ try {
+ SipProfile profile = new SipProfile.Builder(sipProfileUri).build();
+ return new SipPhone(sContext, sPhoneNotifier, profile);
+ } catch (ParseException e) {
+ Log.v("SipPhoneProxy", "setPhone", e);
+ return null;
+ }
+ }
+
+ private static PhoneNotifier makeDefaultPhoneNotifier() {
+ try {
+ return new com.android.internal.telephony.SipPhoneNotifier();
+ } catch (Error e) {
+ Log.e("SipPhoneProxy", "makeDefaultPhoneNotifier", e);
+ throw e;
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneProxy.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneProxy.java
new file mode 100644
index 0000000..7cc1a9b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneProxy.java
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2010 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.internal.telephony.sip;
+
+import com.android.internal.telephony.*;
+import com.android.internal.telephony.gsm.NetworkInfo;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.telephony.CellLocation;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * Temporary. Will be removed after integrating with CallManager.
+ * (TODO)
+ * @hide
+ */
+public class SipPhoneProxy implements Phone {
+ private static final String LOG_TAG = "PHONE";
+
+ private static SipPhoneProxy sPhoneProxy = new SipPhoneProxy();
+
+ public static SipPhoneProxy getInstance() {
+ return sPhoneProxy;
+ }
+
+ private SipPhone mActivePhone;
+ private CallProxy mRingingCall = new CallProxy();
+ private CallProxy mForegroundCall = new CallProxy();
+ private CallProxy mBackgroundCall = new CallProxy();
+
+ private SipPhoneProxy() {
+ }
+
+ public void onNewCall(Object call) {
+ if (mActivePhone.canTake(call)) {
+ Log.v("SipPhoneProxy", "onNewCall(): call taken: " + call);
+ } else {
+ Log.v("SipPhoneProxy", "onNewCall(): call dropped: " + call);
+ }
+ }
+
+ public synchronized void setPhone(SipPhone phone) {
+ if (phone == null) return;
+ if (mActivePhone != null) phone.migrateFrom(mActivePhone);
+ mActivePhone = phone;
+ mForegroundCall.setTarget(phone.getForegroundCall());
+ mBackgroundCall.setTarget(phone.getBackgroundCall());
+ mRingingCall.setTarget(phone.getRingingCall());
+ }
+
+ public synchronized Call getForegroundCall() {
+ return mForegroundCall;
+ }
+
+ public synchronized Call getBackgroundCall() {
+ return mBackgroundCall;
+ }
+
+ public synchronized Call getRingingCall() {
+ return mRingingCall;
+ }
+
+
+ public ServiceState getServiceState() {
+ return mActivePhone.getServiceState();
+ }
+
+ public CellLocation getCellLocation() {
+ return mActivePhone.getCellLocation();
+ }
+
+ public DataState getDataConnectionState() {
+ return mActivePhone.getDataConnectionState();
+ }
+
+ public DataActivityState getDataActivityState() {
+ return mActivePhone.getDataActivityState();
+ }
+
+ public Context getContext() {
+ return mActivePhone.getContext();
+ }
+
+ public void disableDnsCheck(boolean b) {
+ mActivePhone.disableDnsCheck(b);
+ }
+
+ public boolean isDnsCheckDisabled() {
+ return mActivePhone.isDnsCheckDisabled();
+ }
+
+ public State getState() {
+ return mActivePhone.getState();
+ }
+
+ public String getPhoneName() {
+ return mActivePhone.getPhoneName();
+ }
+
+ public int getPhoneType() {
+ return mActivePhone.getPhoneType();
+ }
+
+ public String[] getActiveApnTypes() {
+ return mActivePhone.getActiveApnTypes();
+ }
+
+ public String getActiveApn() {
+ return mActivePhone.getActiveApn();
+ }
+
+ public SignalStrength getSignalStrength() {
+ return mActivePhone.getSignalStrength();
+ }
+
+ public void registerForUnknownConnection(Handler h, int what, Object obj) {
+ mActivePhone.registerForUnknownConnection(h, what, obj);
+ }
+
+ public void unregisterForUnknownConnection(Handler h) {
+ mActivePhone.unregisterForUnknownConnection(h);
+ }
+
+ public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
+ mActivePhone.registerForPreciseCallStateChanged(h, what, obj);
+ }
+
+ public void unregisterForPreciseCallStateChanged(Handler h) {
+ mActivePhone.unregisterForPreciseCallStateChanged(h);
+ }
+
+ public void registerForNewRingingConnection(Handler h, int what, Object obj) {
+ mActivePhone.registerForNewRingingConnection(h, what, obj);
+ }
+
+ public void unregisterForNewRingingConnection(Handler h) {
+ mActivePhone.unregisterForNewRingingConnection(h);
+ }
+
+ public void registerForIncomingRing(Handler h, int what, Object obj) {
+ mActivePhone.registerForIncomingRing(h, what, obj);
+ }
+
+ public void unregisterForIncomingRing(Handler h) {
+ mActivePhone.unregisterForIncomingRing(h);
+ }
+
+ public void registerForDisconnect(Handler h, int what, Object obj) {
+ mActivePhone.registerForDisconnect(h, what, obj);
+ }
+
+ public void unregisterForDisconnect(Handler h) {
+ mActivePhone.unregisterForDisconnect(h);
+ }
+
+ public void registerForMmiInitiate(Handler h, int what, Object obj) {
+ mActivePhone.registerForMmiInitiate(h, what, obj);
+ }
+
+ public void unregisterForMmiInitiate(Handler h) {
+ mActivePhone.unregisterForMmiInitiate(h);
+ }
+
+ public void registerForMmiComplete(Handler h, int what, Object obj) {
+ mActivePhone.registerForMmiComplete(h, what, obj);
+ }
+
+ public void unregisterForMmiComplete(Handler h) {
+ mActivePhone.unregisterForMmiComplete(h);
+ }
+
+ public List<? extends MmiCode> getPendingMmiCodes() {
+ return mActivePhone.getPendingMmiCodes();
+ }
+
+ public void sendUssdResponse(String ussdMessge) {
+ mActivePhone.sendUssdResponse(ussdMessge);
+ }
+
+ public void registerForServiceStateChanged(Handler h, int what, Object obj) {
+ mActivePhone.registerForServiceStateChanged(h, what, obj);
+ }
+
+ public void unregisterForServiceStateChanged(Handler h) {
+ mActivePhone.unregisterForServiceStateChanged(h);
+ }
+
+ public void registerForSuppServiceNotification(Handler h, int what, Object obj) {
+ mActivePhone.registerForSuppServiceNotification(h, what, obj);
+ }
+
+ public void unregisterForSuppServiceNotification(Handler h) {
+ mActivePhone.unregisterForSuppServiceNotification(h);
+ }
+
+ public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
+ mActivePhone.registerForSuppServiceFailed(h, what, obj);
+ }
+
+ public void unregisterForSuppServiceFailed(Handler h) {
+ mActivePhone.unregisterForSuppServiceFailed(h);
+ }
+
+ public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
+ mActivePhone.registerForInCallVoicePrivacyOn(h,what,obj);
+ }
+
+ public void unregisterForInCallVoicePrivacyOn(Handler h){
+ mActivePhone.unregisterForInCallVoicePrivacyOn(h);
+ }
+
+ public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
+ mActivePhone.registerForInCallVoicePrivacyOff(h,what,obj);
+ }
+
+ public void unregisterForInCallVoicePrivacyOff(Handler h){
+ mActivePhone.unregisterForInCallVoicePrivacyOff(h);
+ }
+
+ public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
+ mActivePhone.registerForCdmaOtaStatusChange(h,what,obj);
+ }
+
+ public void unregisterForCdmaOtaStatusChange(Handler h) {
+ mActivePhone.unregisterForCdmaOtaStatusChange(h);
+ }
+
+ public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
+ mActivePhone.registerForSubscriptionInfoReady(h, what, obj);
+ }
+
+ public void unregisterForSubscriptionInfoReady(Handler h) {
+ mActivePhone.unregisterForSubscriptionInfoReady(h);
+ }
+
+ public void registerForEcmTimerReset(Handler h, int what, Object obj) {
+ mActivePhone.registerForEcmTimerReset(h,what,obj);
+ }
+
+ public void unregisterForEcmTimerReset(Handler h) {
+ mActivePhone.unregisterForEcmTimerReset(h);
+ }
+
+ public void registerForRingbackTone(Handler h, int what, Object obj) {
+ mActivePhone.registerForRingbackTone(h,what,obj);
+ }
+
+ public void unregisterForRingbackTone(Handler h) {
+ mActivePhone.unregisterForRingbackTone(h);
+ }
+
+ public void registerForResendIncallMute(Handler h, int what, Object obj) {
+ mActivePhone.registerForResendIncallMute(h,what,obj);
+ }
+
+ public void unregisterForResendIncallMute(Handler h) {
+ mActivePhone.unregisterForResendIncallMute(h);
+ }
+
+ public boolean getIccRecordsLoaded() {
+ return mActivePhone.getIccRecordsLoaded();
+ }
+
+ public IccCard getIccCard() {
+ return mActivePhone.getIccCard();
+ }
+
+ public void acceptCall() throws CallStateException {
+ mActivePhone.acceptCall();
+ }
+
+ public void rejectCall() throws CallStateException {
+ mActivePhone.rejectCall();
+ }
+
+ public void switchHoldingAndActive() throws CallStateException {
+ mActivePhone.switchHoldingAndActive();
+ }
+
+ public boolean canConference() {
+ return mActivePhone.canConference();
+ }
+
+ public void conference() throws CallStateException {
+ mActivePhone.conference();
+ }
+
+ public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+ mActivePhone.enableEnhancedVoicePrivacy(enable, onComplete);
+ }
+
+ public void getEnhancedVoicePrivacy(Message onComplete) {
+ mActivePhone.getEnhancedVoicePrivacy(onComplete);
+ }
+
+ public boolean canTransfer() {
+ return mActivePhone.canTransfer();
+ }
+
+ public void explicitCallTransfer() throws CallStateException {
+ mActivePhone.explicitCallTransfer();
+ }
+
+ public void clearDisconnected() {
+ mActivePhone.clearDisconnected();
+ }
+
+ public Connection dial(String dialString) throws CallStateException {
+ return mActivePhone.dial(dialString);
+ }
+
+ public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException {
+ return mActivePhone.dial(dialString);
+ }
+
+ public boolean handlePinMmi(String dialString) {
+ return mActivePhone.handlePinMmi(dialString);
+ }
+
+ public boolean handleInCallMmiCommands(String command) throws CallStateException {
+ return mActivePhone.handleInCallMmiCommands(command);
+ }
+
+ public void sendDtmf(char c) {
+ mActivePhone.sendDtmf(c);
+ }
+
+ public void startDtmf(char c) {
+ mActivePhone.startDtmf(c);
+ }
+
+ public void stopDtmf() {
+ mActivePhone.stopDtmf();
+ }
+
+ public void setRadioPower(boolean power) {
+ mActivePhone.setRadioPower(power);
+ }
+
+ public boolean getMessageWaitingIndicator() {
+ return mActivePhone.getMessageWaitingIndicator();
+ }
+
+ public boolean getCallForwardingIndicator() {
+ return mActivePhone.getCallForwardingIndicator();
+ }
+
+ public String getLine1Number() {
+ return mActivePhone.getLine1Number();
+ }
+
+ public String getCdmaMin() {
+ return mActivePhone.getCdmaMin();
+ }
+
+ public boolean isMinInfoReady() {
+ return mActivePhone.isMinInfoReady();
+ }
+
+ public String getCdmaPrlVersion() {
+ return mActivePhone.getCdmaPrlVersion();
+ }
+
+ public String getLine1AlphaTag() {
+ return mActivePhone.getLine1AlphaTag();
+ }
+
+ public void setLine1Number(String alphaTag, String number, Message onComplete) {
+ mActivePhone.setLine1Number(alphaTag, number, onComplete);
+ }
+
+ public String getVoiceMailNumber() {
+ return mActivePhone.getVoiceMailNumber();
+ }
+
+ /** @hide */
+ public int getVoiceMessageCount(){
+ return mActivePhone.getVoiceMessageCount();
+ }
+
+ public String getVoiceMailAlphaTag() {
+ return mActivePhone.getVoiceMailAlphaTag();
+ }
+
+ public void setVoiceMailNumber(String alphaTag,String voiceMailNumber,
+ Message onComplete) {
+ mActivePhone.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
+ }
+
+ public void getCallForwardingOption(int commandInterfaceCFReason,
+ Message onComplete) {
+ mActivePhone.getCallForwardingOption(commandInterfaceCFReason,
+ onComplete);
+ }
+
+ public void setCallForwardingOption(int commandInterfaceCFReason,
+ int commandInterfaceCFAction, String dialingNumber,
+ int timerSeconds, Message onComplete) {
+ mActivePhone.setCallForwardingOption(commandInterfaceCFReason,
+ commandInterfaceCFAction, dialingNumber, timerSeconds, onComplete);
+ }
+
+ public void getOutgoingCallerIdDisplay(Message onComplete) {
+ mActivePhone.getOutgoingCallerIdDisplay(onComplete);
+ }
+
+ public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
+ Message onComplete) {
+ mActivePhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode,
+ onComplete);
+ }
+
+ public void getCallWaiting(Message onComplete) {
+ mActivePhone.getCallWaiting(onComplete);
+ }
+
+ public void setCallWaiting(boolean enable, Message onComplete) {
+ mActivePhone.setCallWaiting(enable, onComplete);
+ }
+
+ public void getAvailableNetworks(Message response) {
+ mActivePhone.getAvailableNetworks(response);
+ }
+
+ public void setNetworkSelectionModeAutomatic(Message response) {
+ mActivePhone.setNetworkSelectionModeAutomatic(response);
+ }
+
+ public void selectNetworkManually(NetworkInfo network, Message response) {
+ mActivePhone.selectNetworkManually(network, response);
+ }
+
+ public void setPreferredNetworkType(int networkType, Message response) {
+ mActivePhone.setPreferredNetworkType(networkType, response);
+ }
+
+ public void getPreferredNetworkType(Message response) {
+ mActivePhone.getPreferredNetworkType(response);
+ }
+
+ public void getNeighboringCids(Message response) {
+ mActivePhone.getNeighboringCids(response);
+ }
+
+ public void setOnPostDialCharacter(Handler h, int what, Object obj) {
+ mActivePhone.setOnPostDialCharacter(h, what, obj);
+ }
+
+ public void setMute(boolean muted) {
+ mActivePhone.setMute(muted);
+ }
+
+ public boolean getMute() {
+ return mActivePhone.getMute();
+ }
+
+ public void invokeOemRilRequestRaw(byte[] data, Message response) {
+ mActivePhone.invokeOemRilRequestRaw(data, response);
+ }
+
+ public void invokeOemRilRequestStrings(String[] strings, Message response) {
+ mActivePhone.invokeOemRilRequestStrings(strings, response);
+ }
+
+ public void getDataCallList(Message response) {
+ mActivePhone.getDataCallList(response);
+ }
+
+ public List<DataConnection> getCurrentDataConnectionList() {
+ return mActivePhone.getCurrentDataConnectionList();
+ }
+
+ public void updateServiceLocation() {
+ mActivePhone.updateServiceLocation();
+ }
+
+ public void enableLocationUpdates() {
+ mActivePhone.enableLocationUpdates();
+ }
+
+ public void disableLocationUpdates() {
+ mActivePhone.disableLocationUpdates();
+ }
+
+ public void setUnitTestMode(boolean f) {
+ mActivePhone.setUnitTestMode(f);
+ }
+
+ public boolean getUnitTestMode() {
+ return mActivePhone.getUnitTestMode();
+ }
+
+ public void setBandMode(int bandMode, Message response) {
+ mActivePhone.setBandMode(bandMode, response);
+ }
+
+ public void queryAvailableBandMode(Message response) {
+ mActivePhone.queryAvailableBandMode(response);
+ }
+
+ public boolean getDataRoamingEnabled() {
+ return mActivePhone.getDataRoamingEnabled();
+ }
+
+ public void setDataRoamingEnabled(boolean enable) {
+ mActivePhone.setDataRoamingEnabled(enable);
+ }
+
+ public void queryCdmaRoamingPreference(Message response) {
+ mActivePhone.queryCdmaRoamingPreference(response);
+ }
+
+ public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+ mActivePhone.setCdmaRoamingPreference(cdmaRoamingType, response);
+ }
+
+ public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+ mActivePhone.setCdmaSubscription(cdmaSubscriptionType, response);
+ }
+
+ public SimulatedRadioControl getSimulatedRadioControl() {
+ return mActivePhone.getSimulatedRadioControl();
+ }
+
+ public boolean enableDataConnectivity() {
+ return mActivePhone.enableDataConnectivity();
+ }
+
+ public boolean disableDataConnectivity() {
+ return mActivePhone.disableDataConnectivity();
+ }
+
+ public int enableApnType(String type) {
+ return mActivePhone.enableApnType(type);
+ }
+
+ public int disableApnType(String type) {
+ return mActivePhone.disableApnType(type);
+ }
+
+ public boolean isDataConnectivityEnabled() {
+ return mActivePhone.isDataConnectivityEnabled();
+ }
+
+ public boolean isDataConnectivityPossible() {
+ return mActivePhone.isDataConnectivityPossible();
+ }
+
+ public String getInterfaceName(String apnType) {
+ return mActivePhone.getInterfaceName(apnType);
+ }
+
+ public String getIpAddress(String apnType) {
+ return mActivePhone.getIpAddress(apnType);
+ }
+
+ public String getGateway(String apnType) {
+ return mActivePhone.getGateway(apnType);
+ }
+
+ public String[] getDnsServers(String apnType) {
+ return mActivePhone.getDnsServers(apnType);
+ }
+
+ public String getDeviceId() {
+ return mActivePhone.getDeviceId();
+ }
+
+ public String getDeviceSvn() {
+ return mActivePhone.getDeviceSvn();
+ }
+
+ public String getSubscriberId() {
+ return mActivePhone.getSubscriberId();
+ }
+
+ public String getIccSerialNumber() {
+ return mActivePhone.getIccSerialNumber();
+ }
+
+ public String getEsn() {
+ return mActivePhone.getEsn();
+ }
+
+ public String getMeid() {
+ return mActivePhone.getMeid();
+ }
+
+ public PhoneSubInfo getPhoneSubInfo(){
+ return mActivePhone.getPhoneSubInfo();
+ }
+
+ public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+ return mActivePhone.getIccSmsInterfaceManager();
+ }
+
+ public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+ return mActivePhone.getIccPhoneBookInterfaceManager();
+ }
+
+ public void setTTYMode(int ttyMode, Message onComplete) {
+ mActivePhone.setTTYMode(ttyMode, onComplete);
+ }
+
+ public void queryTTYMode(Message onComplete) {
+ mActivePhone.queryTTYMode(onComplete);
+ }
+
+ public void activateCellBroadcastSms(int activate, Message response) {
+ mActivePhone.activateCellBroadcastSms(activate, response);
+ }
+
+ public void getCellBroadcastSmsConfig(Message response) {
+ mActivePhone.getCellBroadcastSmsConfig(response);
+ }
+
+ public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
+ mActivePhone.setCellBroadcastSmsConfig(configValuesArray, response);
+ }
+
+ public void notifyDataActivity() {
+ mActivePhone.notifyDataActivity();
+ }
+
+ public void getSmscAddress(Message result) {
+ mActivePhone.getSmscAddress(result);
+ }
+
+ public void setSmscAddress(String address, Message result) {
+ mActivePhone.setSmscAddress(address, result);
+ }
+
+ public int getCdmaEriIconIndex() {
+ return mActivePhone.getCdmaEriIconIndex();
+ }
+
+ public String getCdmaEriText() {
+ return mActivePhone.getCdmaEriText();
+ }
+
+ public int getCdmaEriIconMode() {
+ return mActivePhone.getCdmaEriIconMode();
+ }
+
+ public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete){
+ mActivePhone.sendBurstDtmf(dtmfString, on, off, onComplete);
+ }
+
+ public void exitEmergencyCallbackMode(){
+ mActivePhone.exitEmergencyCallbackMode();
+ }
+
+ public boolean isOtaSpNumber(String dialStr){
+ return mActivePhone.isOtaSpNumber(dialStr);
+ }
+
+ public void registerForCallWaiting(Handler h, int what, Object obj){
+ mActivePhone.registerForCallWaiting(h,what,obj);
+ }
+
+ public void unregisterForCallWaiting(Handler h){
+ mActivePhone.unregisterForCallWaiting(h);
+ }
+
+ public void registerForSignalInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerForSignalInfo(h,what,obj);
+ }
+
+ public void unregisterForSignalInfo(Handler h) {
+ mActivePhone.unregisterForSignalInfo(h);
+ }
+
+ public void registerForDisplayInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerForDisplayInfo(h,what,obj);
+ }
+
+ public void unregisterForDisplayInfo(Handler h) {
+ mActivePhone.unregisterForDisplayInfo(h);
+ }
+
+ public void registerForNumberInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerForNumberInfo(h, what, obj);
+ }
+
+ public void unregisterForNumberInfo(Handler h) {
+ mActivePhone.unregisterForNumberInfo(h);
+ }
+
+ public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerForRedirectedNumberInfo(h, what, obj);
+ }
+
+ public void unregisterForRedirectedNumberInfo(Handler h) {
+ mActivePhone.unregisterForRedirectedNumberInfo(h);
+ }
+
+ public void registerForLineControlInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerForLineControlInfo( h, what, obj);
+ }
+
+ public void unregisterForLineControlInfo(Handler h) {
+ mActivePhone.unregisterForLineControlInfo(h);
+ }
+
+ public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerFoT53ClirlInfo(h, what, obj);
+ }
+
+ public void unregisterForT53ClirInfo(Handler h) {
+ mActivePhone.unregisterForT53ClirInfo(h);
+ }
+
+ public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
+ mActivePhone.registerForT53AudioControlInfo( h, what, obj);
+ }
+
+ public void unregisterForT53AudioControlInfo(Handler h) {
+ mActivePhone.unregisterForT53AudioControlInfo(h);
+ }
+
+ public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
+ mActivePhone.setOnEcbModeExitResponse(h,what,obj);
+ }
+
+ public void unsetOnEcbModeExitResponse(Handler h){
+ mActivePhone.unsetOnEcbModeExitResponse(h);
+ }
+}