Home | History | Annotate | Download | only in sip
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      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
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     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.
     15  */
     16 
     17 package com.android.internal.telephony.sip;
     18 
     19 import android.content.Context;
     20 import android.net.LinkProperties;
     21 import android.os.AsyncResult;
     22 import android.os.Handler;
     23 import android.os.Message;
     24 import android.os.Registrant;
     25 import android.os.RegistrantList;
     26 import android.os.SystemProperties;
     27 import android.telephony.CellLocation;
     28 import android.telephony.ServiceState;
     29 import android.telephony.SignalStrength;
     30 import android.util.Log;
     31 
     32 import com.android.internal.telephony.Call;
     33 import com.android.internal.telephony.CallStateException;
     34 import com.android.internal.telephony.Connection;
     35 import com.android.internal.telephony.DataConnection;
     36 import com.android.internal.telephony.IccCard;
     37 import com.android.internal.telephony.IccFileHandler;
     38 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
     39 import com.android.internal.telephony.IccSmsInterfaceManager;
     40 import com.android.internal.telephony.MmiCode;
     41 import com.android.internal.telephony.OperatorInfo;
     42 import com.android.internal.telephony.Phone;
     43 import com.android.internal.telephony.PhoneBase;
     44 import com.android.internal.telephony.PhoneNotifier;
     45 import com.android.internal.telephony.PhoneSubInfo;
     46 import com.android.internal.telephony.TelephonyProperties;
     47 import com.android.internal.telephony.UUSInfo;
     48 
     49 import java.util.ArrayList;
     50 import java.util.List;
     51 
     52 abstract class SipPhoneBase extends PhoneBase {
     53     private static final String LOG_TAG = "SipPhone";
     54 
     55     private RegistrantList mRingbackRegistrants = new RegistrantList();
     56     private State state = State.IDLE;
     57 
     58     public SipPhoneBase(Context context, PhoneNotifier notifier) {
     59         super(notifier, context, new SipCommandInterface(context), false);
     60     }
     61 
     62     public abstract Call getForegroundCall();
     63 
     64     public abstract Call getBackgroundCall();
     65 
     66     public abstract Call getRingingCall();
     67 
     68     public Connection dial(String dialString, UUSInfo uusInfo)
     69             throws CallStateException {
     70         // ignore UUSInfo
     71         return dial(dialString);
     72     }
     73 
     74     void migrateFrom(SipPhoneBase from) {
     75         migrate(mRingbackRegistrants, from.mRingbackRegistrants);
     76         migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
     77         migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
     78         migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
     79         migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
     80         migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
     81         migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
     82         migrate(mMmiRegistrants, from.mMmiRegistrants);
     83         migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
     84         migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
     85     }
     86 
     87     static void migrate(RegistrantList to, RegistrantList from) {
     88         from.removeCleared();
     89         for (int i = 0, n = from.size(); i < n; i++) {
     90             to.add((Registrant) from.get(i));
     91         }
     92     }
     93 
     94     @Override
     95     public void registerForRingbackTone(Handler h, int what, Object obj) {
     96         mRingbackRegistrants.addUnique(h, what, obj);
     97     }
     98 
     99     @Override
    100     public void unregisterForRingbackTone(Handler h) {
    101         mRingbackRegistrants.remove(h);
    102     }
    103 
    104     protected void startRingbackTone() {
    105         AsyncResult result = new AsyncResult(null, Boolean.TRUE, null);
    106         mRingbackRegistrants.notifyRegistrants(result);
    107     }
    108 
    109     protected void stopRingbackTone() {
    110         AsyncResult result = new AsyncResult(null, Boolean.FALSE, null);
    111         mRingbackRegistrants.notifyRegistrants(result);
    112     }
    113 
    114     public ServiceState getServiceState() {
    115         // FIXME: we may need to provide this when data connectivity is lost
    116         // or when server is down
    117         ServiceState s = new ServiceState();
    118         s.setState(ServiceState.STATE_IN_SERVICE);
    119         return s;
    120     }
    121 
    122     public CellLocation getCellLocation() {
    123         return null;
    124     }
    125 
    126     public State getState() {
    127         return state;
    128     }
    129 
    130     public int getPhoneType() {
    131         return Phone.PHONE_TYPE_SIP;
    132     }
    133 
    134     public SignalStrength getSignalStrength() {
    135         return new SignalStrength();
    136     }
    137 
    138     public boolean getMessageWaitingIndicator() {
    139         return false;
    140     }
    141 
    142     public boolean getCallForwardingIndicator() {
    143         return false;
    144     }
    145 
    146     public List<? extends MmiCode> getPendingMmiCodes() {
    147         return new ArrayList<MmiCode>(0);
    148     }
    149 
    150     public DataState getDataConnectionState() {
    151         return DataState.DISCONNECTED;
    152     }
    153 
    154     public DataState getDataConnectionState(String apnType) {
    155         return DataState.DISCONNECTED;
    156     }
    157 
    158     public DataActivityState getDataActivityState() {
    159         return DataActivityState.NONE;
    160     }
    161 
    162     /**
    163      * Notify any interested party of a Phone state change {@link Phone.State}
    164      */
    165     void notifyPhoneStateChanged() {
    166         mNotifier.notifyPhoneState(this);
    167     }
    168 
    169     /**
    170      * Notify registrants of a change in the call state. This notifies changes in {@link Call.State}
    171      * Use this when changes in the precise call state are needed, else use notifyPhoneStateChanged.
    172      */
    173     void notifyPreciseCallStateChanged() {
    174         /* we'd love it if this was package-scoped*/
    175         super.notifyPreciseCallStateChangedP();
    176     }
    177 
    178     void notifyNewRingingConnection(Connection c) {
    179         super.notifyNewRingingConnectionP(c);
    180     }
    181 
    182     void notifyDisconnect(Connection cn) {
    183         mDisconnectRegistrants.notifyResult(cn);
    184     }
    185 
    186     void notifyUnknownConnection() {
    187         mUnknownConnectionRegistrants.notifyResult(this);
    188     }
    189 
    190     void notifySuppServiceFailed(SuppService code) {
    191         mSuppServiceFailedRegistrants.notifyResult(code);
    192     }
    193 
    194     void notifyServiceStateChanged(ServiceState ss) {
    195         super.notifyServiceStateChangedP(ss);
    196     }
    197 
    198     public void notifyCallForwardingIndicator() {
    199         mNotifier.notifyCallForwardingChanged(this);
    200     }
    201 
    202     public boolean canDial() {
    203         int serviceState = getServiceState().getState();
    204         Log.v(LOG_TAG, "canDial(): serviceState = " + serviceState);
    205         if (serviceState == ServiceState.STATE_POWER_OFF) return false;
    206 
    207         String disableCall = SystemProperties.get(
    208                 TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
    209         Log.v(LOG_TAG, "canDial(): disableCall = " + disableCall);
    210         if (disableCall.equals("true")) return false;
    211 
    212         Log.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState());
    213         Log.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState());
    214         Log.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState());
    215         return !getRingingCall().isRinging()
    216                 && (!getForegroundCall().getState().isAlive()
    217                     || !getBackgroundCall().getState().isAlive());
    218     }
    219 
    220     public boolean handleInCallMmiCommands(String dialString)
    221             throws CallStateException {
    222         return false;
    223     }
    224 
    225     boolean isInCall() {
    226         Call.State foregroundCallState = getForegroundCall().getState();
    227         Call.State backgroundCallState = getBackgroundCall().getState();
    228         Call.State ringingCallState = getRingingCall().getState();
    229 
    230        return (foregroundCallState.isAlive() || backgroundCallState.isAlive()
    231             || ringingCallState.isAlive());
    232     }
    233 
    234     public boolean handlePinMmi(String dialString) {
    235         return false;
    236     }
    237 
    238     public void sendUssdResponse(String ussdMessge) {
    239     }
    240 
    241     public void registerForSuppServiceNotification(
    242             Handler h, int what, Object obj) {
    243     }
    244 
    245     public void unregisterForSuppServiceNotification(Handler h) {
    246     }
    247 
    248     public void setRadioPower(boolean power) {
    249     }
    250 
    251     public String getVoiceMailNumber() {
    252         return null;
    253     }
    254 
    255     public String getVoiceMailAlphaTag() {
    256         return null;
    257     }
    258 
    259     public String getDeviceId() {
    260         return null;
    261     }
    262 
    263     public String getDeviceSvn() {
    264         return null;
    265     }
    266 
    267     public String getImei() {
    268         return null;
    269     }
    270 
    271     public String getEsn() {
    272         Log.e(LOG_TAG, "[SipPhone] getEsn() is a CDMA method");
    273         return "0";
    274     }
    275 
    276     public String getMeid() {
    277         Log.e(LOG_TAG, "[SipPhone] getMeid() is a CDMA method");
    278         return "0";
    279     }
    280 
    281     public String getSubscriberId() {
    282         return null;
    283     }
    284 
    285     public String getIccSerialNumber() {
    286         return null;
    287     }
    288 
    289     public String getLine1Number() {
    290         return null;
    291     }
    292 
    293     public String getLine1AlphaTag() {
    294         return null;
    295     }
    296 
    297     public void setLine1Number(String alphaTag, String number, Message onComplete) {
    298         // FIXME: what to reply for SIP?
    299         AsyncResult.forMessage(onComplete, null, null);
    300         onComplete.sendToTarget();
    301     }
    302 
    303     public void setVoiceMailNumber(String alphaTag, String voiceMailNumber,
    304             Message onComplete) {
    305         // FIXME: what to reply for SIP?
    306         AsyncResult.forMessage(onComplete, null, null);
    307         onComplete.sendToTarget();
    308     }
    309 
    310     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
    311     }
    312 
    313     public void setCallForwardingOption(int commandInterfaceCFAction,
    314             int commandInterfaceCFReason, String dialingNumber,
    315             int timerSeconds, Message onComplete) {
    316     }
    317 
    318     public void getOutgoingCallerIdDisplay(Message onComplete) {
    319         // FIXME: what to reply?
    320         AsyncResult.forMessage(onComplete, null, null);
    321         onComplete.sendToTarget();
    322     }
    323 
    324     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
    325                                            Message onComplete) {
    326         // FIXME: what's this for SIP?
    327         AsyncResult.forMessage(onComplete, null, null);
    328         onComplete.sendToTarget();
    329     }
    330 
    331     public void getCallWaiting(Message onComplete) {
    332         AsyncResult.forMessage(onComplete, null, null);
    333         onComplete.sendToTarget();
    334     }
    335 
    336     public void setCallWaiting(boolean enable, Message onComplete) {
    337         Log.e(LOG_TAG, "call waiting not supported");
    338     }
    339 
    340     public boolean getIccRecordsLoaded() {
    341         return false;
    342     }
    343 
    344     public IccCard getIccCard() {
    345         return null;
    346     }
    347 
    348     public void getAvailableNetworks(Message response) {
    349     }
    350 
    351     public void setNetworkSelectionModeAutomatic(Message response) {
    352     }
    353 
    354     public void selectNetworkManually(
    355             OperatorInfo network,
    356             Message response) {
    357     }
    358 
    359     public void getNeighboringCids(Message response) {
    360     }
    361 
    362     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
    363     }
    364 
    365     public void getDataCallList(Message response) {
    366     }
    367 
    368     public List<DataConnection> getCurrentDataConnectionList () {
    369         return null;
    370     }
    371 
    372     public void updateServiceLocation() {
    373     }
    374 
    375     public void enableLocationUpdates() {
    376     }
    377 
    378     public void disableLocationUpdates() {
    379     }
    380 
    381     public boolean getDataRoamingEnabled() {
    382         return false;
    383     }
    384 
    385     public void setDataRoamingEnabled(boolean enable) {
    386     }
    387 
    388     public boolean enableDataConnectivity() {
    389         return false;
    390     }
    391 
    392     public boolean disableDataConnectivity() {
    393         return false;
    394     }
    395 
    396     public boolean isDataConnectivityPossible() {
    397         return false;
    398     }
    399 
    400     boolean updateCurrentCarrierInProvider() {
    401         return false;
    402     }
    403 
    404     public void saveClirSetting(int commandInterfaceCLIRMode) {
    405     }
    406 
    407     public PhoneSubInfo getPhoneSubInfo(){
    408         return null;
    409     }
    410 
    411     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
    412         return null;
    413     }
    414 
    415     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
    416         return null;
    417     }
    418 
    419     public IccFileHandler getIccFileHandler(){
    420         return null;
    421     }
    422 
    423     public void activateCellBroadcastSms(int activate, Message response) {
    424         Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
    425     }
    426 
    427     public void getCellBroadcastSmsConfig(Message response) {
    428         Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
    429     }
    430 
    431     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
    432         Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
    433     }
    434 
    435     //@Override
    436     public boolean needsOtaServiceProvisioning() {
    437         // FIXME: what's this for SIP?
    438         return false;
    439     }
    440 
    441     //@Override
    442     public LinkProperties getLinkProperties(String apnType) {
    443         // FIXME: what's this for SIP?
    444         return null;
    445     }
    446 
    447     void updatePhoneState() {
    448         State oldState = state;
    449 
    450         if (getRingingCall().isRinging()) {
    451             state = State.RINGING;
    452         } else if (getForegroundCall().isIdle()
    453                 && getBackgroundCall().isIdle()) {
    454             state = State.IDLE;
    455         } else {
    456             state = State.OFFHOOK;
    457         }
    458 
    459         if (state != oldState) {
    460             Log.d(LOG_TAG, " ^^^ new phone state: " + state);
    461             notifyPhoneStateChanged();
    462         }
    463     }
    464 }
    465