CDMALTEPhone.java revision c6bbea82bf74ebb492508199b6f3e172b7ce860a
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 (mDcTracker.isApnTypeEnabled(apnType) == false) {
124            ret = PhoneConstants.DataState.DISCONNECTED;
125        } else {
126            switch (mDcTracker.getState(apnType)) {
127                case RETRYING:
128                case FAILED:
129                case IDLE:
130                    ret = PhoneConstants.DataState.DISCONNECTED;
131                    break;
132
133                case CONNECTED:
134                case DISCONNECTING:
135                    if (mCT.mState != PhoneConstants.State.IDLE &&
136                            !mSST.isConcurrentVoiceAndDataAllowed()) {
137                        ret = PhoneConstants.DataState.SUSPENDED;
138                    } else {
139                        ret = PhoneConstants.DataState.CONNECTED;
140                    }
141                    break;
142
143                case CONNECTING:
144                case SCANNING:
145                    ret = PhoneConstants.DataState.CONNECTING;
146                    break;
147            }
148        }
149
150        log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
151        return ret;
152    }
153
154    @Override
155    public void
156    selectNetworkManually(OperatorInfo network,
157            Message response) {
158        // wrap the response message in our own message along with
159        // the operator's id.
160        NetworkSelectMessage nsm = new NetworkSelectMessage();
161        nsm.message = response;
162        nsm.operatorNumeric = network.getOperatorNumeric();
163        nsm.operatorAlphaLong = network.getOperatorAlphaLong();
164
165        // get the message
166        Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
167
168        mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
169    }
170
171    /**
172     * Used to track the settings upon completion of the network change.
173     */
174    private void handleSetSelectNetwork(AsyncResult ar) {
175        // look for our wrapper within the asyncresult, skip the rest if it
176        // is null.
177        if (!(ar.userObj instanceof NetworkSelectMessage)) {
178            loge("unexpected result from user object.");
179            return;
180        }
181
182        NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
183
184        // found the object, now we send off the message we had originally
185        // attached to the request.
186        if (nsm.message != null) {
187            if (DBG) log("sending original message to recipient");
188            AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
189            nsm.message.sendToTarget();
190        }
191
192        // open the shared preferences editor, and write the value.
193        // nsm.operatorNumeric is "" if we're in automatic.selection.
194        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
195        SharedPreferences.Editor editor = sp.edit();
196        editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric);
197        editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong);
198
199        // commit and log the result.
200        if (! editor.commit()) {
201            loge("failed to commit network selection preference");
202        }
203
204    }
205
206    @Override
207    public boolean updateCurrentCarrierInProvider() {
208        if (mSimRecords != null) {
209            try {
210                Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
211                ContentValues map = new ContentValues();
212                String operatorNumeric = mSimRecords.getOperatorNumeric();
213                map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
214                if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" +
215                        operatorNumeric);
216                mContext.getContentResolver().insert(uri, map);
217                return true;
218            } catch (SQLException e) {
219                loge("Can't store current operator ret false", e);
220            }
221        } else {
222            if (DBG) log("updateCurrentCarrierInProvider mIccRecords == null ret false");
223        }
224        return false;
225    }
226
227    // return IMSI from USIM as subscriber ID.
228    @Override
229    public String getSubscriberId() {
230        return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
231    }
232
233    @Override
234    public String getImei() {
235        return mImei;
236    }
237
238    @Override
239    public String getDeviceSvn() {
240        return mImeiSv;
241    }
242
243    @Override
244    public IsimRecords getIsimRecords() {
245        return mIsimUiccRecords;
246    }
247
248    @Override
249    public String getMsisdn() {
250        return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
251    }
252
253    @Override
254    public void getAvailableNetworks(Message response) {
255        mCi.getAvailableNetworks(response);
256    }
257
258    @Override
259    public void requestIsimAuthentication(String nonce, Message result) {
260        mCi.requestIsimAuthentication(nonce, result);
261    }
262
263    @Override
264    protected void onUpdateIccAvailability() {
265        if (mUiccController == null ) {
266            return;
267        }
268
269        // Update IsimRecords
270        UiccCardApplication newUiccApplication =
271                mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS);
272        IsimUiccRecords newIsimUiccRecords = null;
273
274        if (newUiccApplication != null) {
275            newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords();
276        }
277        mIsimUiccRecords = newIsimUiccRecords;
278
279        // Update UsimRecords
280        newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
281        SIMRecords newSimRecords = null;
282        if (newUiccApplication != null) {
283            newSimRecords = (SIMRecords)newUiccApplication.getIccRecords();
284        }
285        if (mSimRecords != newSimRecords) {
286            if (mSimRecords != null) {
287                log("Removing stale SIMRecords object.");
288                mSimRecords.unregisterForNewSms(this);
289                mSimRecords = null;
290            }
291            if (newSimRecords != null) {
292                log("New SIMRecords found");
293                mSimRecords = newSimRecords;
294                mSimRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
295            }
296        }
297
298        super.onUpdateIccAvailability();
299    }
300
301    @Override
302    protected void log(String s) {
303            Rlog.d(LOG_LTE_TAG, s);
304    }
305
306    protected void loge(String s) {
307            Rlog.e(LOG_LTE_TAG, s);
308    }
309
310    protected void loge(String s, Throwable e) {
311        Rlog.e(LOG_LTE_TAG, s, e);
312}
313
314    @Override
315    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
316        pw.println("CDMALTEPhone extends:");
317        super.dump(fd, pw, args);
318        pw.println(" m3gppSMS=" + m3gppSMS);
319    }
320}
321