| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.telephony; |
| |
| import android.content.Context; |
| import android.net.LocalServerSocket; |
| import android.os.Looper; |
| import android.provider.Settings; |
| import android.util.Log; |
| import android.os.SystemProperties; |
| |
| import com.android.internal.telephony.cdma.CDMAPhone; |
| import com.android.internal.telephony.cdma.CDMALTEPhone; |
| import com.android.internal.telephony.gsm.GSMPhone; |
| import com.android.internal.telephony.sip.SipPhone; |
| import com.android.internal.telephony.sip.SipPhoneFactory; |
| |
| /** |
| * {@hide} |
| */ |
| public class PhoneFactory { |
| static final String LOG_TAG = "PHONE"; |
| static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000; |
| static final int SOCKET_OPEN_MAX_RETRY = 3; |
| |
| //***** Class Variables |
| |
| static private Phone sProxyPhone = null; |
| static private CommandsInterface sCommandsInterface = null; |
| |
| static private boolean sMadeDefaults = false; |
| static private PhoneNotifier sPhoneNotifier; |
| static private Looper sLooper; |
| static private Context sContext; |
| |
| static final int preferredCdmaSubscription = RILConstants.PREFERRED_CDMA_SUBSCRIPTION; |
| |
| //***** Class Methods |
| |
| public static void makeDefaultPhones(Context context) { |
| makeDefaultPhone(context); |
| } |
| |
| /** |
| * FIXME replace this with some other way of making these |
| * instances |
| */ |
| public static void makeDefaultPhone(Context context) { |
| synchronized(Phone.class) { |
| if (!sMadeDefaults) { |
| sLooper = Looper.myLooper(); |
| sContext = context; |
| |
| if (sLooper == null) { |
| throw new RuntimeException( |
| "PhoneFactory.makeDefaultPhone must be called from Looper thread"); |
| } |
| |
| int retryCount = 0; |
| for(;;) { |
| boolean hasException = false; |
| retryCount ++; |
| |
| try { |
| // use UNIX domain socket to |
| // prevent subsequent initialization |
| new LocalServerSocket("com.android.internal.telephony"); |
| } catch (java.io.IOException ex) { |
| hasException = true; |
| } |
| |
| if ( !hasException ) { |
| break; |
| } else if (retryCount > SOCKET_OPEN_MAX_RETRY) { |
| throw new RuntimeException("PhoneFactory probably already running"); |
| } else { |
| try { |
| Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); |
| } catch (InterruptedException er) { |
| } |
| } |
| } |
| |
| sPhoneNotifier = new DefaultPhoneNotifier(); |
| |
| // Get preferred network mode |
| int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE; |
| if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) { |
| preferredNetworkMode = Phone.NT_MODE_GLOBAL; |
| } |
| int networkMode = Settings.Secure.getInt(context.getContentResolver(), |
| Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode); |
| Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode)); |
| |
| // Get cdmaSubscription |
| // TODO: Change when the ril will provides a way to know at runtime |
| // the configuration, bug 4202572. And the ril issues the |
| // RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, bug 4295439. |
| int cdmaSubscription; |
| int lteOnCdma = BaseCommands.getLteOnCdmaModeStatic(); |
| switch (lteOnCdma) { |
| case Phone.LTE_ON_CDMA_FALSE: |
| cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_NV; |
| Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV"); |
| break; |
| case Phone.LTE_ON_CDMA_TRUE: |
| cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_RUIM; |
| Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM"); |
| break; |
| case Phone.LTE_ON_CDMA_UNKNOWN: |
| default: |
| //Get cdmaSubscription mode from Settings.System |
| cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(), |
| Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, |
| preferredCdmaSubscription); |
| Log.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION"); |
| break; |
| } |
| Log.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription); |
| |
| //reads the system properties and makes commandsinterface |
| sCommandsInterface = new RIL(context, networkMode, cdmaSubscription); |
| |
| int phoneType = getPhoneType(networkMode); |
| if (phoneType == Phone.PHONE_TYPE_GSM) { |
| Log.i(LOG_TAG, "Creating GSMPhone"); |
| sProxyPhone = new PhoneProxy(new GSMPhone(context, |
| sCommandsInterface, sPhoneNotifier)); |
| } else if (phoneType == Phone.PHONE_TYPE_CDMA) { |
| switch (BaseCommands.getLteOnCdmaModeStatic()) { |
| case Phone.LTE_ON_CDMA_TRUE: |
| Log.i(LOG_TAG, "Creating CDMALTEPhone"); |
| sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, |
| sCommandsInterface, sPhoneNotifier)); |
| break; |
| case Phone.LTE_ON_CDMA_FALSE: |
| default: |
| Log.i(LOG_TAG, "Creating CDMAPhone"); |
| sProxyPhone = new PhoneProxy(new CDMAPhone(context, |
| sCommandsInterface, sPhoneNotifier)); |
| break; |
| } |
| } |
| |
| sMadeDefaults = true; |
| } |
| } |
| } |
| |
| /* |
| * This function returns the type of the phone, depending |
| * on the network mode. |
| * |
| * @param network mode |
| * @return Phone Type |
| */ |
| public static int getPhoneType(int networkMode) { |
| switch(networkMode) { |
| case RILConstants.NETWORK_MODE_CDMA: |
| case RILConstants.NETWORK_MODE_CDMA_NO_EVDO: |
| case RILConstants.NETWORK_MODE_EVDO_NO_CDMA: |
| return Phone.PHONE_TYPE_CDMA; |
| |
| case RILConstants.NETWORK_MODE_WCDMA_PREF: |
| case RILConstants.NETWORK_MODE_GSM_ONLY: |
| case RILConstants.NETWORK_MODE_WCDMA_ONLY: |
| case RILConstants.NETWORK_MODE_GSM_UMTS: |
| return Phone.PHONE_TYPE_GSM; |
| |
| // Use CDMA Phone for the global mode including CDMA |
| case RILConstants.NETWORK_MODE_GLOBAL: |
| case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO: |
| case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA: |
| return Phone.PHONE_TYPE_CDMA; |
| |
| case RILConstants.NETWORK_MODE_LTE_ONLY: |
| if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) { |
| return Phone.PHONE_TYPE_CDMA; |
| } else { |
| return Phone.PHONE_TYPE_GSM; |
| } |
| default: |
| return Phone.PHONE_TYPE_GSM; |
| } |
| } |
| |
| public static Phone getDefaultPhone() { |
| if (sLooper != Looper.myLooper()) { |
| throw new RuntimeException( |
| "PhoneFactory.getDefaultPhone must be called from Looper thread"); |
| } |
| |
| if (!sMadeDefaults) { |
| throw new IllegalStateException("Default phones haven't been made yet!"); |
| } |
| return sProxyPhone; |
| } |
| |
| public static Phone getCdmaPhone() { |
| Phone phone; |
| synchronized(PhoneProxy.lockForRadioTechnologyChange) { |
| switch (BaseCommands.getLteOnCdmaModeStatic()) { |
| case Phone.LTE_ON_CDMA_TRUE: { |
| phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier); |
| break; |
| } |
| case Phone.LTE_ON_CDMA_FALSE: |
| case Phone.LTE_ON_CDMA_UNKNOWN: |
| default: { |
| phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier); |
| break; |
| } |
| } |
| } |
| return phone; |
| } |
| |
| public static Phone getGsmPhone() { |
| synchronized(PhoneProxy.lockForRadioTechnologyChange) { |
| Phone phone = new GSMPhone(sContext, sCommandsInterface, sPhoneNotifier); |
| return phone; |
| } |
| } |
| |
| /** |
| * Makes a {@link SipPhone} object. |
| * @param sipUri the local SIP URI the phone runs on |
| * @return the {@code SipPhone} object or null if the SIP URI is not valid |
| */ |
| public static SipPhone makeSipPhone(String sipUri) { |
| return SipPhoneFactory.makePhone(sipUri, sContext, sPhoneNotifier); |
| } |
| } |