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