CDMALTEPhone.java revision b93bb3538c55f173f94a4ee7510d9d1521d8f731
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.IsimRecords;
55import com.android.internal.telephony.uicc.IsimUiccRecords;
56import com.android.internal.telephony.uicc.SIMRecords;
57import com.android.internal.telephony.uicc.UiccCardApplication;
58import com.android.internal.telephony.uicc.UiccController;
59import com.android.internal.telephony.ServiceStateTracker;
60import com.android.internal.telephony.TelephonyIntents;
61import com.android.internal.telephony.TelephonyProperties;
62
63import java.io.FileDescriptor;
64import java.io.PrintWriter;
65
66import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
67import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
68import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
69
70import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_ACTIVATED;
71import static com.android.internal.telephony.PhoneConstants.EVENT_SUBSCRIPTION_DEACTIVATED;
72
73public class CDMALTEPhone extends CDMAPhone {
74    static final String LOG_LTE_TAG = "CDMALTEPhone";
75    private static final boolean DBG = true;
76
77    /** CdmaLtePhone in addition to RuimRecords available from
78     * PhoneBase needs access to SIMRecords and IsimUiccRecords
79     */
80    private SIMRecords mSimRecords;
81    private IsimUiccRecords mIsimUiccRecords;
82
83    // Constructors
84    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
85            int phoneId) {
86        this(context, ci, notifier, false, phoneId);
87    }
88
89    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
90            boolean unitTestMode, int phoneId) {
91        super(context, ci, notifier, phoneId);
92
93        Rlog.d(LOG_TAG, "CDMALTEPhone: constructor: sub = " + mPhoneId);
94
95        mDcTracker = new DcTracker(this);
96
97    }
98
99    // Constructors
100    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
101        super(context, ci, notifier, false);
102    }
103
104    @Override
105    public void handleMessage (Message msg) {
106        switch (msg.what) {
107            case EVENT_SUBSCRIPTION_ACTIVATED:
108                log("EVENT_SUBSCRIPTION_ACTIVATED");
109                onSubscriptionActivated();
110                break;
111
112            case EVENT_SUBSCRIPTION_DEACTIVATED:
113                log("EVENT_SUBSCRIPTION_DEACTIVATED");
114                onSubscriptionDeactivated();
115                break;
116
117            default:
118                super.handleMessage(msg);
119        }
120    }
121
122    @Override
123    protected void initSstIcc() {
124        mSST = new CdmaLteServiceStateTracker(this);
125    }
126
127    @Override
128    public void dispose() {
129        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
130            super.dispose();
131        }
132    }
133
134    @Override
135    public void removeReferences() {
136        super.removeReferences();
137    }
138
139    @Override
140    public PhoneConstants.DataState getDataConnectionState(String apnType) {
141        PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
142
143        if (mSST == null) {
144            // Radio Technology Change is ongoing, dispose() and
145            // removeReferences() have already been called
146
147            ret = PhoneConstants.DataState.DISCONNECTED;
148        } else if (mDcTracker.isApnTypeEnabled(apnType) == false) {
149            ret = PhoneConstants.DataState.DISCONNECTED;
150        } else {
151            switch (mDcTracker.getState(apnType)) {
152                case RETRYING:
153                case FAILED:
154                case IDLE:
155                    ret = PhoneConstants.DataState.DISCONNECTED;
156                    break;
157
158                case CONNECTED:
159                case DISCONNECTING:
160                    if (mCT.mState != PhoneConstants.State.IDLE &&
161                            !mSST.isConcurrentVoiceAndDataAllowed()) {
162                        ret = PhoneConstants.DataState.SUSPENDED;
163                    } else {
164                        ret = PhoneConstants.DataState.CONNECTED;
165                    }
166                    break;
167
168                case CONNECTING:
169                case SCANNING:
170                    ret = PhoneConstants.DataState.CONNECTING;
171                    break;
172            }
173        }
174
175        log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
176        return ret;
177    }
178
179    /**
180     * Sets the "current" field in the telephony provider according to the
181     * build-time operator numeric property
182     *
183     * @return true for success; false otherwise.
184     */
185    @Override
186    boolean updateCurrentCarrierInProvider(String operatorNumeric) {
187        boolean retVal;
188        if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) == null) {
189            if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null");
190            retVal = super.updateCurrentCarrierInProvider(operatorNumeric);
191        } else {
192            if (DBG) log("updateCurrentCarrierInProvider not updated");
193            retVal = true;
194        }
195        if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal);
196        return retVal;
197    }
198
199    @Override
200    public boolean updateCurrentCarrierInProvider() {
201        long currentDds = SubscriptionManager.getDefaultDataSubId();
202        String operatorNumeric = getOperatorNumeric();
203
204        Rlog.d(LOG_TAG, "updateCurrentCarrierInProvider: mSubscription = " + getSubId()
205                + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric);
206
207        if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) {
208            try {
209                Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
210                ContentValues map = new ContentValues();
211                map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
212                mContext.getContentResolver().insert(uri, map);
213                return true;
214            } catch (SQLException e) {
215                Rlog.e(LOG_TAG, "Can't store current operator", e);
216            }
217        }
218        return false;
219    }
220
221    // return IMSI from USIM as subscriber ID.
222    @Override
223    public String getSubscriberId() {
224        return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
225    }
226
227    // return GID1 from USIM
228    @Override
229    public String getGroupIdLevel1() {
230        return (mSimRecords != null) ? mSimRecords.getGid1() : "";
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    protected void onUpdateIccAvailability() {
260        if (mUiccController == null ) {
261            return;
262        }
263
264        UiccCardApplication newUiccApplication = getUiccCardApplication();
265
266        UiccCardApplication app = mUiccApplication.get();
267        if (app != newUiccApplication) {
268            if (app != null) {
269                log("Removing stale icc objects.");
270                if (mIccRecords.get() != null) {
271                    unregisterForRuimRecordEvents();
272                }
273                mIccRecords.set(null);
274                mUiccApplication.set(null);
275            }
276            if (newUiccApplication != null) {
277                log("New Uicc application found");
278                mUiccApplication.set(newUiccApplication);
279                mIccRecords.set(newUiccApplication.getIccRecords());
280                registerForRuimRecordEvents();
281            }
282        }
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    protected UiccCardApplication getUiccCardApplication() {
378            return  mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
379    }
380
381    @Override
382    public void setSystemProperty(String property, String value) {
383        if(getUnitTestMode()) {
384            return;
385        }
386        TelephonyManager.setTelephonyProperty(property, getSubId(), value);
387    }
388
389    public String getSystemProperty(String property, String defValue) {
390        if(getUnitTestMode()) {
391            return null;
392        }
393        return TelephonyManager.getTelephonyProperty(property, getSubId(), defValue);
394    }
395
396    public void updateDataConnectionTracker() {
397        ((DcTracker)mDcTracker).update();
398    }
399
400    public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
401        ((DcTracker)mDcTracker)
402                .setInternalDataEnabled(enable, onCompleteMsg);
403    }
404
405    public boolean setInternalDataEnabledFlag(boolean enable) {
406       return ((DcTracker)mDcTracker)
407                .setInternalDataEnabledFlag(enable);
408    }
409
410    /**
411     * @return operator numeric.
412     */
413    public String getOperatorNumeric() {
414        String operatorNumeric = null;
415
416        if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
417            operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
418        } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM
419                && mIccRecords != null && mIccRecords.get() != null) {
420            operatorNumeric = mIccRecords.get().getOperatorNumeric();
421        } else {
422            Rlog.e(LOG_TAG, "getOperatorNumeric: Cannot retrieve operatorNumeric:"
423                    + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + " mIccRecords = "
424                    + ((mIccRecords != null) && (mIccRecords.get() != null)
425                        ? mIccRecords.get().getRecordsLoaded()
426                        : null));
427        }
428
429        Rlog.d(LOG_TAG, "getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource
430                + " operatorNumeric = " + operatorNumeric);
431
432        return operatorNumeric;
433    }
434    public void registerForAllDataDisconnected(Handler h, int what, Object obj) {
435        ((DcTracker)mDcTracker)
436               .registerForAllDataDisconnected(h, what, obj);
437    }
438
439    public void unregisterForAllDataDisconnected(Handler h) {
440        ((DcTracker)mDcTracker)
441                .unregisterForAllDataDisconnected(h);
442    }
443
444    @Override
445    protected void log(String s) {
446            Rlog.d(LOG_LTE_TAG, s);
447    }
448
449    protected void loge(String s) {
450            Rlog.e(LOG_LTE_TAG, s);
451    }
452
453    protected void loge(String s, Throwable e) {
454        Rlog.e(LOG_LTE_TAG, s, e);
455    }
456
457    @Override
458    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
459        pw.println("CDMALTEPhone extends:");
460        super.dump(fd, pw, args);
461    }
462}
463