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