CDMALTEPhone.java revision cbaa45bbf2cab852b6c9c3a887e9f803d4e857ea
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.state != 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        mCM.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    @Override
233    public String getImei() {
234        return mImei;
235    }
236
237    @Override
238    public String getDeviceSvn() {
239        return mImeiSv;
240    }
241
242    @Override
243    public IsimRecords getIsimRecords() {
244        return mIsimUiccRecords;
245    }
246
247    @Override
248    public String getMsisdn() {
249        return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
250    }
251
252    @Override
253    public void getAvailableNetworks(Message response) {
254        mCM.getAvailableNetworks(response);
255    }
256
257    @Override
258    public void requestIsimAuthentication(String nonce, Message result) {
259        mCM.requestIsimAuthentication(nonce, result);
260    }
261
262    @Override
263    protected void onUpdateIccAvailability() {
264        if (mUiccController == null ) {
265            return;
266        }
267
268        // Update IsimRecords
269        UiccCardApplication newUiccApplication =
270                mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS);
271        IsimUiccRecords newIsimUiccRecords = null;
272
273        if (newUiccApplication != null) {
274            newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords();
275        }
276        mIsimUiccRecords = newIsimUiccRecords;
277
278        // Update UsimRecords
279        newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
280        SIMRecords newSimRecords = null;
281        if (newUiccApplication != null) {
282            newSimRecords = (SIMRecords)newUiccApplication.getIccRecords();
283        }
284        if (mSimRecords != newSimRecords) {
285            if (mSimRecords != null) {
286                log("Removing stale SIMRecords object.");
287                mSimRecords.unregisterForNewSms(this);
288                mSimRecords = null;
289            }
290            if (newSimRecords != null) {
291                log("New SIMRecords found");
292                mSimRecords = newSimRecords;
293                mSimRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
294            }
295        }
296
297        super.onUpdateIccAvailability();
298    }
299
300    @Override
301    protected void log(String s) {
302            Rlog.d(LOG_LTE_TAG, s);
303    }
304
305    protected void loge(String s) {
306            Rlog.e(LOG_LTE_TAG, s);
307    }
308
309    protected void loge(String s, Throwable e) {
310        Rlog.e(LOG_LTE_TAG, s, e);
311}
312
313    @Override
314    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
315        pw.println("CDMALTEPhone extends:");
316        super.dump(fd, pw, args);
317        pw.println(" m3gppSMS=" + m3gppSMS);
318    }
319}
320