CDMALTEPhone.java revision 80bc1e5a6f0bd91b886351997b797e01732c1c67
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.app.ActivityManagerNative;
20import android.content.ContentValues;
21import android.content.Context;
22import android.content.Intent;
23import android.content.SharedPreferences;
24import android.database.SQLException;
25import android.net.Uri;
26import android.os.AsyncResult;
27import android.os.Handler;
28import android.os.Message;
29import android.os.UserHandle;
30import android.preference.PreferenceManager;
31import android.os.PowerManager;
32import android.os.SystemProperties;
33import android.provider.Telephony;
34import android.text.TextUtils;
35import android.telephony.SubscriptionManager;
36import android.telephony.Rlog;
37
38import com.android.internal.telephony.CommandsInterface;
39import android.telephony.TelephonyManager;
40
41import com.android.internal.telephony.dataconnection.DcTracker;
42import com.android.internal.telephony.MccTable;
43import com.android.internal.telephony.OperatorInfo;
44import com.android.internal.telephony.PhoneConstants;
45import com.android.internal.telephony.PhoneNotifier;
46import com.android.internal.telephony.PhoneProxy;
47import com.android.internal.telephony.PhoneFactory;
48import com.android.internal.telephony.PhoneSubInfo;
49import com.android.internal.telephony.SMSDispatcher;
50import com.android.internal.telephony.SmsBroadcastUndelivered;
51import com.android.internal.telephony.Subscription;
52import com.android.internal.telephony.gsm.GsmSMSDispatcher;
53import com.android.internal.telephony.gsm.SmsMessage;
54import com.android.internal.telephony.uicc.IccRecords;
55import com.android.internal.telephony.uicc.IsimRecords;
56import com.android.internal.telephony.uicc.IsimUiccRecords;
57import com.android.internal.telephony.uicc.RuimRecords;
58import com.android.internal.telephony.uicc.SIMRecords;
59import com.android.internal.telephony.uicc.UiccCardApplication;
60import com.android.internal.telephony.uicc.UiccController;
61import com.android.internal.telephony.ServiceStateTracker;
62import com.android.internal.telephony.TelephonyIntents;
63import com.android.internal.telephony.TelephonyProperties;
64
65import java.io.FileDescriptor;
66import java.io.PrintWriter;
67
68import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
69import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
70import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
71
72import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_ACTIVATED;
73import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_DEACTIVATED;
74
75public class CDMALTEPhone extends CDMAPhone {
76    static final String LOG_LTE_TAG = "CDMALTEPhone";
77    private static final boolean DBG = true;
78
79    /** CdmaLtePhone in addition to RuimRecords available from
80     * PhoneBase needs access to SIMRecords and IsimUiccRecords
81     */
82    private SIMRecords mSimRecords;
83    private IsimUiccRecords mIsimUiccRecords;
84
85    // Constructors
86    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
87            int phoneId) {
88        this(context, ci, notifier, false, phoneId);
89    }
90
91    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
92            boolean unitTestMode, int phoneId) {
93        super(context, ci, notifier, phoneId);
94
95        Rlog.d(LOG_TAG, "CDMALTEPhone: constructor: sub = " + mPhoneId);
96
97        mDcTracker = new DcTracker(this);
98
99    }
100
101    // Constructors
102    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
103        super(context, ci, notifier, false);
104    }
105
106    @Override
107    public void handleMessage (Message msg) {
108        switch (msg.what) {
109            case EVENT_SUBSCRIPTION_ACTIVATED:
110                log("EVENT_SUBSCRIPTION_ACTIVATED");
111                onSubscriptionActivated();
112                break;
113
114            case EVENT_SUBSCRIPTION_DEACTIVATED:
115                log("EVENT_SUBSCRIPTION_DEACTIVATED");
116                onSubscriptionDeactivated();
117                break;
118
119            default:
120                super.handleMessage(msg);
121        }
122    }
123
124    @Override
125    protected void initSstIcc() {
126        mSST = new CdmaLteServiceStateTracker(this);
127    }
128
129    @Override
130    public void dispose() {
131        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
132            super.dispose();
133        }
134    }
135
136    @Override
137    public void removeReferences() {
138        super.removeReferences();
139    }
140
141    @Override
142    public PhoneConstants.DataState getDataConnectionState(String apnType) {
143        PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
144
145        if (mSST == null) {
146            // Radio Technology Change is ongoing, dispose() and
147            // removeReferences() have already been called
148
149            ret = PhoneConstants.DataState.DISCONNECTED;
150        } else if (mDcTracker.isApnTypeEnabled(apnType) == false) {
151            ret = PhoneConstants.DataState.DISCONNECTED;
152        } else {
153            switch (mDcTracker.getState(apnType)) {
154                case RETRYING:
155                case FAILED:
156                case IDLE:
157                    ret = PhoneConstants.DataState.DISCONNECTED;
158                    break;
159
160                case CONNECTED:
161                case DISCONNECTING:
162                    if (mCT.mState != PhoneConstants.State.IDLE &&
163                            !mSST.isConcurrentVoiceAndDataAllowed()) {
164                        ret = PhoneConstants.DataState.SUSPENDED;
165                    } else {
166                        ret = PhoneConstants.DataState.CONNECTED;
167                    }
168                    break;
169
170                case CONNECTING:
171                case SCANNING:
172                    ret = PhoneConstants.DataState.CONNECTING;
173                    break;
174            }
175        }
176
177        log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
178        return ret;
179    }
180
181    /**
182     * Sets the "current" field in the telephony provider according to the
183     * build-time operator numeric property
184     *
185     * @return true for success; false otherwise.
186     */
187    @Override
188    boolean updateCurrentCarrierInProvider(String operatorNumeric) {
189        boolean retVal;
190        if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) == null) {
191            if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null");
192            retVal = super.updateCurrentCarrierInProvider(operatorNumeric);
193        } else {
194            if (DBG) log("updateCurrentCarrierInProvider not updated");
195            retVal = true;
196        }
197        if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal);
198        return retVal;
199    }
200
201    @Override
202    public boolean updateCurrentCarrierInProvider() {
203        long currentDds = SubscriptionManager.getDefaultDataSubId();
204        String operatorNumeric = getOperatorNumeric();
205
206        Rlog.d(LOG_TAG, "updateCurrentCarrierInProvider: mSubscription = " + getSubId()
207                + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric);
208
209        if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) {
210            try {
211                Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
212                ContentValues map = new ContentValues();
213                map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
214                mContext.getContentResolver().insert(uri, map);
215                return true;
216            } catch (SQLException e) {
217                Rlog.e(LOG_TAG, "Can't store current operator", e);
218            }
219        }
220        return false;
221    }
222
223    // return IMSI from USIM as subscriber ID.
224    @Override
225    public String getSubscriberId() {
226        return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
227    }
228
229    // return GID1 from USIM
230    @Override
231    public String getGroupIdLevel1() {
232        return (mSimRecords != null) ? mSimRecords.getGid1() : "";
233    }
234
235    @Override
236    public String getImei() {
237        return mImei;
238    }
239
240    @Override
241    public String getDeviceSvn() {
242        return mImeiSv;
243    }
244
245    @Override
246    public IsimRecords getIsimRecords() {
247        return mIsimUiccRecords;
248    }
249
250    @Override
251    public String getMsisdn() {
252        return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
253    }
254
255    @Override
256    public void getAvailableNetworks(Message response) {
257        mCi.getAvailableNetworks(response);
258    }
259
260    @Override
261    protected void onUpdateIccAvailability() {
262        if (mUiccController == null ) {
263            return;
264        }
265
266        // Update IsimRecords
267        UiccCardApplication newUiccApplication =
268                mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS);
269        IsimUiccRecords newIsimUiccRecords = null;
270
271        if (newUiccApplication != null) {
272            newIsimUiccRecords = (IsimUiccRecords) newUiccApplication.getIccRecords();
273        }
274        mIsimUiccRecords = newIsimUiccRecords;
275
276        // Update UsimRecords
277        newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
278        SIMRecords newSimRecords = null;
279        if (newUiccApplication != null) {
280            newSimRecords = (SIMRecords) newUiccApplication.getIccRecords();
281        }
282        mSimRecords = newSimRecords;
283
284        super.onUpdateIccAvailability();
285    }
286
287    @Override
288    protected void init(Context context, PhoneNotifier notifier) {
289        mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
290        mCT = new CdmaCallTracker(this);
291        mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCi, this,
292                EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
293        mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
294        mSubInfo = new PhoneSubInfo(this);
295        mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
296
297        mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
298        mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
299        mCi.registerForOn(this, EVENT_RADIO_ON, null);
300        mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
301        mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
302        mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
303        mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE,
304                null);
305
306        PowerManager pm
307            = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
308        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG);
309
310        // This is needed to handle phone process crashes
311        String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
312        mIsPhoneInEcmState = inEcm.equals("true");
313        if (mIsPhoneInEcmState) {
314            // Send a message which will invoke handleExitEmergencyCallbackMode
315            mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
316        }
317
318        // get the string that specifies the carrier OTA Sp number
319        mCarrierOtaSpNumSchema = SystemProperties.get(
320                TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,"");
321
322        // Notify voicemails.
323        notifier.notifyMessageWaitingChanged(this);
324        setProperties();
325    }
326
327    private void onSubscriptionActivated() {
328//        mSubscriptionData = SubscriptionManager.getCurrentSubscription(mSubscription);
329
330        log("SUBSCRIPTION ACTIVATED : slotId : " + mSubscriptionData.slotId
331                + " appid : " + mSubscriptionData.m3gpp2Index
332                + " subId : " + mSubscriptionData.subId
333                + " subStatus : " + mSubscriptionData.subStatus);
334
335        // Make sure properties are set for proper subscription.
336        setProperties();
337
338        onUpdateIccAvailability();
339        mSST.sendMessage(mSST.obtainMessage(ServiceStateTracker.EVENT_ICC_CHANGED));
340        ((CdmaLteServiceStateTracker)mSST).updateCdmaSubscription();
341        ((DcTracker)mDcTracker).updateRecords();
342    }
343
344    private void onSubscriptionDeactivated() {
345        log("SUBSCRIPTION DEACTIVATED");
346        // resetSubSpecifics
347        mSubscriptionData = null;
348    }
349
350    // Set the properties per subscription
351    private void setProperties() {
352        //Change the system property
353        setSystemProperty(TelephonyProperties.CURRENT_ACTIVE_PHONE,
354                new Integer(PhoneConstants.PHONE_TYPE_CDMA).toString());
355        // Sets operator alpha property by retrieving from build-time system property
356        String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
357        if (!TextUtils.isEmpty(operatorAlpha)) {
358            setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
359        }
360
361        // Sets operator numeric property by retrieving from build-time system property
362        String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
363        log("update icc_operator_numeric=" + operatorNumeric);
364        if (!TextUtils.isEmpty(operatorNumeric)) {
365            setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
366            // Sets iso country property by retrieving from build-time system property
367            setIsoCountryProperty(operatorNumeric);
368            // Updates MCC MNC device configuration information
369            log("update mccmnc=" + operatorNumeric);
370            MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
371        }
372        // Sets current entry in the telephony carrier table
373        updateCurrentCarrierInProvider();
374    }
375
376    @Override
377    public void setSystemProperty(String property, String value) {
378        if(getUnitTestMode()) {
379            return;
380        }
381        TelephonyManager.setTelephonyProperty(property, getSubId(), value);
382    }
383
384    public String getSystemProperty(String property, String defValue) {
385        if(getUnitTestMode()) {
386            return null;
387        }
388        return TelephonyManager.getTelephonyProperty(property, getSubId(), defValue);
389    }
390
391    public void updateDataConnectionTracker() {
392        ((DcTracker)mDcTracker).update();
393    }
394
395    public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
396        ((DcTracker)mDcTracker)
397                .setInternalDataEnabled(enable, onCompleteMsg);
398    }
399
400    public boolean setInternalDataEnabledFlag(boolean enable) {
401       return ((DcTracker)mDcTracker)
402                .setInternalDataEnabledFlag(enable);
403    }
404
405    /**
406     * @return operator numeric.
407     */
408    public String getOperatorNumeric() {
409        String operatorNumeric = null;
410        IccRecords curIccRecords = null;
411        if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
412            operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
413        } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM) {
414            curIccRecords = mSimRecords;
415            if (curIccRecords != null) {
416                operatorNumeric = curIccRecords.getOperatorNumeric();
417            } else {
418                curIccRecords = mIccRecords.get();
419                if (curIccRecords != null && (curIccRecords instanceof RuimRecords)) {
420                    RuimRecords csim = (RuimRecords) curIccRecords;
421                    operatorNumeric = csim.getRUIMOperatorNumeric();
422                }
423            }
424        }
425        if (operatorNumeric == null) {
426            Rlog.e(LOG_TAG, "getOperatorNumeric: Cannot retrieve operatorNumeric:"
427                    + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + " mIccRecords = "
428                    + ((curIccRecords != null) ? curIccRecords.getRecordsLoaded() : null));
429        }
430
431        Rlog.d(LOG_TAG, "getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource
432                + " operatorNumeric = " + operatorNumeric);
433
434        return operatorNumeric;
435    }
436    public void registerForAllDataDisconnected(Handler h, int what, Object obj) {
437        ((DcTracker)mDcTracker)
438               .registerForAllDataDisconnected(h, what, obj);
439    }
440
441    public void unregisterForAllDataDisconnected(Handler h) {
442        ((DcTracker)mDcTracker)
443                .unregisterForAllDataDisconnected(h);
444    }
445
446    @Override
447    protected void log(String s) {
448            Rlog.d(LOG_LTE_TAG, s);
449    }
450
451    protected void loge(String s) {
452            Rlog.e(LOG_LTE_TAG, s);
453    }
454
455    protected void loge(String s, Throwable e) {
456        Rlog.e(LOG_LTE_TAG, s, e);
457    }
458
459    @Override
460    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
461        pw.println("CDMALTEPhone extends:");
462        super.dump(fd, pw, args);
463    }
464}
465