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