PhoneFactory.java revision c67761d00a25bd095364e3ff4e4cb8e88b2e974c
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 mode
102                int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
103                if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
104                    preferredNetworkMode = Phone.NT_MODE_GLOBAL;
105                }
106                int networkMode = Settings.Global.getInt(context.getContentResolver(),
107                        Settings.Global.PREFERRED_NETWORK_MODE, preferredNetworkMode);
108                Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
109
110                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
111                Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
112
113                //reads the system properties and makes commandsinterface
114                sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
115
116                // Instantiate UiccController so that all other classes can just call getInstance()
117                UiccController.make(context, sCommandsInterface);
118
119                int phoneType = TelephonyManager.getPhoneType(networkMode);
120                if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
121                    Rlog.i(LOG_TAG, "Creating GSMPhone");
122                    sProxyPhone = new PhoneProxy(new GSMPhone(context,
123                            sCommandsInterface, sPhoneNotifier));
124                } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
125                    switch (TelephonyManager.getLteOnCdmaModeStatic()) {
126                        case PhoneConstants.LTE_ON_CDMA_TRUE:
127                            Rlog.i(LOG_TAG, "Creating CDMALTEPhone");
128                            sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,
129                                sCommandsInterface, sPhoneNotifier));
130                            break;
131                        case PhoneConstants.LTE_ON_CDMA_FALSE:
132                        default:
133                            Rlog.i(LOG_TAG, "Creating CDMAPhone");
134                            sProxyPhone = new PhoneProxy(new CDMAPhone(context,
135                                    sCommandsInterface, sPhoneNotifier));
136                            break;
137                    }
138                }
139
140                // Ensure that we have a default SMS app. Requesting the app with
141                // updateIfNeeded set to true is enough to configure a default SMS app.
142                ComponentName componentName =
143                        SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */);
144                String packageName = "NONE";
145                if (componentName != null) {
146                    packageName = componentName.getPackageName();
147                }
148                Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);
149
150                sMadeDefaults = true;
151            }
152        }
153    }
154
155    public static Phone getDefaultPhone() {
156        if (sLooper != Looper.myLooper()) {
157            throw new RuntimeException(
158                "PhoneFactory.getDefaultPhone must be called from Looper thread");
159        }
160
161        if (!sMadeDefaults) {
162            throw new IllegalStateException("Default phones haven't been made yet!");
163        }
164       return sProxyPhone;
165    }
166
167    public static Phone getCdmaPhone() {
168        Phone phone;
169        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
170            switch (TelephonyManager.getLteOnCdmaModeStatic()) {
171                case PhoneConstants.LTE_ON_CDMA_TRUE: {
172                    phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier);
173                    break;
174                }
175                case PhoneConstants.LTE_ON_CDMA_FALSE:
176                case PhoneConstants.LTE_ON_CDMA_UNKNOWN:
177                default: {
178                    phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
179                    break;
180                }
181            }
182        }
183        return phone;
184    }
185
186    public static Phone getGsmPhone() {
187        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
188            Phone phone = new GSMPhone(sContext, sCommandsInterface, sPhoneNotifier);
189            return phone;
190        }
191    }
192
193    /**
194     * Makes a {@link SipPhone} object.
195     * @param sipUri the local SIP URI the phone runs on
196     * @return the {@code SipPhone} object or null if the SIP URI is not valid
197     */
198    public static SipPhone makeSipPhone(String sipUri) {
199        return SipPhoneFactory.makePhone(sipUri, sContext, sPhoneNotifier);
200    }
201}
202