CDMALTEPhone.java revision a8467dd0c524787104b1ccdddc5e8af10ba729ed
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        setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
358
359        // Sets operator numeric property by retrieving from build-time system property
360        String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
361        log("update icc_operator_numeric=" + operatorNumeric);
362        setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
363        // Sets iso country property by retrieving from build-time system property
364        setIsoCountryProperty(operatorNumeric);
365        // Updates MCC MNC device configuration information
366        log("update mccmnc=" + operatorNumeric);
367        MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
368        // Sets current entry in the telephony carrier table
369        updateCurrentCarrierInProvider();
370    }
371
372    @Override
373    protected UiccCardApplication getUiccCardApplication() {
374            return  mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
375    }
376
377    @Override
378    public void setSystemProperty(String property, String value) {
379        if(getUnitTestMode()) {
380            return;
381        }
382        TelephonyManager.setTelephonyProperty(property, getSubId(), value);
383    }
384
385    public String getSystemProperty(String property, String defValue) {
386        if(getUnitTestMode()) {
387            return null;
388        }
389        return TelephonyManager.getTelephonyProperty(property, getSubId(), defValue);
390    }
391
392    public void updateDataConnectionTracker() {
393        ((DcTracker)mDcTracker).update();
394    }
395
396    public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
397        ((DcTracker)mDcTracker)
398                .setInternalDataEnabled(enable, onCompleteMsg);
399    }
400
401    public boolean setInternalDataEnabledFlag(boolean enable) {
402       return ((DcTracker)mDcTracker)
403                .setInternalDataEnabledFlag(enable);
404    }
405
406    /**
407     * @return operator numeric.
408     */
409    public String getOperatorNumeric() {
410        String operatorNumeric = null;
411
412        if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
413            operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
414        } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM
415                && mIccRecords != null && mIccRecords.get() != null) {
416            operatorNumeric = mIccRecords.get().getOperatorNumeric();
417        } else {
418            Rlog.e(LOG_TAG, "getOperatorNumeric: Cannot retrieve operatorNumeric:"
419                    + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + " mIccRecords = "
420                    + ((mIccRecords != null) && (mIccRecords.get() != null)
421                        ? mIccRecords.get().getRecordsLoaded()
422                        : null));
423        }
424
425        Rlog.d(LOG_TAG, "getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource
426                + " operatorNumeric = " + operatorNumeric);
427
428        return operatorNumeric;
429    }
430    public void registerForAllDataDisconnected(Handler h, int what, Object obj) {
431        ((DcTracker)mDcTracker)
432               .registerForAllDataDisconnected(h, what, obj);
433    }
434
435    public void unregisterForAllDataDisconnected(Handler h) {
436        ((DcTracker)mDcTracker)
437                .unregisterForAllDataDisconnected(h);
438    }
439
440    @Override
441    protected void log(String s) {
442            Rlog.d(LOG_LTE_TAG, s);
443    }
444
445    protected void loge(String s) {
446            Rlog.e(LOG_LTE_TAG, s);
447    }
448
449    protected void loge(String s, Throwable e) {
450        Rlog.e(LOG_LTE_TAG, s, e);
451    }
452
453    @Override
454    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
455        pw.println("CDMALTEPhone extends:");
456        super.dump(fd, pw, args);
457    }
458}
459