Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2006 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;
     18 
     19 import android.content.Context;
     20 import android.net.LocalServerSocket;
     21 import android.os.Looper;
     22 import android.provider.Settings;
     23 import android.telephony.TelephonyManager;
     24 import android.telephony.Rlog;
     25 import com.android.internal.telephony.cdma.CDMAPhone;
     26 import com.android.internal.telephony.cdma.CDMALTEPhone;
     27 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
     28 import com.android.internal.telephony.gsm.GSMPhone;
     29 import com.android.internal.telephony.sip.SipPhone;
     30 import com.android.internal.telephony.sip.SipPhoneFactory;
     31 import com.android.internal.telephony.uicc.UiccController;
     32 
     33 /**
     34  * {@hide}
     35  */
     36 public class PhoneFactory {
     37     static final String LOG_TAG = "PhoneFactory";
     38     static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
     39     static final int SOCKET_OPEN_MAX_RETRY = 3;
     40 
     41     //***** Class Variables
     42 
     43     static private Phone sProxyPhone = null;
     44     static private CommandsInterface sCommandsInterface = null;
     45 
     46     static private boolean sMadeDefaults = false;
     47     static private PhoneNotifier sPhoneNotifier;
     48     static private Looper sLooper;
     49     static private Context sContext;
     50 
     51     static final int sPreferredCdmaSubscription =
     52                          CdmaSubscriptionSourceManager.PREFERRED_CDMA_SUBSCRIPTION;
     53 
     54     //***** Class Methods
     55 
     56     public static void makeDefaultPhones(Context context) {
     57         makeDefaultPhone(context);
     58     }
     59 
     60     /**
     61      * FIXME replace this with some other way of making these
     62      * instances
     63      */
     64     public static void makeDefaultPhone(Context context) {
     65         synchronized(Phone.class) {
     66             if (!sMadeDefaults) {
     67                 sLooper = Looper.myLooper();
     68                 sContext = context;
     69 
     70                 if (sLooper == null) {
     71                     throw new RuntimeException(
     72                         "PhoneFactory.makeDefaultPhone must be called from Looper thread");
     73                 }
     74 
     75                 int retryCount = 0;
     76                 for(;;) {
     77                     boolean hasException = false;
     78                     retryCount ++;
     79 
     80                     try {
     81                         // use UNIX domain socket to
     82                         // prevent subsequent initialization
     83                         new LocalServerSocket("com.android.internal.telephony");
     84                     } catch (java.io.IOException ex) {
     85                         hasException = true;
     86                     }
     87 
     88                     if ( !hasException ) {
     89                         break;
     90                     } else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
     91                         throw new RuntimeException("PhoneFactory probably already running");
     92                     } else {
     93                         try {
     94                             Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
     95                         } catch (InterruptedException er) {
     96                         }
     97                     }
     98                 }
     99 
    100                 sPhoneNotifier = new DefaultPhoneNotifier();
    101 
    102                 // Get preferred network mode
    103                 int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
    104                 if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
    105                     preferredNetworkMode = Phone.NT_MODE_GLOBAL;
    106                 }
    107                 int networkMode = Settings.Global.getInt(context.getContentResolver(),
    108                         Settings.Global.PREFERRED_NETWORK_MODE, preferredNetworkMode);
    109                 Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
    110 
    111                 // Get cdmaSubscription
    112                 // TODO: Change when the ril will provides a way to know at runtime
    113                 //       the configuration, bug 4202572. And the ril issues the
    114                 //       RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, bug 4295439.
    115                 int cdmaSubscription;
    116                 int lteOnCdma = TelephonyManager.getLteOnCdmaModeStatic();
    117                 switch (lteOnCdma) {
    118                     case PhoneConstants.LTE_ON_CDMA_FALSE:
    119                         cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV;
    120                         Rlog.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
    121                         break;
    122                     case PhoneConstants.LTE_ON_CDMA_TRUE:
    123                         cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM;
    124                         Rlog.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
    125                         break;
    126                     case PhoneConstants.LTE_ON_CDMA_UNKNOWN:
    127                     default:
    128                         //Get cdmaSubscription mode from Settings.System
    129                         cdmaSubscription = Settings.Global.getInt(context.getContentResolver(),
    130                                 Settings.Global.PREFERRED_CDMA_SUBSCRIPTION,
    131                                 sPreferredCdmaSubscription);
    132                         Rlog.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION");
    133                         break;
    134                 }
    135                 Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
    136 
    137                 //reads the system properties and makes commandsinterface
    138                 sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
    139 
    140                 // Instantiate UiccController so that all other classes can just call getInstance()
    141                 UiccController.make(context, sCommandsInterface);
    142 
    143                 int phoneType = TelephonyManager.getPhoneType(networkMode);
    144                 if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
    145                     Rlog.i(LOG_TAG, "Creating GSMPhone");
    146                     sProxyPhone = new PhoneProxy(new GSMPhone(context,
    147                             sCommandsInterface, sPhoneNotifier));
    148                 } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
    149                     switch (TelephonyManager.getLteOnCdmaModeStatic()) {
    150                         case PhoneConstants.LTE_ON_CDMA_TRUE:
    151                             Rlog.i(LOG_TAG, "Creating CDMALTEPhone");
    152                             sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,
    153                                 sCommandsInterface, sPhoneNotifier));
    154                             break;
    155                         case PhoneConstants.LTE_ON_CDMA_FALSE:
    156                         default:
    157                             Rlog.i(LOG_TAG, "Creating CDMAPhone");
    158                             sProxyPhone = new PhoneProxy(new CDMAPhone(context,
    159                                     sCommandsInterface, sPhoneNotifier));
    160                             break;
    161                     }
    162                 }
    163 
    164                 sMadeDefaults = true;
    165             }
    166         }
    167     }
    168 
    169     public static Phone getDefaultPhone() {
    170         if (sLooper != Looper.myLooper()) {
    171             throw new RuntimeException(
    172                 "PhoneFactory.getDefaultPhone must be called from Looper thread");
    173         }
    174 
    175         if (!sMadeDefaults) {
    176             throw new IllegalStateException("Default phones haven't been made yet!");
    177         }
    178        return sProxyPhone;
    179     }
    180 
    181     public static Phone getCdmaPhone() {
    182         Phone phone;
    183         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
    184             switch (TelephonyManager.getLteOnCdmaModeStatic()) {
    185                 case PhoneConstants.LTE_ON_CDMA_TRUE: {
    186                     phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier);
    187                     break;
    188                 }
    189                 case PhoneConstants.LTE_ON_CDMA_FALSE:
    190                 case PhoneConstants.LTE_ON_CDMA_UNKNOWN:
    191                 default: {
    192                     phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
    193                     break;
    194                 }
    195             }
    196         }
    197         return phone;
    198     }
    199 
    200     public static Phone getGsmPhone() {
    201         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
    202             Phone phone = new GSMPhone(sContext, sCommandsInterface, sPhoneNotifier);
    203             return phone;
    204         }
    205     }
    206 
    207     /**
    208      * Makes a {@link SipPhone} object.
    209      * @param sipUri the local SIP URI the phone runs on
    210      * @return the {@code SipPhone} object or null if the SIP URI is not valid
    211      */
    212     public static SipPhone makeSipPhone(String sipUri) {
    213         return SipPhoneFactory.makePhone(sipUri, sContext, sPhoneNotifier);
    214     }
    215 }
    216