CDMALTEPhone.java revision 0e4abef0d7e978d4c3dea5199f451a1c69158d03
1/*
2 * Copyright (C) 2011 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.cdma;
18
19import android.content.ContentValues;
20import android.content.Context;
21import android.content.SharedPreferences;
22import android.database.SQLException;
23import android.net.Uri;
24import android.os.AsyncResult;
25import android.os.Message;
26import android.preference.PreferenceManager;
27import android.provider.Telephony;
28import android.telephony.Rlog;
29
30import com.android.internal.telephony.CommandsInterface;
31import com.android.internal.telephony.OperatorInfo;
32import com.android.internal.telephony.PhoneConstants;
33import com.android.internal.telephony.PhoneNotifier;
34import com.android.internal.telephony.PhoneProxy;
35import com.android.internal.telephony.SMSDispatcher;
36import com.android.internal.telephony.gsm.GsmSMSDispatcher;
37import com.android.internal.telephony.gsm.SmsMessage;
38import com.android.internal.telephony.uicc.IsimRecords;
39import com.android.internal.telephony.uicc.IsimUiccRecords;
40import com.android.internal.telephony.uicc.SIMRecords;
41import com.android.internal.telephony.uicc.UiccCardApplication;
42import com.android.internal.telephony.uicc.UiccController;
43
44import java.io.FileDescriptor;
45import java.io.PrintWriter;
46
47public class CDMALTEPhone extends CDMAPhone {
48    static final String LOG_LTE_TAG = "CDMALTEPhone";
49    private static final boolean DBG = true;
50
51    /** Secondary SMSDispatcher for 3GPP format messages. */
52    SMSDispatcher m3gppSMS;
53
54    /** CdmaLtePhone in addition to RuimRecords available from
55     * PhoneBase needs access to SIMRecords and IsimUiccRecords
56     */
57    private SIMRecords mSimRecords;
58    private IsimUiccRecords mIsimUiccRecords;
59
60    /**
61     * Small container class used to hold information relevant to
62     * the carrier selection process. operatorNumeric can be ""
63     * if we are looking for automatic selection. operatorAlphaLong is the
64     * corresponding operator name.
65     */
66    private static class NetworkSelectMessage {
67        public Message message;
68        public String operatorNumeric;
69        public String operatorAlphaLong;
70    }
71
72    // Constructors
73    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
74        super(context, ci, notifier, false);
75        m3gppSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
76    }
77
78    @Override
79    public void handleMessage (Message msg) {
80        AsyncResult ar;
81        switch (msg.what) {
82            // handle the select network completion callbacks.
83            case EVENT_SET_NETWORK_MANUAL_COMPLETE:
84                handleSetSelectNetwork((AsyncResult) msg.obj);
85                break;
86            case EVENT_NEW_ICC_SMS:
87                ar = (AsyncResult)msg.obj;
88                m3gppSMS.dispatchMessage((SmsMessage)ar.result);
89                break;
90            default:
91                super.handleMessage(msg);
92        }
93    }
94
95    @Override
96    protected void initSstIcc() {
97        mSST = new CdmaLteServiceStateTracker(this);
98    }
99
100    @Override
101    public void dispose() {
102        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
103            super.dispose();
104            m3gppSMS.dispose();
105        }
106    }
107
108    @Override
109    public void removeReferences() {
110        super.removeReferences();
111        m3gppSMS = null;
112    }
113
114    @Override
115    public PhoneConstants.DataState getDataConnectionState(String apnType) {
116        PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
117
118        if (mSST == null) {
119            // Radio Technology Change is ongoing, dispose() and
120            // removeReferences() have already been called
121
122            ret = PhoneConstants.DataState.DISCONNECTED;
123        } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false) {
124            ret = PhoneConstants.DataState.DISCONNECTED;
125        } else {
126            switch (mDataConnectionTracker.getState(apnType)) {
127                case FAILED:
128                case IDLE:
129                    ret = PhoneConstants.DataState.DISCONNECTED;
130                    break;
131
132                case CONNECTED:
133                case DISCONNECTING:
134                    if (mCT.mState != PhoneConstants.State.IDLE &&
135                            !mSST.isConcurrentVoiceAndDataAllowed()) {
136                        ret = PhoneConstants.DataState.SUSPENDED;
137                    } else {
138                        ret = PhoneConstants.DataState.CONNECTED;
139                    }
140                    break;
141
142                case CONNECTING:
143                case SCANNING:
144                    ret = PhoneConstants.DataState.CONNECTING;
145                    break;
146            }
147        }
148
149        log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
150        return ret;
151    }
152
153    @Override
154    public void
155    selectNetworkManually(OperatorInfo network,
156            Message response) {
157        // wrap the response message in our own message along with
158        // the operator's id.
159        NetworkSelectMessage nsm = new NetworkSelectMessage();
160        nsm.message = response;
161        nsm.operatorNumeric = network.getOperatorNumeric();
162        nsm.operatorAlphaLong = network.getOperatorAlphaLong();
163
164        // get the message
165        Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
166
167        mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
168    }
169
170    /**
171     * Used to track the settings upon completion of the network change.
172     */
173    private void handleSetSelectNetwork(AsyncResult ar) {
174        // look for our wrapper within the asyncresult, skip the rest if it
175        // is null.
176        if (!(ar.userObj instanceof NetworkSelectMessage)) {
177            loge("unexpected result from user object.");
178            return;
179        }
180
181        NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
182
183        // found the object, now we send off the message we had originally
184        // attached to the request.
185        if (nsm.message != null) {
186            if (DBG) log("sending original message to recipient");
187            AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
188            nsm.message.sendToTarget();
189        }
190
191        // open the shared preferences editor, and write the value.
192        // nsm.operatorNumeric is "" if we're in automatic.selection.
193        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
194        SharedPreferences.Editor editor = sp.edit();
195        editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric);
196        editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong);
197
198        // commit and log the result.
199        if (! editor.commit()) {
200            loge("failed to commit network selection preference");
201        }
202
203    }
204
205    @Override
206    public boolean updateCurrentCarrierInProvider() {
207        if (mSimRecords != null) {
208            try {
209                Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
210                ContentValues map = new ContentValues();
211                String operatorNumeric = mSimRecords.getOperatorNumeric();
212                map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
213                if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" +
214                        operatorNumeric);
215                mContext.getContentResolver().insert(uri, map);
216                return true;
217            } catch (SQLException e) {
218                loge("Can't store current operator ret false", e);
219            }
220        } else {
221            if (DBG) log("updateCurrentCarrierInProvider mIccRecords == null ret false");
222        }
223        return false;
224    }
225
226    // return IMSI from USIM as subscriber ID.
227    @Override
228    public String getSubscriberId() {
229        return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
230    }
231
232    // return GID1 from USIM
233    @Override
234    public String getGroupIdLevel1() {
235        return (mSimRecords != null) ? mSimRecords.getGid1() : "";
236    }
237
238    @Override
239    public String getImei() {
240        return mImei;
241    }
242
243    @Override
244    public String getDeviceSvn() {
245        return mImeiSv;
246    }
247
248    @Override
249    public IsimRecords getIsimRecords() {
250        return mIsimUiccRecords;
251    }
252
253    @Override
254    public String getMsisdn() {
255        return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
256    }
257
258    @Override
259    public void getAvailableNetworks(Message response) {
260        mCi.getAvailableNetworks(response);
261    }
262
263    @Override
264    public void requestIsimAuthentication(String nonce, Message result) {
265        mCi.requestIsimAuthentication(nonce, result);
266    }
267
268    @Override
269    protected void onUpdateIccAvailability() {
270        if (mUiccController == null ) {
271            return;
272        }
273
274        // Update IsimRecords
275        UiccCardApplication newUiccApplication =
276                mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS);
277        IsimUiccRecords newIsimUiccRecords = null;
278
279        if (newUiccApplication != null) {
280            newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords();
281        }
282        mIsimUiccRecords = newIsimUiccRecords;
283
284        // Update UsimRecords
285        newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
286        SIMRecords newSimRecords = null;
287        if (newUiccApplication != null) {
288            newSimRecords = (SIMRecords)newUiccApplication.getIccRecords();
289        }
290        if (mSimRecords != newSimRecords) {
291            if (mSimRecords != null) {
292                log("Removing stale SIMRecords object.");
293                mSimRecords.unregisterForNewSms(this);
294                mSimRecords = null;
295            }
296            if (newSimRecords != null) {
297                log("New SIMRecords found");
298                mSimRecords = newSimRecords;
299                mSimRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
300            }
301        }
302
303        super.onUpdateIccAvailability();
304    }
305
306    @Override
307    protected void log(String s) {
308            Rlog.d(LOG_LTE_TAG, s);
309    }
310
311    protected void loge(String s) {
312            Rlog.e(LOG_LTE_TAG, s);
313    }
314
315    protected void loge(String s, Throwable e) {
316        Rlog.e(LOG_LTE_TAG, s, e);
317}
318
319    @Override
320    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
321        pw.println("CDMALTEPhone extends:");
322        super.dump(fd, pw, args);
323        pw.println(" m3gppSMS=" + m3gppSMS);
324    }
325}
326