/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; import android.telephony.ServiceState; import android.telephony.SignalStrength; /** * {@hide} */ public abstract class ServiceStateTracker extends Handler { /** * Access technology currently in use. */ protected static final int DATA_ACCESS_UNKNOWN = 0; protected static final int DATA_ACCESS_GPRS = 1; protected static final int DATA_ACCESS_EDGE = 2; protected static final int DATA_ACCESS_UMTS = 3; protected static final int DATA_ACCESS_CDMA_IS95A = 4; protected static final int DATA_ACCESS_CDMA_IS95B = 5; protected static final int DATA_ACCESS_CDMA_1xRTT = 6; protected static final int DATA_ACCESS_CDMA_EvDo_0 = 7; protected static final int DATA_ACCESS_CDMA_EvDo_A = 8; protected static final int DATA_ACCESS_HSDPA = 9; protected static final int DATA_ACCESS_HSUPA = 10; protected static final int DATA_ACCESS_HSPA = 11; protected CommandsInterface cm; public ServiceState ss; protected ServiceState newSS; public SignalStrength mSignalStrength; /** * A unique identifier to track requests associated with a poll * and ignore stale responses. The value is a count-down of * expected responses in this pollingContext. */ protected int[] pollingContext; protected boolean mDesiredPowerState; /** * By default, strength polling is enabled. However, if we're * getting unsolicited signal strength updates from the radio, set * value to true and don't bother polling any more. */ protected boolean dontPollSignalStrength = false; protected RegistrantList networkAttachedRegistrants = new RegistrantList(); protected RegistrantList roamingOnRegistrants = new RegistrantList(); protected RegistrantList roamingOffRegistrants = new RegistrantList(); protected static final boolean DBG = true; /** Signal strength poll rate. */ protected static final int POLL_PERIOD_MILLIS = 20 * 1000; /** Waiting period before recheck gprs and voice registration. */ public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000; public static final int DATA_STATE_POLL_SLEEP_MS = 100; /** GSM events */ protected static final int EVENT_RADIO_STATE_CHANGED = 1; protected static final int EVENT_NETWORK_STATE_CHANGED = 2; protected static final int EVENT_GET_SIGNAL_STRENGTH = 3; protected static final int EVENT_POLL_STATE_REGISTRATION = 4; protected static final int EVENT_POLL_STATE_GPRS = 5; protected static final int EVENT_POLL_STATE_OPERATOR = 6; protected static final int EVENT_POLL_SIGNAL_STRENGTH = 10; protected static final int EVENT_NITZ_TIME = 11; protected static final int EVENT_SIGNAL_STRENGTH_UPDATE = 12; protected static final int EVENT_RADIO_AVAILABLE = 13; protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14; protected static final int EVENT_GET_LOC_DONE = 15; protected static final int EVENT_SIM_RECORDS_LOADED = 16; protected static final int EVENT_SIM_READY = 17; protected static final int EVENT_LOCATION_UPDATES_ENABLED = 18; protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE = 19; protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE = 20; protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE = 21; protected static final int EVENT_CHECK_REPORT_GPRS = 22; protected static final int EVENT_RESTRICTED_STATE_CHANGED = 23; /** CDMA events */ protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA = 24; protected static final int EVENT_POLL_STATE_OPERATOR_CDMA = 25; protected static final int EVENT_RUIM_READY = 26; protected static final int EVENT_RUIM_RECORDS_LOADED = 27; protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA = 28; protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA = 29; protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA = 30; protected static final int EVENT_GET_LOC_DONE_CDMA = 31; protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA = 32; protected static final int EVENT_NV_LOADED = 33; protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION = 34; protected static final int EVENT_NV_READY = 35; protected static final int EVENT_ERI_FILE_LOADED = 36; protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE = 37; protected static final int EVENT_SET_RADIO_POWER_OFF = 38; protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; /** * List of ISO codes for countries that can have an offset of * GMT+0 when not in daylight savings time. This ignores some * small places such as the Canary Islands (Spain) and * Danmarkshavn (Denmark). The list must be sorted by code. */ protected static final String[] GMT_COUNTRY_CODES = { "bf", // Burkina Faso "ci", // Cote d'Ivoire "eh", // Western Sahara "fo", // Faroe Islands, Denmark "gh", // Ghana "gm", // Gambia "gn", // Guinea "gw", // Guinea Bissau "ie", // Ireland "lr", // Liberia "is", // Iceland "ma", // Morocco "ml", // Mali "mr", // Mauritania "pt", // Portugal "sl", // Sierra Leone "sn", // Senegal "st", // Sao Tome and Principe "tg", // Togo "uk", // U.K }; /** Reason for registration denial. */ protected static final String REGISTRATION_DENIED_GEN = "General"; protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure"; public ServiceStateTracker() { } public boolean getDesiredPowerState() { return mDesiredPowerState; } /** * Registration point for combined roaming on * combined roaming is true when roaming is true and ONS differs SPN * * @param h handler to notify * @param what what code of message when delivered * @param obj placed in Message.obj */ public void registerForRoamingOn(Handler h, int what, Object obj) { Registrant r = new Registrant(h, what, obj); roamingOnRegistrants.add(r); if (ss.getRoaming()) { r.notifyRegistrant(); } } public void unregisterForRoamingOn(Handler h) { roamingOnRegistrants.remove(h); } /** * Registration point for combined roaming off * combined roaming is true when roaming is true and ONS differs SPN * * @param h handler to notify * @param what what code of message when delivered * @param obj placed in Message.obj */ public void registerForRoamingOff(Handler h, int what, Object obj) { Registrant r = new Registrant(h, what, obj); roamingOffRegistrants.add(r); if (!ss.getRoaming()) { r.notifyRegistrant(); } } public void unregisterForRoamingOff(Handler h) { roamingOffRegistrants.remove(h); } /** * Reregister network through toggle perferred network type * This is a work aorund to deregister and register network since there is * no ril api to set COPS=2 (deregister) only. * * @param onComplete is dispatched when this is complete. it will be * an AsyncResult, and onComplete.obj.exception will be non-null * on failure. */ public void reRegisterNetwork(Message onComplete) { cm.getPreferredNetworkType( obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete)); } public void setRadioPower(boolean power) { mDesiredPowerState = power; setPowerStateToDesired(); } /** * These two flags manage the behavior of the cell lock -- the * lock should be held if either flag is true. The intention is * to allow temporary aquisition of the lock to get a single * update. Such a lock grab and release can thus be made to not * interfere with more permanent lock holds -- in other words, the * lock will only be released if both flags are false, and so * releases by temporary users will only affect the lock state if * there is no continuous user. */ private boolean mWantContinuousLocationUpdates; private boolean mWantSingleLocationUpdate; public void enableSingleLocationUpdate() { if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return; mWantSingleLocationUpdate = true; cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED)); } public void enableLocationUpdates() { if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return; mWantContinuousLocationUpdates = true; cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED)); } protected void disableSingleLocationUpdate() { mWantSingleLocationUpdate = false; if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) { cm.setLocationUpdates(false, null); } } public void disableLocationUpdates() { mWantContinuousLocationUpdates = false; if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) { cm.setLocationUpdates(false, null); } } public abstract void handleMessage(Message msg); protected abstract void handlePollStateResult(int what, AsyncResult ar); protected abstract void updateSpnDisplay(); protected abstract void setPowerStateToDesired(); /** * Clean up existing voice and data connection then turn off radio power. * * Hang up the existing voice calls to decrease call drop rate. */ protected abstract void powerOffRadioSafely(); /** Cancel a pending (if any) pollState() operation */ protected void cancelPollState() { // This will effectively cancel the rest of the poll requests. pollingContext = new int[1]; } }