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