GsmServiceStateTracker.java revision 0825495a331bb44df395a0cdb79fab85e68db5d5
10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2006 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.gsm;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CommandException;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CommandsInterface;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.DataConnectionTracker;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.EventLogTags;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccCard;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccCardConstants;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccCardStatus;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.MccTable;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.Phone;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.RestrictedState;
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.RILConstants;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.ServiceStateTracker;
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.TelephonyIntents;
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.TelephonyProperties;
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.AlarmManager;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Notification;
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.NotificationManager;
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.BroadcastReceiver;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ContentResolver;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.IntentFilter;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.database.ContentObserver;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.PowerManager;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Registrant;
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.RegistrantList;
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemClock;
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.provider.Settings;
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.provider.Settings.SettingNotFoundException;
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState;
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.SignalStrength;
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.gsm.GsmCellLocation;
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.TextUtils;
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.EventLog;
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.TimeUtils;
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.FileDescriptor;
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.PrintWriter;
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Arrays;
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Calendar;
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Collection;
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Date;
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashSet;
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.TimeZone;
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide}
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillefinal class GsmServiceStateTracker extends ServiceStateTracker {
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String LOG_TAG = "GSM";
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final boolean DBG = true;
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GSMPhone phone;
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmCellLocation cellLoc;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmCellLocation newCellLoc;
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    int mPreferredNetworkType;
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mMaxDataCalls = 1;
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mNewMaxDataCalls = 1;
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mReasonDataDenied = -1;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mNewReasonDataDenied = -1;
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * GSM roaming status solely based on TS 27.007 7.2 CREG. Only used by
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * handlePollStateResult to store CREG roaming result.
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mGsmRoaming = false;
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Data roaming status solely based on TS 27.007 10.1.19 CGREG. Only used by
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * handlePollStateResult to store CGREG roaming result.
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mDataRoaming = false;
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Mark when service state is in emergency call only mode
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mEmergencyOnly = false;
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Sometimes we get the NITZ time before we know what country we
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * are in. Keep the time zone information from the NITZ string so
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * we can fix the time zone once know the country.
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mNeedFixZoneAfterNitz = false;
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mZoneOffset;
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mZoneDst;
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private long mZoneTime;
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mGotCountryCode = false;
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private ContentResolver cr;
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Boolean is true is setTimeFromNITZString was called */
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mNitzUpdatedTime = false;
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    String mSavedTimeZone;
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    long mSavedTime;
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    long mSavedAtTime;
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * We can't register for SIM_RECORDS_LOADED immediately because the
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * SIMRecords object may not be instantiated yet.
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mNeedToRegForSimLoaded;
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Started the recheck process after finding gprs should registered but not. */
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mStartedGprsRegCheck = false;
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Already sent the event-log for no gprs register. */
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mReportedGprsNoReg = false;
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * The Notification object given to the NotificationManager.
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Notification mNotification;
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Wake lock used while setting time of day. */
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private PowerManager.WakeLock mWakeLock;
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String WAKELOCK_TAG = "ServiceStateTracker";
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Keep track of SPN display rules, so we only broadcast intent if something changes. */
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private String curSpn = null;
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private String curPlmn = null;
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int curSpnRule = 0;
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** waiting period before recheck gprs and voice registration. */
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Notification type. */
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int PS_ENABLED = 1001;            // Access Control blocks data service
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int PS_DISABLED = 1002;           // Access Control enables data service
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CS_ENABLED = 1003;            // Access Control blocks all voice/sms service
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CS_DISABLED = 1004;           // Access Control enables all voice/sms service
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CS_NORMAL_ENABLED = 1005;     // Access Control blocks normal voice/sms service
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CS_EMERGENCY_ENABLED = 1006;  // Access Control blocks emergency call service
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Notification id. */
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int PS_NOTIFICATION = 888;  // Id to update and cancel PS restricted
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int CS_NOTIFICATION = 999;  // Id to update and cancel CS restricted
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void onReceive(Context context, Intent intent) {
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED)) {
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // update emergency string whenever locale changed
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                updateSpnDisplay();
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void onChange(boolean selfChange) {
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i("GsmServiceStateTracker", "Auto time state changed");
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            revertToNitzTime();
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private ContentObserver mAutoTimeZoneObserver = new ContentObserver(new Handler()) {
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void onChange(boolean selfChange) {
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i("GsmServiceStateTracker", "Auto time zone state changed");
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            revertToNitzTimeZone();
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public GsmServiceStateTracker(GSMPhone phone) {
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        super();
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.phone = phone;
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm = phone.mCM;
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ss = new ServiceState();
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        newSS = new ServiceState();
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cellLoc = new GsmCellLocation();
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        newCellLoc = new GsmCellLocation();
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSignalStrength = new SignalStrength();
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PowerManager powerManager =
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.setOnNITZTime(this, EVENT_NITZ_TIME, null);
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.getIccCard().registerForReady(this, EVENT_SIM_READY, null);
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // system setting property AIRPLANE_MODE_ON is set in Settings.
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int airplaneMode = Settings.System.getInt(
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                phone.getContext().getContentResolver(),
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Settings.System.AIRPLANE_MODE_ON, 0);
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mDesiredPowerState = ! (airplaneMode > 0);
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cr = phone.getContext().getContentResolver();
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cr.registerContentObserver(
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mAutoTimeObserver);
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cr.registerContentObserver(
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Settings.System.getUriFor(Settings.System.AUTO_TIME_ZONE), true,
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mAutoTimeZoneObserver);
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        setSignalStrengthDefaultValues();
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNeedToRegForSimLoaded = true;
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Monitor locale change
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        IntentFilter filter = new IntentFilter();
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.getContext().registerReceiver(mIntentReceiver, filter);
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Gsm doesn't support OTASP so its not needed
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.notifyOtaspChanged(OTASP_NOT_NEEDED);
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dispose() {
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Unregister for all events.
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unregisterForAvailable(this);
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unregisterForRadioStateChanged(this);
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unregisterForVoiceNetworkStateChanged(this);
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.getIccCard().unregisterForReady(this);
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.mIccRecords.unregisterForRecordsLoaded(this);
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unSetOnSignalStrengthUpdate(this);
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unSetOnRestrictedStateChanged(this);
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unSetOnNITZTime(this);
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cr.unregisterContentObserver(this.mAutoTimeObserver);
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cr.unregisterContentObserver(this.mAutoTimeZoneObserver);
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void finalize() {
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if(DBG) log("finalize");
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected Phone getPhone() {
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return phone;
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void handleMessage (Message msg) {
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        AsyncResult ar;
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] ints;
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String[] strings;
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Message message;
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!phone.mIsTheCurrentActivePhone) {
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG, "Received message " + msg +
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    "[" + msg.what + "] while being destroyed. Ignoring.");
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (msg.what) {
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RADIO_AVAILABLE:
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //this is unnecessary
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //setPowerStateToDesired();
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SIM_READY:
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Set the network type, in case the radio does not restore it.
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.setCurrentPreferredNetworkType();
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // The SIM is now ready i.e if it was locked
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // it has been unlocked. At this stage, the radio is already
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // powered on.
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (mNeedToRegForSimLoaded) {
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    phone.mIccRecords.registerForRecordsLoaded(this,
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            EVENT_SIM_RECORDS_LOADED, null);
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mNeedToRegForSimLoaded = false;
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                boolean skipRestoringSelection = phone.getContext().getResources().getBoolean(
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        com.android.internal.R.bool.skip_restoring_network_selection);
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!skipRestoringSelection) {
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // restore the previous network selection.
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    phone.restoreSavedNetworkSelection(null);
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollState();
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Signal strength polling stops when radio is off
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                queueNextSignalStrengthPoll();
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RADIO_STATE_CHANGED:
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // This will do nothing in the radio not
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // available case
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                setPowerStateToDesired();
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollState();
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_NETWORK_STATE_CHANGED:
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollState();
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_GET_SIGNAL_STRENGTH:
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // This callback is called when signal strength is polled
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // all by itself
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!(cm.getRadioState().isOn())) {
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Polling will continue when radio turns back on
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return;
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onSignalStrengthResult(ar);
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                queueNextSignalStrengthPoll();
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_GET_LOC_DONE:
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.exception == null) {
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    String states[] = (String[])ar.result;
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int lac = -1;
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int cid = -1;
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (states.length >= 3) {
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        try {
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (states[1] != null && states[1].length() > 0) {
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                lac = Integer.parseInt(states[1], 16);
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (states[2] != null && states[2].length() > 0) {
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                cid = Integer.parseInt(states[2], 16);
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } catch (NumberFormatException ex) {
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            Log.w(LOG_TAG, "error parsing location: " + ex);
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    cellLoc.setLacAndCid(lac, cid);
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    phone.notifyLocationChanged();
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Release any temporary cell lock, which could have been
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // acquired to allow a single-shot location update.
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                disableSingleLocationUpdate();
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_POLL_STATE_REGISTRATION:
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_POLL_STATE_GPRS:
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_POLL_STATE_OPERATOR:
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_POLL_STATE_NETWORK_SELECTION_MODE:
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                handlePollStateResult(msg.what, ar);
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_POLL_SIGNAL_STRENGTH:
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Just poll signal strength...not part of pollState()
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_NITZ_TIME:
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String nitzString = (String)((Object[])ar.result)[0];
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue();
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                setTimeFromNITZString(nitzString, nitzReceiveTime);
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SIGNAL_STRENGTH_UPDATE:
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // This is a notification from
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // CommandsInterface.setOnSignalStrengthUpdate
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // The radio is telling us about signal strength changes
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // we don't have to ask it
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                dontPollSignalStrength = true;
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onSignalStrengthResult(ar);
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SIM_RECORDS_LOADED:
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                updateSpnDisplay();
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_LOCATION_UPDATES_ENABLED:
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.exception == null) {
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    cm.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE, null));
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SET_PREFERRED_NETWORK_TYPE:
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Don't care the result, only use for dereg network (COPS=2)
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                message = obtainMessage(EVENT_RESET_PREFERRED_NETWORK_TYPE, ar.userObj);
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.setPreferredNetworkType(mPreferredNetworkType, message);
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RESET_PREFERRED_NETWORK_TYPE:
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.userObj != null) {
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    AsyncResult.forMessage(((Message) ar.userObj)).exception
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            = ar.exception;
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((Message) ar.userObj).sendToTarget();
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_GET_PREFERRED_NETWORK_TYPE:
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.exception == null) {
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mPreferredNetworkType = ((int[])ar.result)[0];
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mPreferredNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj);
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.setPreferredNetworkType(toggledNetworkType, message);
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_CHECK_REPORT_GPRS:
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ss != null && !isGprsConsistent(gprsState, ss.getState())) {
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Can't register data service while voice service is ok
4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // i.e. CREG is ok while CGREG is not
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // possible a network or baseband side error
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL,
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            ss.getOperatorNumeric(), loc != null ? loc.getCid() : -1);
4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mReportedGprsNoReg = true;
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mStartedGprsRegCheck = false;
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RESTRICTED_STATE_CHANGED:
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // This is a notification from
4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // CommandsInterface.setOnRestrictedStateChanged
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED");
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                onRestrictedStateChanged(ar);
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            default:
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                super.handleMessage(msg);
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void setPowerStateToDesired() {
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // If we want it on and it's off, turn it on
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mDesiredPowerState
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.setRadioPower(true, null);
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // If it's on and available and we want it off gracefully
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            DataConnectionTracker dcTracker = phone.mDataConnectionTracker;
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            powerOffRadioSafely(dcTracker);
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } // Otherwise, we're in the desired state
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void hangupAndPowerOff() {
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // hang up all active voice calls
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (phone.isInCall()) {
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.mCT.ringingCall.hangupIfAlive();
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.mCT.backgroundCall.hangupIfAlive();
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.mCT.foregroundCall.hangupIfAlive();
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.setRadioPower(false, null);
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void updateSpnDisplay() {
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int rule = phone.mIccRecords.getDisplayRule(ss.getOperatorNumeric());
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String spn = phone.mIccRecords.getServiceProviderName();
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String plmn = ss.getOperatorAlphaLong();
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // For emergency calls only, pass the EmergencyCallsOnly string via EXTRA_PLMN
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mEmergencyOnly && cm.getRadioState().isOn()) {
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            plmn = Resources.getSystem().
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                getText(com.android.internal.R.string.emergency_calls_only).toString();
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (DBG) log("updateSpnDisplay: emergency only and radio is on plmn='" + plmn + "'");
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (rule != curSpnRule
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                || !TextUtils.equals(spn, curSpn)
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                || !TextUtils.equals(plmn, curPlmn)) {
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean showSpn = !mEmergencyOnly && !TextUtils.isEmpty(spn)
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean showPlmn = !TextUtils.isEmpty(plmn) &&
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (DBG) {
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log(String.format("updateSpnDisplay: changed sending intent" + " rule=" + rule +
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'",
5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            showPlmn, plmn, showSpn, spn));
5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn);
5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            intent.putExtra(TelephonyIntents.EXTRA_SPN, spn);
5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.getContext().sendStickyBroadcast(intent);
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        curSpnRule = rule;
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        curSpn = spn;
5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        curPlmn = plmn;
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Handle the result of one of the pollState()-related requests
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void handlePollStateResult (int what, AsyncResult ar) {
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int ints[];
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String states[];
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Ignore stale requests from last poll
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ar.userObj != pollingContext) return;
5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ar.exception != null) {
5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CommandException.Error err=null;
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ar.exception instanceof CommandException) {
5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                err = ((CommandException)(ar.exception)).getCommandError();
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Radio has crashed or turned off
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cancelPollState();
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (!cm.getRadioState().isOn()) {
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Radio has crashed or turned off
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cancelPollState();
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                loge("RIL implementation has returned an error where it must succeed" +
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ar.exception);
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else try {
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switch (what) {
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_POLL_STATE_REGISTRATION:
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    states = (String[])ar.result;
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int lac = -1;
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int cid = -1;
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int regState = -1;
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int reasonRegStateDenied = -1;
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int psc = -1;
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (states.length > 0) {
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        try {
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            regState = Integer.parseInt(states[0]);
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (states.length >= 3) {
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                if (states[1] != null && states[1].length() > 0) {
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    lac = Integer.parseInt(states[1], 16);
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                }
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                if (states[2] != null && states[2].length() > 0) {
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    cid = Integer.parseInt(states[2], 16);
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                }
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (states.length > 14) {
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                if (states[14] != null && states[14].length() > 0) {
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    psc = Integer.parseInt(states[14], 16);
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                }
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } catch (NumberFormatException ex) {
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            loge("error parsing RegistrationState: " + ex);
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mGsmRoaming = regCodeIsRoaming(regState);
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newSS.setState (regCodeToServiceState(regState));
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (regState == 10 || regState == 12 || regState == 13 || regState == 14) {
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mEmergencyOnly = true;
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mEmergencyOnly = false;
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // LAC and CID are -1 if not avail
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newCellLoc.setLacAndCid(lac, cid);
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newCellLoc.setPsc(psc);
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_POLL_STATE_GPRS:
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    states = (String[])ar.result;
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int type = 0;
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    regState = -1;
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mNewReasonDataDenied = -1;
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mNewMaxDataCalls = 1;
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (states.length > 0) {
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        try {
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            regState = Integer.parseInt(states[0]);
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            // states[3] (if present) is the current radio technology
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (states.length >= 4 && states[3] != null) {
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                type = Integer.parseInt(states[3]);
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if ((states.length >= 5 ) && (regState == 3)) {
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                mNewReasonDataDenied = Integer.parseInt(states[4]);
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (states.length >= 6) {
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                mNewMaxDataCalls = Integer.parseInt(states[5]);
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } catch (NumberFormatException ex) {
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            loge("error parsing GprsRegistrationState: " + ex);
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newGPRSState = regCodeToServiceState(regState);
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mDataRoaming = regCodeIsRoaming(regState);
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mNewRilRadioTechnology = type;
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newSS.setRadioTechnology(type);
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_POLL_STATE_OPERATOR:
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    String opNames[] = (String[])ar.result;
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (opNames != null && opNames.length >= 3) {
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                         newSS.setOperatorName (opNames[0], opNames[1], opNames[2]);
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_POLL_STATE_NETWORK_SELECTION_MODE:
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ints = (int[])ar.result;
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newSS.setIsManualSelection(ints[0] == 1);
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (RuntimeException ex) {
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            loge("Exception while polling service state. Probably malformed RIL response." + ex);
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pollingContext[0]--;
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (pollingContext[0] == 0) {
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            /**
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *  Since the roaming states of gsm service (from +CREG) and
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *  data service (from +CGREG) could be different, the new SS
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *  is set roaming while either one is roaming.
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *  There is an exception for the above rule. The new SS is not set
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *  as roaming while gsm service reports roaming but indeed it is
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             *  not roaming between operators.
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             */
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean roaming = (mGsmRoaming || mDataRoaming);
6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (mGsmRoaming && !isRoamingBetweenOperators(mGsmRoaming, newSS)) {
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                roaming = false;
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            newSS.setRoaming(roaming);
6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            newSS.setEmergencyOnly(mEmergencyOnly);
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pollStateDone();
6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void setSignalStrengthDefaultValues() {
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // TODO Make a constructor only has boolean gsm as parameter
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1,
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                -1, -1, -1, SignalStrength.INVALID_SNR, -1, true);
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * A complete "service state" from our perspective is
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * composed of a handful of separate requests to the radio.
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * We make all of these requests at once, but then abandon them
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * and start over again if the radio notifies us that some
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * event has changed
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void pollState() {
7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pollingContext = new int[1];
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pollingContext[0] = 0;
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (cm.getRadioState()) {
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case RADIO_UNAVAILABLE:
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                newSS.setStateOutOfService();
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                newCellLoc.setStateInvalid();
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                setSignalStrengthDefaultValues();
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mGotCountryCode = false;
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mNitzUpdatedTime = false;
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollStateDone();
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case RADIO_OFF:
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                newSS.setStateOff();
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                newCellLoc.setStateInvalid();
7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                setSignalStrengthDefaultValues();
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mGotCountryCode = false;
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mNitzUpdatedTime = false;
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollStateDone();
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            default:
7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Issue all poll-related commands at once
7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // then count down the responses, which
7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // are allowed to arrive out-of-order
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollingContext[0]++;
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.getOperator(
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    obtainMessage(
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        EVENT_POLL_STATE_OPERATOR, pollingContext));
7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollingContext[0]++;
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.getDataRegistrationState(
7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    obtainMessage(
7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        EVENT_POLL_STATE_GPRS, pollingContext));
7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollingContext[0]++;
7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.getVoiceRegistrationState(
7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    obtainMessage(
7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        EVENT_POLL_STATE_REGISTRATION, pollingContext));
7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollingContext[0]++;
7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.getNetworkSelectionMode(
7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    obtainMessage(
7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        EVENT_POLL_STATE_NETWORK_SELECTION_MODE, pollingContext));
7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void pollStateDone() {
7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) {
7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Poll ServiceState done: " +
7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " oldSS=[" + ss + "] newSS=[" + newSS +
7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "] oldGprs=" + gprsState + " newData=" + newGPRSState +
7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " oldMaxDataCalls=" + mMaxDataCalls +
7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " mNewMaxDataCalls=" + mNewMaxDataCalls +
7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " oldReasonDataDenied=" + mReasonDataDenied +
7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " mNewReasonDataDenied=" + mNewReasonDataDenied +
7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " oldType=" + ServiceState.rilRadioTechnologyToString(mRilRadioTechnology) +
7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " newType=" + ServiceState.rilRadioTechnologyToString(mNewRilRadioTechnology));
7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasRegistered =
7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ss.getState() != ServiceState.STATE_IN_SERVICE
7650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            && newSS.getState() == ServiceState.STATE_IN_SERVICE;
7660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasDeregistered =
7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ss.getState() == ServiceState.STATE_IN_SERVICE
7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            && newSS.getState() != ServiceState.STATE_IN_SERVICE;
7700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasGprsAttached =
7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                gprsState != ServiceState.STATE_IN_SERVICE
7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && newGPRSState == ServiceState.STATE_IN_SERVICE;
7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasGprsDetached =
7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                gprsState == ServiceState.STATE_IN_SERVICE
7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && newGPRSState != ServiceState.STATE_IN_SERVICE;
7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasRadioTechnologyChanged = mRilRadioTechnology != mNewRilRadioTechnology;
7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasChanged = !newSS.equals(ss);
7820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
7860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
7880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Add an event log when connection state changes
7900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ss.getState() != newSS.getState() || gprsState != newGPRSState) {
7910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE,
7920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ss.getState(), gprsState, newSS.getState(), newGPRSState);
7930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ServiceState tss;
7960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        tss = ss;
7970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ss = newSS;
7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        newSS = tss;
7990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // clean slate for next time
8000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        newSS.setStateOutOfService();
8010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        GsmCellLocation tcl = cellLoc;
8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cellLoc = newCellLoc;
8040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        newCellLoc = tcl;
8050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Add an event log when network type switched
8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // TODO: we may add filtering to reduce the event logged,
8080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // i.e. check preferred network setting, only switch to 2G, etc
8090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasRadioTechnologyChanged) {
8100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int cid = -1;
8110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (loc != null) cid = loc.getCid();
8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED, cid, mRilRadioTechnology,
8140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mNewRilRadioTechnology);
8150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (DBG) {
8160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("RAT switched " + ServiceState.rilRadioTechnologyToString(mRilRadioTechnology) +
8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        " -> " + ServiceState.rilRadioTechnologyToString(mNewRilRadioTechnology) +
8180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        " at cell " + cid);
8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        gprsState = newGPRSState;
8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mReasonDataDenied = mNewReasonDataDenied;
8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mMaxDataCalls = mNewMaxDataCalls;
8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRilRadioTechnology = mNewRilRadioTechnology;
8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // this new state has been applied - forget it until we get a new new state
8270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNewRilRadioTechnology = 0;
8280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        newSS.setStateOutOfService(); // clean slate for next time
8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasRadioTechnologyChanged) {
8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ServiceState.rilRadioTechnologyToString(mRilRadioTechnology));
8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasRegistered) {
8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mNetworkAttachedRegistrants.notifyRegistrants();
8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (DBG) {
8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("pollStateDone: registering current mNitzUpdatedTime=" +
8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mNitzUpdatedTime + " changing to false");
8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mNitzUpdatedTime = false;
8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasChanged) {
8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String operatorNumeric;
8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            updateSpnDisplay();
8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ss.getOperatorAlphaLong());
8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String prevOperatorNumeric =
8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            operatorNumeric = ss.getOperatorNumeric();
8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (operatorNumeric == null) {
8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (DBG) log("operatorNumeric is null");
8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mGotCountryCode = false;
8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mNitzUpdatedTime = false;
8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String iso = "";
8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String mcc = operatorNumeric.substring(0, 3);
8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                try{
8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    iso = MccTable.countryCodeForMcc(Integer.parseInt(mcc));
8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } catch ( NumberFormatException ex){
8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    loge("pollStateDone: countryCodeForMcc error" + ex);
8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } catch ( StringIndexOutOfBoundsException ex) {
8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    loge("pollStateDone: countryCodeForMcc error" + ex);
8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso);
8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mGotCountryCode = true;
8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                TimeZone zone = null;
8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!mNitzUpdatedTime && !mcc.equals("000") && !TextUtils.isEmpty(iso) &&
8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        getAutoTimeZone()) {
8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Test both paths if ignore nitz is true
8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    boolean testOneUniqueOffsetPath = SystemProperties.getBoolean(
8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                TelephonyProperties.PROPERTY_IGNORE_NITZ, false) &&
8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    ((SystemClock.uptimeMillis() & 1) == 0);
8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ArrayList<TimeZone> uniqueZones = TimeUtils.getTimeZonesWithUniqueOffsets(iso);
8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if ((uniqueZones.size() == 1) || testOneUniqueOffsetPath) {
8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        zone = uniqueZones.get(0);
8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) {
8930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                           log("pollStateDone: no nitz but one TZ for iso-cc=" + iso +
8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                   " with zone.getID=" + zone.getID() +
8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                   " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath);
8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        setAndBroadcastNetworkSetTimeZone(zone.getID());
8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) {
9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            log("pollStateDone: there are " + uniqueZones.size() +
9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                " unique offsets for iso-cc='" + iso +
9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath +
9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                "', do nothing");
9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (shouldFixTimeZoneNow(phone, operatorNumeric, prevOperatorNumeric,
9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mNeedFixZoneAfterNitz)) {
9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // If the offset is (0, false) and the timezone property
9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // is set, use the timezone property rather than
9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // GMT.
9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    String zoneName = SystemProperties.get(TIMEZONE_PROPERTY);
9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (DBG) {
9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        log("pollStateDone: fix time zone zoneName='" + zoneName +
9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst +
9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            " iso-cc='" + iso +
9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, iso));
9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // "(mZoneOffset == 0) && (mZoneDst == false) &&
9220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    //  (Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)"
9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // means that we received a NITZ string telling
9240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // it is in GMT+0 w/ DST time zone
9250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // BUT iso tells is NOT, e.g, a wrong NITZ reporting
9260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // local time w/ 0 offset.
9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if ((mZoneOffset == 0) && (mZoneDst == false) &&
9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (zoneName != null) && (zoneName.length() > 0) &&
9290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)) {
9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        zone = TimeZone.getDefault();
9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (mNeedFixZoneAfterNitz) {
9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            // For wrong NITZ reporting local time w/ 0 offset,
9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            // need adjust time to reflect default timezone setting
9340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            long ctm = System.currentTimeMillis();
9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            long tzOffset = zone.getOffset(ctm);
9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (DBG) {
9370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                log("pollStateDone: tzOffset=" + tzOffset + " ltod=" +
9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                        TimeUtils.logTimeOfDay(ctm));
9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (getAutoTime()) {
9410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                long adj = ctm - tzOffset;
9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                if (DBG) log("pollStateDone: adj ltod=" +
9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                        TimeUtils.logTimeOfDay(adj));
9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                setAndBroadcastNetworkSetTime(adj);
9450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            } else {
9460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                // Adjust the saved NITZ time to account for tzOffset.
9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                mSavedTime = mSavedTime - tzOffset;
9480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            }
9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
9500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) log("pollStateDone: using default TimeZone");
9510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else if (iso.equals("")){
9520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Country code not found.  This is likely a test network.
9530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Get a TimeZone based only on the NITZ parameters (best guess).
9540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime);
9550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) log("pollStateDone: using NITZ TimeZone");
9560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
9570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, iso);
9580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) log("pollStateDone: using getTimeZone(off, dst, time, iso)");
9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mNeedFixZoneAfterNitz = false;
9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (zone != null) {
9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        log("pollStateDone: zone != null zone.getID=" + zone.getID());
9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (getAutoTimeZone()) {
9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            setAndBroadcastNetworkSetTimeZone(zone.getID());
9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        saveNitzTimeZone(zone.getID());
9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        log("pollStateDone: zone == null");
9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
9720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
9760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ss.getRoaming() ? "true" : "false");
9770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyServiceStateChanged(ss);
9790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasGprsAttached) {
9820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mAttachedRegistrants.notifyRegistrants();
9830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasGprsDetached) {
9860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mDetachedRegistrants.notifyRegistrants();
9870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasRadioTechnologyChanged) {
9900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED);
9910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasRoamingOn) {
9940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRoamingOnRegistrants.notifyRegistrants();
9950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasRoamingOff) {
9980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRoamingOffRegistrants.notifyRegistrants();
9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasLocationChanged) {
10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyLocationChanged();
10030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (! isGprsConsistent(gprsState, ss.getState())) {
10060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mStartedGprsRegCheck = true;
10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int check_period = Settings.Secure.getInt(
10100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        phone.getContext().getContentResolver(),
10110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        Settings.Secure.GPRS_REGISTER_CHECK_PERIOD_MS,
10120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
10130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
10140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        check_period);
10150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
10160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
10170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mReportedGprsNoReg = false;
10180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Check if GPRS got registered while voice is registered.
10230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
10240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param gprsState for GPRS registration state, i.e. CGREG in GSM
10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param serviceState for voice registration state, i.e. CREG in GSM
10260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return false if device only register to voice but not gprs
10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
10280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean isGprsConsistent(int gprsState, int serviceState) {
10290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return !((serviceState == ServiceState.STATE_IN_SERVICE) &&
10300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (gprsState != ServiceState.STATE_IN_SERVICE));
10310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns a TimeZone object based only on parameters from the NITZ string.
10350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
10360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private TimeZone getNitzTimeZone(int offset, boolean dst, long when) {
10370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        TimeZone guess = findTimeZone(offset, dst, when);
10380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (guess == null) {
10390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Couldn't find a proper timezone.  Perhaps the DST data is wrong.
10400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            guess = findTimeZone(offset, !dst, when);
10410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
10430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return guess;
10440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private TimeZone findTimeZone(int offset, boolean dst, long when) {
10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int rawOffset = offset;
10480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (dst) {
10490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            rawOffset -= 3600000;
10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String[] zones = TimeZone.getAvailableIDs(rawOffset);
10520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        TimeZone guess = null;
10530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Date d = new Date(when);
10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (String zone : zones) {
10550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            TimeZone tz = TimeZone.getTimeZone(zone);
10560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (tz.getOffset(when) == offset &&
10570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                tz.inDaylightTime(d) == dst) {
10580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                guess = tz;
10590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
10600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
10610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return guess;
10640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void queueNextSignalStrengthPoll() {
10670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (dontPollSignalStrength) {
10680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // The radio is telling us about signal strength changes
10690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // we don't have to ask it
10700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
10710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Message msg;
10740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        msg = obtainMessage();
10760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        msg.what = EVENT_POLL_SIGNAL_STRENGTH;
10770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        long nextTime;
10790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // TODO Don't poll signal strength if screen is off
10810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
10820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
10850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  Send signal-strength-changed notification if changed.
10860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  Called both for solicited and unsolicited signal strength updates.
10870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
10880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void onSignalStrengthResult(AsyncResult ar) {
10890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SignalStrength oldSignalStrength = mSignalStrength;
10900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int rssi = 99;
10910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int lteSignalStrength = -1;
10920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int lteRsrp = -1;
10930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int lteRsrq = -1;
10940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int lteRssnr = SignalStrength.INVALID_SNR;
10950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int lteCqi = -1;
10960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ar.exception != null) {
10980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // -1 = unknown
10990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // most likely radio is resetting/disconnected
11000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            setSignalStrengthDefaultValues();
11010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
11020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int[] ints = (int[])ar.result;
11030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // bug 658816 seems to be a case where the result is 0-length
11050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ints.length != 0) {
11060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                rssi = ints[0];
11070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                lteSignalStrength = ints[7];
11080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                lteRsrp = ints[8];
11090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                lteRsrq = ints[9];
11100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                lteRssnr = ints[10];
11110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                lteCqi = ints[11];
11120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
11130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                loge("Bogus signal strength response");
11140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                rssi = 99;
11150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
11160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
11190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                -1, -1, -1, lteSignalStrength, lteRsrp, lteRsrq, lteRssnr, lteCqi, true);
11200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!mSignalStrength.equals(oldSignalStrength)) {
11220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
11230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                  // POLL_PERIOD_MILLIS) during Radio Technology Change)
11240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                phone.notifySignalStrength();
11250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville           } catch (NullPointerException ex) {
11260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("onSignalStrengthResult() Phone already destroyed: " + ex
11270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        + "SignalStrength not notified");
11280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville           }
11290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
11310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
11330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Set restricted state based on the OnRestrictedStateChanged notification
11340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * If any voice or packet restricted state changes, trigger a UI
11350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * notification and notify registrants when sim is ready.
11360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
11370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ar an int value of RIL_RESTRICTED_STATE_*
11380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
11390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void onRestrictedStateChanged(AsyncResult ar) {
11400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        RestrictedState newRs = new RestrictedState();
11410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState);
11430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ar.exception == null) {
11450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int[] ints = (int[])ar.result;
11460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int state = ints[0];
11470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            newRs.setCsEmergencyRestricted(
11490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
11500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
11510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            //ignore the normal call and data restricted state before SIM READY
11520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (phone.getIccCard().getState() == IccCardConstants.State.READY) {
11530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                newRs.setCsNormalRestricted(
11540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
11550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
11560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                newRs.setPsRestricted(
11570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
11580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
11590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (DBG) log("onRestrictedStateChanged: new rs "+ newRs);
11610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
11630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mPsRestrictEnabledRegistrants.notifyRegistrants();
11640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                setNotification(PS_ENABLED);
11650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
11660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mPsRestrictDisabledRegistrants.notifyRegistrants();
11670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                setNotification(PS_DISABLED);
11680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
11690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            /**
11710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * There are two kind of cs restriction, normal and emergency. So
11720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * there are 4 x 4 combinations in current and new restricted states
11730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * and we only need to notify when state is changed.
11740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             */
11750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (mRestrictedState.isCsRestricted()) {
11760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!newRs.isCsRestricted()) {
11770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove all restriction
11780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_DISABLED);
11790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (!newRs.isCsNormalRestricted()) {
11800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove normal restriction
11810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_EMERGENCY_ENABLED);
11820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (!newRs.isCsEmergencyRestricted()) {
11830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove emergency restriction
11840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_NORMAL_ENABLED);
11850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
11860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (mRestrictedState.isCsEmergencyRestricted() &&
11870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    !mRestrictedState.isCsNormalRestricted()) {
11880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!newRs.isCsRestricted()) {
11890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove all restriction
11900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_DISABLED);
11910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (newRs.isCsRestricted()) {
11920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // enable all restriction
11930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_ENABLED);
11940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (newRs.isCsNormalRestricted()) {
11950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove emergency restriction and enable normal restriction
11960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_NORMAL_ENABLED);
11970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
11980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (!mRestrictedState.isCsEmergencyRestricted() &&
11990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mRestrictedState.isCsNormalRestricted()) {
12000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!newRs.isCsRestricted()) {
12010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove all restriction
12020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_DISABLED);
12030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (newRs.isCsRestricted()) {
12040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // enable all restriction
12050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_ENABLED);
12060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (newRs.isCsEmergencyRestricted()) {
12070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // remove normal restriction and enable emergency restriction
12080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_EMERGENCY_ENABLED);
12090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
12100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
12110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (newRs.isCsRestricted()) {
12120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // enable all restriction
12130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_ENABLED);
12140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (newRs.isCsEmergencyRestricted()) {
12150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // enable emergency restriction
12160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_EMERGENCY_ENABLED);
12170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if (newRs.isCsNormalRestricted()) {
12180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // enable normal restriction
12190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setNotification(CS_NORMAL_ENABLED);
12200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
12210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
12220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRestrictedState = newRs;
12240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
12250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        log("onRestrictedStateChanged: X rs "+ mRestrictedState);
12260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
12270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** code is registration state 0-5 from TS 27.007 7.2 */
12290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int regCodeToServiceState(int code) {
12300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (code) {
12310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 0:
12320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 2: // 2 is "searching"
12330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 3: // 3 is "registration denied"
12340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 4: // 4 is "unknown" no vaild in current baseband
12350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 10:// same as 0, but indicates that emergency call is possible.
12360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 12:// same as 2, but indicates that emergency call is possible.
12370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 13:// same as 3, but indicates that emergency call is possible.
12380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 14:// same as 4, but indicates that emergency call is possible.
12390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return ServiceState.STATE_OUT_OF_SERVICE;
12400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 1:
12420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return ServiceState.STATE_IN_SERVICE;
12430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case 5:
12450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // in service, roam
12460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return ServiceState.STATE_IN_SERVICE;
12470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            default:
12490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                loge("regCodeToServiceState: unexpected service state " + code);
12500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return ServiceState.STATE_OUT_OF_SERVICE;
12510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
12520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
12530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
12560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * code is registration state 0-5 from TS 27.007 7.2
12570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * returns true if registered roam, false otherwise
12580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
12590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean regCodeIsRoaming (int code) {
12600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // 5 is  "in service -- roam"
12610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return 5 == code;
12620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
12630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
12650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Set roaming state when gsmRoaming is true and, if operator mcc is the
12660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * same as sim mcc, ons is different from spn
12670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param gsmRoaming TS 27.007 7.2 CREG registered roaming
12680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param s ServiceState hold current ons
12690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true for roaming state set
12700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
12710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean isRoamingBetweenOperators(boolean gsmRoaming, ServiceState s) {
12720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String spn = SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "empty");
12730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String onsl = s.getOperatorAlphaLong();
12750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String onss = s.getOperatorAlphaShort();
12760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean equalsOnsl = onsl != null && spn.equals(onsl);
12780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean equalsOnss = onss != null && spn.equals(onss);
12790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String simNumeric = SystemProperties.get(
12810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
12820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String  operatorNumeric = s.getOperatorNumeric();
12830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean equalsMcc = true;
12850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
12860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            equalsMcc = simNumeric.substring(0, 3).
12870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    equals(operatorNumeric.substring(0, 3));
12880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (Exception e){
12890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
12900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return gsmRoaming && !(equalsMcc && (equalsOnsl || equalsOnss));
12920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
12930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static int twoDigitsAt(String s, int offset) {
12950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int a, b;
12960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        a = Character.digit(s.charAt(offset), 10);
12980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        b = Character.digit(s.charAt(offset+1), 10);
12990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (a < 0 || b < 0) {
13010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new RuntimeException("invalid format");
13030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
13040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return a*10 + b;
13060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
13070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
13090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return The current GPRS state. IN_SERVICE is the same as "attached"
13100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * and OUT_OF_SERVICE is the same as detached.
13110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
13120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    int getCurrentGprsState() {
13130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return gprsState;
13140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
13150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int getCurrentDataConnectionState() {
13170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return gprsState;
13180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
13190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
13210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true if phone is camping on a technology (eg UMTS)
13220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * that could support voice and data simultaneously.
13230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
13240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isConcurrentVoiceAndDataAllowed() {
13250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return (mRilRadioTechnology >= ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
13260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
13270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
13290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Provides the name of the algorithmic time zone for the specified
13300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * offset.  Taken from TimeZone.java.
13310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
13320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static String displayNameFor(int off) {
13330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        off = off / 1000 / 60;
13340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        char[] buf = new char[9];
13360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[0] = 'G';
13370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[1] = 'M';
13380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[2] = 'T';
13390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (off < 0) {
13410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf[3] = '-';
13420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            off = -off;
13430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
13440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf[3] = '+';
13450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
13460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int hours = off / 60;
13480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int minutes = off % 60;
13490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[4] = (char) ('0' + hours / 10);
13510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[5] = (char) ('0' + hours % 10);
13520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[6] = ':';
13540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[7] = (char) ('0' + minutes / 10);
13560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf[8] = (char) ('0' + minutes % 10);
13570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return new String(buf);
13590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
13600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
13620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * nitzReceiveTime is time_t that the NITZ time was posted
13630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
13640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void setTimeFromNITZString (String nitz, long nitzReceiveTime) {
13650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // "yy/mm/dd,hh:mm:ss(+/-)tz"
13660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // tz is in number of quarter-hours
13670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        long start = SystemClock.elapsedRealtime();
13690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) {log("NITZ: " + nitz + "," + nitzReceiveTime +
13700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        " start=" + start + " delay=" + (start - nitzReceiveTime));
13710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
13720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
13740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            /* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
13750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville             * offset as well (which we won't worry about until later) */
13760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
13770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.clear();
13790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.DST_OFFSET, 0);
13800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String[] nitzSubs = nitz.split("[/:,+-]");
13820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int year = 2000 + Integer.parseInt(nitzSubs[0]);
13840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.YEAR, year);
13850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // month is 0 based!
13870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int month = Integer.parseInt(nitzSubs[1]) - 1;
13880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.MONTH, month);
13890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int date = Integer.parseInt(nitzSubs[2]);
13910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.DATE, date);
13920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int hour = Integer.parseInt(nitzSubs[3]);
13940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.HOUR, hour);
13950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int minute = Integer.parseInt(nitzSubs[4]);
13970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.MINUTE, minute);
13980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int second = Integer.parseInt(nitzSubs[5]);
14000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            c.set(Calendar.SECOND, second);
14010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean sign = (nitz.indexOf('-') == -1);
14030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int tzOffset = Integer.parseInt(nitzSubs[6]);
14050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int dst = (nitzSubs.length >= 8 ) ? Integer.parseInt(nitzSubs[7])
14070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                              : 0;
14080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // The zone offset received from NITZ is for current local time,
14100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // so DST correction is already applied.  Don't add it again.
14110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            //
14120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // tzOffset += dst * 4;
14130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            //
14140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // We could unapply it if we wanted the raw offset.
14150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            tzOffset = (sign ? 1 : -1) * tzOffset * 15 * 60 * 1000;
14170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            TimeZone    zone = null;
14190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // As a special extension, the Android emulator appends the name of
14210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // the host computer's timezone to the nitz string. this is zoneinfo
14220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // timezone name of the form Area!Location or Area!Location!SubLocation
14230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // so we need to convert the ! into /
14240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (nitzSubs.length >= 9) {
14250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String  tzname = nitzSubs[8].replace('!','/');
14260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                zone = TimeZone.getTimeZone( tzname );
14270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
14280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String iso = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);
14300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (zone == null) {
14320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (mGotCountryCode) {
14340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (iso != null && iso.length() > 0) {
14350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        zone = TimeUtils.getTimeZone(tzOffset, dst != 0,
14360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                c.getTimeInMillis(),
14370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                iso);
14380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
14390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // We don't have a valid iso country code.  This is
14400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // most likely because we're on a test network that's
14410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // using a bogus MCC (eg, "001"), so get a TimeZone
14420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // based only on the NITZ parameters.
14430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        zone = getNitzTimeZone(tzOffset, (dst != 0), c.getTimeInMillis());
14440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
14450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
14460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
14470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if ((zone == null) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){
14490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // We got the time before the country or the zone has changed
14500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // so we don't know how to identify the DST rules yet.  Save
14510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // the information and hope to fix it up later.
14520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mNeedFixZoneAfterNitz = true;
14540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mZoneOffset  = tzOffset;
14550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mZoneDst     = dst != 0;
14560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mZoneTime    = c.getTimeInMillis();
14570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
14580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (zone != null) {
14600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (getAutoTimeZone()) {
14610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setAndBroadcastNetworkSetTimeZone(zone.getID());
14620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
14630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                saveNitzTimeZone(zone.getID());
14640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
14650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String ignore = SystemProperties.get("gsm.ignore-nitz");
14670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ignore != null && ignore.equals("yes")) {
14680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("NITZ: Not setting clock because gsm.ignore-nitz is set");
14690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
14700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
14710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
14730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mWakeLock.acquire();
14740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (getAutoTime()) {
14760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    long millisSinceNitzReceived
14770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            = SystemClock.elapsedRealtime() - nitzReceiveTime;
14780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (millisSinceNitzReceived < 0) {
14800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Sanity check: something is wrong
14810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) {
14820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            log("NITZ: not setting time, clock has rolled "
14830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                            + "backwards since NITZ time was received, "
14840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                            + nitz);
14850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
14860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        return;
14870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
14880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (millisSinceNitzReceived > Integer.MAX_VALUE) {
14900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // If the time is this far off, something is wrong > 24 days!
14910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (DBG) {
14920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            log("NITZ: not setting time, processing has taken "
14930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                        + (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
14940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                        + " days");
14950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
14960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        return;
14970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
14980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Note: with range checks above, cast to int is safe
15000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
15010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (DBG) {
15030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        log("NITZ: Setting time of day to " + c.getTime()
15040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + " NITZ receive delay(ms): " + millisSinceNitzReceived
15050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + " gained(ms): "
15060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + (c.getTimeInMillis() - System.currentTimeMillis())
15070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + " from " + nitz);
15080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
15090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    setAndBroadcastNetworkSetTime(c.getTimeInMillis());
15110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Log.i(LOG_TAG, "NITZ: after Setting time of day");
15120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
15130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
15140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                saveNitzTime(c.getTimeInMillis());
15150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (false) {
15160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    long end = SystemClock.elapsedRealtime();
15170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    log("NITZ: end=" + end + " dur=" + (end - start));
15180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
15190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mNitzUpdatedTime = true;
15200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } finally {
15210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mWakeLock.release();
15220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
15230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (RuntimeException ex) {
15240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
15250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
15260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean getAutoTime() {
15290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
15300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return Settings.System.getInt(phone.getContext().getContentResolver(),
15310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Settings.System.AUTO_TIME) > 0;
15320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (SettingNotFoundException snfe) {
15330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return true;
15340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
15350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean getAutoTimeZone() {
15380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
15390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return Settings.System.getInt(phone.getContext().getContentResolver(),
15400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Settings.System.AUTO_TIME_ZONE) > 0;
15410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (SettingNotFoundException snfe) {
15420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return true;
15430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
15440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void saveNitzTimeZone(String zoneId) {
15470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSavedTimeZone = zoneId;
15480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void saveNitzTime(long time) {
15510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSavedTime = time;
15520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSavedAtTime = SystemClock.elapsedRealtime();
15530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
15560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Set the timezone and send out a sticky broadcast so the system can
15570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * determine if the timezone was set by the carrier.
15580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
15590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param zoneId timezone set by carrier
15600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
15610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void setAndBroadcastNetworkSetTimeZone(String zoneId) {
15620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId);
15630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        AlarmManager alarm =
15640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
15650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        alarm.setTimeZone(zoneId);
15660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
15670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
15680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        intent.putExtra("time-zone", zoneId);
15690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.getContext().sendStickyBroadcast(intent);
15700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) {
15710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("setAndBroadcastNetworkSetTimeZone: call alarm.setTimeZone and broadcast zoneId=" +
15720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                zoneId);
15730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
15740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
15770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Set the time and Send out a sticky broadcast so the system can determine
15780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * if the time was set by the carrier.
15790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
15800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param time time set by network
15810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
15820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void setAndBroadcastNetworkSetTime(long time) {
15830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms");
15840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SystemClock.setCurrentTimeMillis(time);
15850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
15860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
15870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        intent.putExtra("time", time);
15880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.getContext().sendStickyBroadcast(intent);
15890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
15900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
15910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void revertToNitzTime() {
15920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (Settings.System.getInt(phone.getContext().getContentResolver(),
15930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Settings.System.AUTO_TIME, 0) == 0) {
15940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
15950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
15960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) {
15970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Reverting to NITZ Time: mSavedTime=" + mSavedTime
15980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                + " mSavedAtTime=" + mSavedAtTime);
15990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mSavedTime != 0 && mSavedAtTime != 0) {
16010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            setAndBroadcastNetworkSetTime(mSavedTime
16020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    + (SystemClock.elapsedRealtime() - mSavedAtTime));
16030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void revertToNitzTimeZone() {
16070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (Settings.System.getInt(phone.getContext().getContentResolver(),
16080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Settings.System.AUTO_TIME_ZONE, 0) == 0) {
16090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
16100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
16120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mSavedTimeZone != null) {
16130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
16140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
16180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Post a notification to NotificationManager for restricted state
16190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
16200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE
16210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
16220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void setNotification(int notifyType) {
16230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("setNotification: create notification " + notifyType);
16250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Context context = phone.getContext();
16260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification = new Notification();
16280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification.when = System.currentTimeMillis();
16290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification.flags = Notification.FLAG_AUTO_CANCEL;
16300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification.icon = com.android.internal.R.drawable.stat_sys_warning;
16310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent();
16320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification.contentIntent = PendingIntent
16330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        .getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
16340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CharSequence details = "";
16360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle);
16370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int notificationId = CS_NOTIFICATION;
16380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (notifyType) {
16400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PS_ENABLED:
16410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            notificationId = PS_NOTIFICATION;
16420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            details = context.getText(com.android.internal.R.string.RestrictedOnData);;
16430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
16440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PS_DISABLED:
16450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            notificationId = PS_NOTIFICATION;
16460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
16470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case CS_ENABLED:
16480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            details = context.getText(com.android.internal.R.string.RestrictedOnAllVoice);;
16490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
16500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case CS_NORMAL_ENABLED:
16510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
16520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
16530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case CS_EMERGENCY_ENABLED:
16540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            details = context.getText(com.android.internal.R.string.RestrictedOnEmergency);;
16550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
16560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case CS_DISABLED:
16570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // do nothing and cancel the notification later
16580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
16590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("setNotification: put notification " + title + " / " +details);
16620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification.tickerText = title;
16630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mNotification.setLatestEventInfo(context, title, details,
16640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mNotification.contentIntent);
16650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        NotificationManager notificationManager = (NotificationManager)
16670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            context.getSystemService(Context.NOTIFICATION_SERVICE);
16680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
16700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // cancel previous post notification
16710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            notificationManager.cancel(notificationId);
16720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
16730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // update restricted state notification
16740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            notificationManager.notify(notificationId, mNotification);
16750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
16790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void log(String s) {
16800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.d(LOG_TAG, "[GsmSST] " + s);
16810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
16840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void loge(String s) {
16850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.e(LOG_TAG, "[GsmSST] " + s);
16860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static void sloge(String s) {
16890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.e(LOG_TAG, "[GsmSST] " + s);
16900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
16930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
16940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println("GsmServiceStateTracker extends:");
16950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        super.dump(fd, pw, args);
16960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" phone=" + phone);
16970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" cellLoc=" + cellLoc);
16980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" newCellLoc=" + newCellLoc);
16990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mPreferredNetworkType=" + mPreferredNetworkType);
17000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" gprsState=" + gprsState);
17010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" newGPRSState=" + newGPRSState);
17020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mMaxDataCalls=" + mMaxDataCalls);
17030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls);
17040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mReasonDataDenied=" + mReasonDataDenied);
17050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied);
17060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mGsmRoaming=" + mGsmRoaming);
17070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mDataRoaming=" + mDataRoaming);
17080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mEmergencyOnly=" + mEmergencyOnly);
17090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mNeedFixZoneAfterNitz=" + mNeedFixZoneAfterNitz);
17100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mZoneOffset=" + mZoneOffset);
17110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mZoneDst=" + mZoneDst);
17120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mZoneTime=" + mZoneTime);
17130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mGotCountryCode=" + mGotCountryCode);
17140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mNitzUpdatedTime=" + mNitzUpdatedTime);
17150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mSavedTimeZone=" + mSavedTimeZone);
17160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mSavedTime=" + mSavedTime);
17170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mSavedAtTime=" + mSavedAtTime);
17180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mNeedToRegForSimLoaded=" + mNeedToRegForSimLoaded);
17190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck);
17200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg);
17210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mNotification=" + mNotification);
17220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" mWakeLock=" + mWakeLock);
17230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" curSpn=" + curSpn);
17240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" curPlmn=" + curPlmn);
17250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" curSpnRule=" + curSpnRule);
17260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
17270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1728