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 17package com.android.internal.telephony; 18 19import android.content.Context; 20import android.net.LocalServerSocket; 21import android.os.Looper; 22import android.provider.Settings; 23import android.util.Log; 24import android.os.SystemProperties; 25 26import com.android.internal.telephony.cdma.CDMAPhone; 27import com.android.internal.telephony.cdma.CDMALTEPhone; 28import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 29import com.android.internal.telephony.gsm.GSMPhone; 30import com.android.internal.telephony.sip.SipPhone; 31import com.android.internal.telephony.sip.SipPhoneFactory; 32 33/** 34 * {@hide} 35 */ 36public class PhoneFactory { 37 static final String LOG_TAG = "PHONE"; 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 preferredCdmaSubscription = 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 (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) { 105 preferredNetworkMode = Phone.NT_MODE_GLOBAL; 106 } 107 int networkMode = Settings.Secure.getInt(context.getContentResolver(), 108 Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode); 109 Log.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 = BaseCommands.getLteOnCdmaModeStatic(); 117 switch (lteOnCdma) { 118 case Phone.LTE_ON_CDMA_FALSE: 119 cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV; 120 Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV"); 121 break; 122 case Phone.LTE_ON_CDMA_TRUE: 123 cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM; 124 Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM"); 125 break; 126 case Phone.LTE_ON_CDMA_UNKNOWN: 127 default: 128 //Get cdmaSubscription mode from Settings.System 129 cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(), 130 Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, 131 preferredCdmaSubscription); 132 Log.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION"); 133 break; 134 } 135 Log.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 int phoneType = getPhoneType(networkMode); 141 if (phoneType == Phone.PHONE_TYPE_GSM) { 142 Log.i(LOG_TAG, "Creating GSMPhone"); 143 sProxyPhone = new PhoneProxy(new GSMPhone(context, 144 sCommandsInterface, sPhoneNotifier)); 145 } else if (phoneType == Phone.PHONE_TYPE_CDMA) { 146 switch (BaseCommands.getLteOnCdmaModeStatic()) { 147 case Phone.LTE_ON_CDMA_TRUE: 148 Log.i(LOG_TAG, "Creating CDMALTEPhone"); 149 sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, 150 sCommandsInterface, sPhoneNotifier)); 151 break; 152 case Phone.LTE_ON_CDMA_FALSE: 153 default: 154 Log.i(LOG_TAG, "Creating CDMAPhone"); 155 sProxyPhone = new PhoneProxy(new CDMAPhone(context, 156 sCommandsInterface, sPhoneNotifier)); 157 break; 158 } 159 } 160 161 sMadeDefaults = true; 162 } 163 } 164 } 165 166 /* 167 * This function returns the type of the phone, depending 168 * on the network mode. 169 * 170 * @param network mode 171 * @return Phone Type 172 */ 173 public static int getPhoneType(int networkMode) { 174 switch(networkMode) { 175 case RILConstants.NETWORK_MODE_CDMA: 176 case RILConstants.NETWORK_MODE_CDMA_NO_EVDO: 177 case RILConstants.NETWORK_MODE_EVDO_NO_CDMA: 178 return Phone.PHONE_TYPE_CDMA; 179 180 case RILConstants.NETWORK_MODE_WCDMA_PREF: 181 case RILConstants.NETWORK_MODE_GSM_ONLY: 182 case RILConstants.NETWORK_MODE_WCDMA_ONLY: 183 case RILConstants.NETWORK_MODE_GSM_UMTS: 184 return Phone.PHONE_TYPE_GSM; 185 186 // Use CDMA Phone for the global mode including CDMA 187 case RILConstants.NETWORK_MODE_GLOBAL: 188 case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO: 189 case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA: 190 return Phone.PHONE_TYPE_CDMA; 191 192 case RILConstants.NETWORK_MODE_LTE_ONLY: 193 if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) { 194 return Phone.PHONE_TYPE_CDMA; 195 } else { 196 return Phone.PHONE_TYPE_GSM; 197 } 198 default: 199 return Phone.PHONE_TYPE_GSM; 200 } 201 } 202 203 public static Phone getDefaultPhone() { 204 if (sLooper != Looper.myLooper()) { 205 throw new RuntimeException( 206 "PhoneFactory.getDefaultPhone must be called from Looper thread"); 207 } 208 209 if (!sMadeDefaults) { 210 throw new IllegalStateException("Default phones haven't been made yet!"); 211 } 212 return sProxyPhone; 213 } 214 215 public static Phone getCdmaPhone() { 216 Phone phone; 217 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 218 switch (BaseCommands.getLteOnCdmaModeStatic()) { 219 case Phone.LTE_ON_CDMA_TRUE: { 220 phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier); 221 break; 222 } 223 case Phone.LTE_ON_CDMA_FALSE: 224 case Phone.LTE_ON_CDMA_UNKNOWN: 225 default: { 226 phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier); 227 break; 228 } 229 } 230 } 231 return phone; 232 } 233 234 public static Phone getGsmPhone() { 235 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 236 Phone phone = new GSMPhone(sContext, sCommandsInterface, sPhoneNotifier); 237 return phone; 238 } 239 } 240 241 /** 242 * Makes a {@link SipPhone} object. 243 * @param sipUri the local SIP URI the phone runs on 244 * @return the {@code SipPhone} object or null if the SIP URI is not valid 245 */ 246 public static SipPhone makeSipPhone(String sipUri) { 247 return SipPhoneFactory.makePhone(sipUri, sContext, sPhoneNotifier); 248 } 249} 250