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