2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.internal.telephony.sip;
19 import android.content.Context;
20 import android.os.AsyncResult;
21 import android.os.Handler;
22 import android.os.Message;
23 import android.os.Registrant;
24 import android.os.RegistrantList;
25 import android.os.SystemProperties;
26 import android.telephony.CellLocation;
27 import android.telephony.ServiceState;
28 import android.telephony.SignalStrength;
29 import android.util.Log;
31 import com.android.internal.telephony.Call;
32 import com.android.internal.telephony.CallStateException;
33 import com.android.internal.telephony.Connection;
34 import com.android.internal.telephony.DataConnection;
35 import com.android.internal.telephony.IccCard;
36 import com.android.internal.telephony.IccFileHandler;
37 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
38 import com.android.internal.telephony.IccSmsInterfaceManager;
39 import com.android.internal.telephony.MmiCode;
40 import com.android.internal.telephony.Phone;
41 import com.android.internal.telephony.PhoneBase;
42 import com.android.internal.telephony.PhoneNotifier;
43 import com.android.internal.telephony.PhoneSubInfo;
44 import com.android.internal.telephony.TelephonyProperties;
46 import java.util.ArrayList;
47 import java.util.List;
49 abstract class SipPhoneBase extends PhoneBase {
50 private static final String LOG_TAG = "SipPhone";
52 private RegistrantList mRingbackRegistrants = new RegistrantList();
53 private State state = State.IDLE;
55 public SipPhoneBase(Context context, PhoneNotifier notifier) {
56 super(notifier, context, new SipCommandInterface(context), false);
59 public abstract Call getForegroundCall();
61 public abstract Call getBackgroundCall();
63 public abstract Call getRingingCall();
65 void migrateFrom(SipPhoneBase from) {
66 migrate(mRingbackRegistrants, from.mRingbackRegistrants);
67 migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
68 migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
69 migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
70 migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
71 migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
72 migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
73 migrate(mMmiRegistrants, from.mMmiRegistrants);
74 migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
75 migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
78 static void migrate(RegistrantList to, RegistrantList from) {
80 for (int i = 0, n = from.size(); i < n; i++) {
81 to.add((Registrant) from.get(i));
86 public void registerForRingbackTone(Handler h, int what, Object obj) {
87 mRingbackRegistrants.addUnique(h, what, obj);
91 public void unregisterForRingbackTone(Handler h) {
92 mRingbackRegistrants.remove(h);
95 protected void startRingbackTone() {
96 AsyncResult result = new AsyncResult(null, new Boolean(true), null);
97 mRingbackRegistrants.notifyRegistrants(result);
100 protected void stopRingbackTone() {
101 AsyncResult result = new AsyncResult(null, new Boolean(false), null);
102 mRingbackRegistrants.notifyRegistrants(result);
105 public ServiceState getServiceState() {
106 // FIXME: we may need to provide this when data connectivity is lost
107 // or when server is down
108 ServiceState s = new ServiceState();
109 s.setState(ServiceState.STATE_IN_SERVICE);
113 public CellLocation getCellLocation() {
117 public State getState() {
121 public int getPhoneType() {
122 return Phone.PHONE_TYPE_SIP;
125 public SignalStrength getSignalStrength() {
126 return new SignalStrength();
129 public boolean getMessageWaitingIndicator() {
133 public boolean getCallForwardingIndicator() {
137 public List<? extends MmiCode> getPendingMmiCodes() {
138 return new ArrayList<MmiCode>(0);
141 public DataState getDataConnectionState() {
142 return DataState.DISCONNECTED;
145 public DataState getDataConnectionState(String apnType) {
146 return DataState.DISCONNECTED;
149 public DataActivityState getDataActivityState() {
150 return DataActivityState.NONE;
154 * Notify any interested party of a Phone state change {@link Phone.State}
156 void notifyPhoneStateChanged() {
157 mNotifier.notifyPhoneState(this);
161 * Notify registrants of a change in the call state. This notifies changes in {@link Call.State}
162 * Use this when changes in the precise call state are needed, else use notifyPhoneStateChanged.
164 void notifyPreciseCallStateChanged() {
165 /* we'd love it if this was package-scoped*/
166 super.notifyPreciseCallStateChangedP();
169 void notifyNewRingingConnection(Connection c) {
170 super.notifyNewRingingConnectionP(c);
173 void notifyDisconnect(Connection cn) {
174 mDisconnectRegistrants.notifyResult(cn);
177 void notifyUnknownConnection() {
178 mUnknownConnectionRegistrants.notifyResult(this);
181 void notifySuppServiceFailed(SuppService code) {
182 mSuppServiceFailedRegistrants.notifyResult(code);
185 void notifyServiceStateChanged(ServiceState ss) {
186 super.notifyServiceStateChangedP(ss);
189 public void notifyCallForwardingIndicator() {
190 mNotifier.notifyCallForwardingChanged(this);
193 public boolean canDial() {
194 int serviceState = getServiceState().getState();
195 Log.v(LOG_TAG, "canDial(): serviceState = " + serviceState);
196 if (serviceState == ServiceState.STATE_POWER_OFF) return false;
198 String disableCall = SystemProperties.get(
199 TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
200 Log.v(LOG_TAG, "canDial(): disableCall = " + disableCall);
201 if (disableCall.equals("true")) return false;
203 Log.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState());
204 Log.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState());
205 Log.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState());
206 return !getRingingCall().isRinging()
207 && (!getForegroundCall().getState().isAlive()
208 || !getBackgroundCall().getState().isAlive());
211 public boolean handleInCallMmiCommands(String dialString)
212 throws CallStateException {
217 Call.State foregroundCallState = getForegroundCall().getState();
218 Call.State backgroundCallState = getBackgroundCall().getState();
219 Call.State ringingCallState = getRingingCall().getState();
221 return (foregroundCallState.isAlive() || backgroundCallState.isAlive()
222 || ringingCallState.isAlive());
225 public boolean handlePinMmi(String dialString) {
229 public void sendUssdResponse(String ussdMessge) {
232 public void registerForSuppServiceNotification(
233 Handler h, int what, Object obj) {
236 public void unregisterForSuppServiceNotification(Handler h) {
239 public void setRadioPower(boolean power) {
242 public String getVoiceMailNumber() {
246 public String getVoiceMailAlphaTag() {
250 public String getDeviceId() {
254 public String getDeviceSvn() {
258 public String getEsn() {
259 Log.e(LOG_TAG, "[SipPhone] getEsn() is a CDMA method");
263 public String getMeid() {
264 Log.e(LOG_TAG, "[SipPhone] getMeid() is a CDMA method");
268 public String getSubscriberId() {
272 public String getIccSerialNumber() {
276 public String getLine1Number() {
280 public String getLine1AlphaTag() {
284 public void setLine1Number(String alphaTag, String number, Message onComplete) {
285 // FIXME: what to reply for SIP?
286 AsyncResult.forMessage(onComplete, null, null);
287 onComplete.sendToTarget();
290 public void setVoiceMailNumber(String alphaTag, String voiceMailNumber,
291 Message onComplete) {
292 // FIXME: what to reply for SIP?
293 AsyncResult.forMessage(onComplete, null, null);
294 onComplete.sendToTarget();
297 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
300 public void setCallForwardingOption(int commandInterfaceCFAction,
301 int commandInterfaceCFReason, String dialingNumber,
302 int timerSeconds, Message onComplete) {
305 public void getOutgoingCallerIdDisplay(Message onComplete) {
306 // FIXME: what to reply?
307 AsyncResult.forMessage(onComplete, null, null);
308 onComplete.sendToTarget();
311 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
312 Message onComplete) {
313 // FIXME: what's this for SIP?
314 AsyncResult.forMessage(onComplete, null, null);
315 onComplete.sendToTarget();
318 public void getCallWaiting(Message onComplete) {
319 AsyncResult.forMessage(onComplete, null, null);
320 onComplete.sendToTarget();
323 public void setCallWaiting(boolean enable, Message onComplete) {
324 Log.e(LOG_TAG, "call waiting not supported");
327 public boolean getIccRecordsLoaded() {
331 public IccCard getIccCard() {
335 public void getAvailableNetworks(Message response) {
338 public void setNetworkSelectionModeAutomatic(Message response) {
341 public void selectNetworkManually(
342 com.android.internal.telephony.gsm.NetworkInfo network,
346 public void getNeighboringCids(Message response) {
349 public void setOnPostDialCharacter(Handler h, int what, Object obj) {
352 public void getDataCallList(Message response) {
355 public List<DataConnection> getCurrentDataConnectionList () {
359 public void updateServiceLocation() {
362 public void enableLocationUpdates() {
365 public void disableLocationUpdates() {
368 public boolean getDataRoamingEnabled() {
372 public void setDataRoamingEnabled(boolean enable) {
375 public boolean enableDataConnectivity() {
379 public boolean disableDataConnectivity() {
383 public boolean isDataConnectivityPossible() {
387 boolean updateCurrentCarrierInProvider() {
391 public void saveClirSetting(int commandInterfaceCLIRMode) {
394 public PhoneSubInfo getPhoneSubInfo(){
398 public IccSmsInterfaceManager getIccSmsInterfaceManager(){
402 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
406 public IccFileHandler getIccFileHandler(){
410 public void activateCellBroadcastSms(int activate, Message response) {
411 Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
414 public void getCellBroadcastSmsConfig(Message response) {
415 Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
418 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
419 Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
422 void updatePhoneState() {
423 State oldState = state;
425 if (getRingingCall().isRinging()) {
426 state = State.RINGING;
427 } else if (getForegroundCall().isIdle()
428 && getBackgroundCall().isIdle()) {
431 state = State.OFFHOOK;
434 if (state != oldState) {
435 Log.d(LOG_TAG, " ^^^ new phone state: " + state);
436 notifyPhoneStateChanged();