diff options
Diffstat (limited to 'telephony/java/com')
48 files changed, 2194 insertions, 2053 deletions
diff --git a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java b/telephony/java/com/android/internal/telephony/ApnSetting.java index 05527af..5af8e35 100644 --- a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java +++ b/telephony/java/com/android/internal/telephony/ApnSetting.java @@ -14,27 +14,26 @@ * limitations under the License. */ -package com.android.internal.telephony.gsm; +package com.android.internal.telephony; -import com.android.internal.telephony.*; /** * This class represents a apn setting for create PDP link */ public class ApnSetting { - String carrier; - String apn; - String proxy; - String port; - String mmsc; - String mmsProxy; - String mmsPort; - String user; - String password; - int authType; + public String carrier; + public String apn; + public String proxy; + public String port; + public String mmsc; + public String mmsProxy; + public String mmsPort; + public String user; + public String password; + public int authType; public String[] types; - int id; - String numeric; + public int id; + public String numeric; public ApnSetting(int id, String numeric, String carrier, String apn, String proxy, String port, diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java index a8dd9c2..719e5b4 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -380,12 +380,17 @@ public final class CallManager { break; case OFFHOOK: Phone fgPhone = getFgPhone(); - // Enable IN_CALL mode while foreground call is in DIALING, - // ALERTING, ACTIVE and DISCONNECTING state and not from sipPhone + // While foreground call is in DIALING, + // ALERTING, ACTIVE and DISCONNECTING state if (getActiveFgCallState() != Call.State.IDLE - && getActiveFgCallState() != Call.State.DISCONNECTED - && !(fgPhone instanceof SipPhone)) { - mode = AudioManager.MODE_IN_CALL; + && getActiveFgCallState() != Call.State.DISCONNECTED) { + if (fgPhone instanceof SipPhone) { + // enable IN_COMMUNICATION audio mode for sipPhone + mode = AudioManager.MODE_IN_COMMUNICATION; + } else { + // enable IN_CALL audio mode for telephony + mode = AudioManager.MODE_IN_CALL; + } } break; } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 857d105..014901d 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -72,6 +72,7 @@ public class CallerInfo { */ public String name; public String phoneNumber; + public String nomalizedNumber; public String cnapName; public int numberPresentation; @@ -152,6 +153,12 @@ public class CallerInfo { info.phoneNumber = cursor.getString(columnIndex); } + // Look for the normalized number + columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER); + if (columnIndex != -1) { + info.nomalizedNumber = cursor.getString(columnIndex); + } + // Look for the label/type combo columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL); if (columnIndex != -1) { diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 79bb832..c47e076 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -20,6 +20,7 @@ import android.content.AsyncQueryHandler; import android.content.Context; import android.database.Cursor; import android.database.SQLException; +import android.location.CountryDetector; import android.net.Uri; import android.os.Handler; import android.os.Looper; @@ -240,7 +241,11 @@ public class CallerInfoAsyncQuery { // Use the number entered by the user for display. if (!TextUtils.isEmpty(cw.number)) { - mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number); + CountryDetector detector = (CountryDetector) mQueryContext.getSystemService( + Context.COUNTRY_DETECTOR); + mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number, + mCallerInfo.nomalizedNumber, + detector.detectCountry().getCountryIso()); } } diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index 5de0426..c7da3d4 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -27,8 +27,8 @@ import android.os.Handler; */ public interface CommandsInterface { enum RadioState { - RADIO_OFF, /* Radio explictly powered off (eg CFUN=0) */ - RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */ + RADIO_OFF, /* Radio explicitly powered off (e.g. CFUN=0) */ + RADIO_UNAVAILABLE, /* Radio unavailable (e.g. resetting or not booted) */ SIM_NOT_READY, /* Radio is on, but the SIM interface is not ready */ SIM_LOCKED_OR_ABSENT, /* SIM PIN locked, PUK required, network personalization, or SIM absent */ @@ -121,7 +121,7 @@ public interface CommandsInterface { // See 27.007 +CCFC or +CLCK static final int SERVICE_CLASS_NONE = 0; // no user input static final int SERVICE_CLASS_VOICE = (1 << 0); - static final int SERVICE_CLASS_DATA = (1 << 1); //synoym for 16+32+64+128 + static final int SERVICE_CLASS_DATA = (1 << 1); //synonym for 16+32+64+128 static final int SERVICE_CLASS_FAX = (1 << 2); static final int SERVICE_CLASS_SMS = (1 << 3); static final int SERVICE_CLASS_DATA_SYNC = (1 << 4); @@ -951,22 +951,6 @@ public interface CommandsInterface { void writeSmsToRuim(int status, String pdu, Message response); - /** - * @deprecated - * @param apn - * @param user - * @param password - * @param response - */ - void setupDefaultPDP(String apn, String user, String password, Message response); - - /** - * @deprecated - * @param cid - * @param response - */ - void deactivateDefaultPDP(int cid, Message response); - void setRadioPower(boolean on, Message response); void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message response); @@ -974,7 +958,7 @@ public interface CommandsInterface { void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message response); /** - * parameters equivilient to 27.007 AT+CRSM command + * parameters equivalent to 27.007 AT+CRSM command * response.obj will be an AsyncResult * response.obj.userObj will be a IccIoResult on success */ @@ -1079,7 +1063,7 @@ public interface CommandsInterface { /** * (AsyncResult)response.obj).result will be an Integer representing - * the sum of enabled serivice classes (sum of SERVICE_CLASS_*) + * the sum of enabled service classes (sum of SERVICE_CLASS_*) * * @param facility one of CB_FACILTY_* * @param password password or "" if not required @@ -1152,7 +1136,7 @@ public interface CommandsInterface { /** * Request to enable/disable network state change notifications when - * location informateion (lac and/or cid) has changed. + * location information (lac and/or cid) has changed. * * @param enable true to enable, false to disable * @param response callback message @@ -1183,7 +1167,7 @@ public interface CommandsInterface { /** * Indicates to the vendor ril that StkService is running - * rand is eady to receive RIL_UNSOL_STK_XXXX commands. + * and is ready to receive RIL_UNSOL_STK_XXXX commands. * * @param result callback message */ @@ -1354,10 +1338,12 @@ public interface CommandsInterface { * * @param cid * The connection ID + * @param reason + * Data disconnect reason. * @param result * Callback message is empty on completion */ - public void deactivateDataCall(int cid, Message result); + public void deactivateDataCall(int cid, int reason, Message result); /** * Activate or deactivate cell broadcast SMS for CDMA. diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index 6634017..58fb13b 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -16,16 +16,25 @@ package com.android.internal.telephony; -import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.util.HierarchicalState; import com.android.internal.util.HierarchicalStateMachine; +import android.net.LinkAddress; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.AsyncResult; import android.os.Message; import android.os.SystemProperties; +import android.text.TextUtils; import android.util.EventLog; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; + /** * {@hide} * @@ -60,7 +69,7 @@ import android.util.EventLog; * EVENT_GET_LAST_FAIL_DONE, * EVENT_DEACTIVATE_DONE. * } - * ++ # mInactiveState + * ++ # mInactiveState * e(doNotifications) * x(clearNotifications) { * EVENT_RESET { notifiyDisconnectCompleted }. @@ -252,13 +261,13 @@ public abstract class DataConnection extends HierarchicalStateMachine { protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100; //***** Member Variables + protected int mId; protected int mTag; protected PhoneBase phone; + protected RetryManager mRetryMgr; protected int cid; - protected String interfaceName; - protected String ipAddress; - protected String gatewayAddress; - protected String[] dnsServers; + protected LinkProperties mLinkProperties = new LinkProperties(); + protected LinkCapabilities mCapabilities = new LinkCapabilities(); protected long createTime; protected long lastFailTime; protected FailCause lastFailCause; @@ -278,13 +287,12 @@ public abstract class DataConnection extends HierarchicalStateMachine { //***** Constructor - protected DataConnection(PhoneBase phone, String name) { + protected DataConnection(PhoneBase phone, String name, RetryManager rm) { super(name); if (DBG) log("DataConnection constructor E"); this.phone = phone; + mRetryMgr = rm; this.cid = -1; - this.dnsServers = new String[2]; - clearSettings(); setDbg(false); @@ -305,9 +313,19 @@ public abstract class DataConnection extends HierarchicalStateMachine { * and is either a DisconnectParams or ConnectionParams. */ private void tearDownData(Object o) { + int discReason = RILConstants.DEACTIVATE_REASON_NONE; + if ((o != null) && (o instanceof DisconnectParams)) { + DisconnectParams dp = (DisconnectParams)o; + Message m = dp.onCompletedMsg; + if ((m != null) && (m.obj != null) && (m.obj instanceof String)) { + String reason = (String)m.obj; + if (TextUtils.equals(reason, Phone.REASON_RADIO_TURNED_OFF)) + discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF; + } + } if (phone.mCM.getRadioState().isOn()) { if (DBG) log("tearDownData radio is on, call deactivateDataCall"); - phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, o)); + phone.mCM.deactivateDataCall(cid, discReason, obtainMessage(EVENT_DEACTIVATE_DONE, o)); } else { if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately"); AsyncResult ar = new AsyncResult(o, null, null); @@ -353,8 +371,8 @@ public abstract class DataConnection extends HierarchicalStateMachine { if (dp.onCompletedMsg != null) { Message msg = dp.onCompletedMsg; - log(String.format("msg.what=%d msg.obj=%s", - msg.what, ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>"))); + log(String.format("msg=%s msg.obj=%s", msg.toString(), + ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>"))); AsyncResult.forMessage(msg); msg.sendToTarget(); } @@ -367,6 +385,10 @@ public abstract class DataConnection extends HierarchicalStateMachine { clearSettings(); } + public RetryManager getRetryMgr() { + return mRetryMgr; + } + /** * Clear all settings called when entering mInactiveState. */ @@ -377,11 +399,7 @@ public abstract class DataConnection extends HierarchicalStateMachine { this.lastFailTime = -1; this.lastFailCause = FailCause.NONE; - interfaceName = null; - ipAddress = null; - gatewayAddress = null; - dnsServers[0] = null; - dnsServers[1] = null; + mLinkProperties = new LinkProperties(); } /** @@ -416,35 +434,67 @@ public abstract class DataConnection extends HierarchicalStateMachine { // for (int i = 0; i < response.length; i++) { // log(" response[" + i + "]='" + response[i] + "'"); // } + + // Start with clean network properties and if we have + // a failure we'll clear again at the bottom of this code. + LinkProperties linkProperties = new LinkProperties(); if (response.length >= 2) { cid = Integer.parseInt(response[0]); - interfaceName = response[1]; - if (response.length > 2) { - ipAddress = response[2]; + String interfaceName = response[1]; + result = SetupResult.SUCCESS; + + try { String prefix = "net." + interfaceName + "."; - gatewayAddress = SystemProperties.get(prefix + "gw"); + + NetworkInterface networkInterface = NetworkInterface.getByName(interfaceName); + linkProperties.setInterfaceName(interfaceName); + + // TODO: Get gateway and dns via RIL interface not property? + String gatewayAddress = SystemProperties.get(prefix + "gw"); + linkProperties.setGateway(InetAddress.getByName(gatewayAddress)); + + for (InterfaceAddress addr : networkInterface.getInterfaceAddresses()) { + linkProperties.addLinkAddress(new LinkAddress(addr)); + } + // TODO: Get gateway and dns via RIL interface not property? + String dnsServers[] = new String[2]; dnsServers[0] = SystemProperties.get(prefix + "dns1"); dnsServers[1] = SystemProperties.get(prefix + "dns2"); - if (DBG) { - log("interface=" + interfaceName + " ipAddress=" + ipAddress - + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0] - + " DNS2=" + dnsServers[1]); - } - if (isDnsOk(dnsServers)) { - result = SetupResult.SUCCESS; + linkProperties.addDns(InetAddress.getByName(dnsServers[0])); + linkProperties.addDns(InetAddress.getByName(dnsServers[1])); } else { result = SetupResult.ERR_BadDns; } - } else { - result = SetupResult.SUCCESS; + } catch (UnknownHostException e1) { + log("onSetupCompleted: UnknowHostException " + e1); + e1.printStackTrace(); + result = SetupResult.ERR_Other; + } catch (SocketException e2) { + log("onSetupCompleted: SocketException " + e2); + e2.printStackTrace(); + result = SetupResult.ERR_Other; } } else { + log("onSetupCompleted: error; expected number of responses >= 2 was " + + response.length); result = SetupResult.ERR_Other; } + + // An error occurred so clear properties + if (result != SetupResult.SUCCESS) { + log("onSetupCompleted with an error clearing LinkProperties"); + linkProperties.clear(); + } + mLinkProperties = linkProperties; } - if (DBG) log("DataConnection setup result='" + result + "' on cid=" + cid); + if (DBG) { + log("DataConnection setup result='" + result + "' on cid=" + cid); + if (result == SetupResult.SUCCESS) { + log("LinkProperties: " + mLinkProperties.toString()); + } + } return result; } @@ -606,7 +656,16 @@ public abstract class DataConnection extends HierarchicalStateMachine { break; case ERR_BadDns: // Connection succeeded but DNS info is bad so disconnect - EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS, dnsServers[0]); + StringBuilder dnsAddressesSb = new StringBuilder(); + for (InetAddress addr : mLinkProperties.getDnses()) { + if (dnsAddressesSb.length() != 0) dnsAddressesSb.append(" "); + dnsAddressesSb.append(addr.toString()); + } + if (dnsAddressesSb.length() == 0) { + dnsAddressesSb.append("no-dns-addresses"); + } + EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS, + dnsAddressesSb.toString()); tearDownData(cp); transitionTo(mDisconnectingBadDnsState); break; @@ -815,13 +874,13 @@ public abstract class DataConnection extends HierarchicalStateMachine { /** * Connect to the apn and return an AsyncResult in onCompletedMsg. - * Used for cellular networks that use Acess Point Names (APN) such + * Used for cellular networks that use Acesss Point Names (APN) such * as GSM networks. * * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj, * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). - * @param apn is the Acces Point Name to connect to + * @param apn is the Access Point Name to connect to */ public void connect(Message onCompletedMsg, ApnSetting apn) { sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg))); @@ -873,31 +932,29 @@ public abstract class DataConnection extends HierarchicalStateMachine { } /** - * @return the interface name as a string. + * Get the DataConnection ID */ - public String getInterface() { - return interfaceName; + public int getDataConnectionId() { + return mId; } /** - * @return the ip address as a string. - */ - public String getIpAddress() { - return ipAddress; - } - - /** - * @return the gateway address as a string. + * Return the LinkProperties for the connection. + * + * @return a copy of the LinkProperties, is never null. */ - public String getGatewayAddress() { - return gatewayAddress; + public LinkProperties getLinkProperties() { + return new LinkProperties(mLinkProperties); } /** - * @return an array of associated DNS addresses. + * A capability is an Integer/String pair, the capabilities + * are defined in the class LinkSocket#Key. + * + * @return a copy of this connections capabilities, may be empty but never null. */ - public String[] getDnsServers() { - return dnsServers; + public LinkCapabilities getLinkCapabilities() { + return new LinkCapabilities(mCapabilities); } /** diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 265bf7e..737342f 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -17,24 +17,36 @@ package com.android.internal.telephony; import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.net.IConnectivityManager; +import android.net.LinkCapabilities; +import android.net.LinkProperties; +import android.net.NetworkInfo; +import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; -import android.os.RemoteException; +import android.os.Messenger; +import android.os.ServiceManager; +import android.preference.PreferenceManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.util.Log; import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; /** * {@hide} - * */ public abstract class DataConnectionTracker extends Handler { - protected static final boolean DBG = false; - protected final String LOG_TAG = "DataConnectionTracker"; + protected static final boolean DBG = true; /** * IDLE: ready to start data connection setup, default state @@ -70,6 +82,10 @@ public abstract class DataConnectionTracker extends Handler { DORMANT } + public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER = + "com.android.internal.telephony"; + public static String EXTRA_MESSENGER = "EXTRA_MESSENGER"; + /***** Event Codes *****/ protected static final int EVENT_DATA_SETUP_COMPLETE = 1; protected static final int EVENT_RADIO_AVAILABLE = 3; @@ -99,9 +115,11 @@ public abstract class DataConnectionTracker extends Handler { public static final int EVENT_CLEAN_UP_CONNECTION = 34; protected static final int EVENT_CDMA_OTA_PROVISION = 35; protected static final int EVENT_RESTART_RADIO = 36; - protected static final int EVENT_SET_MASTER_DATA_ENABLE = 37; + protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37; protected static final int EVENT_RESET_DONE = 38; + public static final int CMD_SET_DATA_ENABLE = 39; + /***** Constants *****/ protected static final int APN_INVALID_ID = -1; @@ -112,16 +130,23 @@ public abstract class DataConnectionTracker extends Handler { protected static final int APN_HIPRI_ID = 4; protected static final int APN_NUM_TYPES = 5; - protected static final int DISABLED = 0; - protected static final int ENABLED = 1; + public static final int DISABLED = 0; + public static final int ENABLED = 1; + + // responds to the setInternalDataEnabled call - used internally to turn off data + // for example during emergency calls + protected boolean mInternalDataEnabled = true; - // responds to the setDataEnabled call - used independently from the APN requests - protected boolean mMasterDataEnabled = true; + // responds to public (user) API to enable/disable data use + // independent of mInternalDataEnabled and requests for APN access + // persisted + protected boolean mDataEnabled = true; protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES]; + protected int enabledCount = 0; - /* Currently requested APN type */ + /* Currently requested APN type (TODO: This should probably be a parameter not a member) */ protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT; /** Retry configuration: A doubling of retry times from 5secs to 30minutes */ @@ -135,8 +160,6 @@ public abstract class DataConnectionTracker extends Handler { /** Slow poll when attempting connection recovery. */ protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000; - /** Default ping deadline, in seconds. */ - protected static final int DEFAULT_PING_DEADLINE = 5; /** Default max failure count before attempting to network re-registration. */ protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3; @@ -163,20 +186,27 @@ public abstract class DataConnectionTracker extends Handler { // represents an invalid IP address protected static final String NULL_IP = "0.0.0.0"; + // TODO: See if we can remove INTENT_RECONNECT_ALARM + // having to have different values for GSM and + // CDMA. If so we can then remove the need for + // getActionIntentReconnectAlarm. + protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason"; // member variables - protected PhoneBase phone; - protected Activity activity = Activity.NONE; - protected State state = State.IDLE; + protected PhoneBase mPhone; + protected Activity mActivity = Activity.NONE; + protected State mState = State.IDLE; protected Handler mDataConnectionTracker = null; - protected long txPkts, rxPkts, sentSinceLastRecv; - protected int netStatPollPeriod; + protected long mTxPkts; + protected long mRxPkts; + protected long mSentSinceLastRecv; + protected int mNetStatPollPeriod; protected int mNoRecvPollCount = 0; - protected boolean netStatPollEnabled = false; + protected boolean mNetStatPollEnabled = false; - /** Manage the behavior of data retry after failure */ + /** Manage the behavior of data retry after failure (TODO: One per connection in the future?) */ protected RetryManager mRetryMgr = new RetryManager(); // wifi connection status will be updated by sticky intent @@ -186,28 +216,129 @@ public abstract class DataConnectionTracker extends Handler { protected PendingIntent mReconnectIntent = null; /** CID of active data connection */ - protected int cidActive; + protected int mCidActive; + + /** indication of our availability (preconditions to trysetupData are met) **/ + protected boolean mAvailability = false; + + // When false we will not auto attach and manully attaching is required. + protected boolean mAutoAttachOnCreation = false; + + // State of screen + // (TODO: Reconsider tying directly to screen, maybe this is + // really a lower power mode") + protected boolean mIsScreenOn = true; + + /** The link properties (dns, gateway, ip, etc) */ + protected LinkProperties mLinkProperties = new LinkProperties(); + + /** The link capabilities */ + protected LinkCapabilities mLinkCapabilities = new LinkCapabilities(); + + /** Allows the generation of unique Id's for DataConnection objects */ + protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0); + + /** The data connections. */ + protected HashMap<Integer, DataConnection> mDataConnections = + new HashMap<Integer, DataConnection>(); + + /* Currently active APN */ + protected ApnSetting mActiveApn; + + protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver () + { + @Override + public void onReceive(Context context, Intent intent) + { + String action = intent.getAction(); + if (action.equals(Intent.ACTION_SCREEN_ON)) { + mIsScreenOn = true; + stopNetStatPoll(); + startNetStatPoll(); + } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { + mIsScreenOn = false; + stopNetStatPoll(); + startNetStatPoll(); + } else if (action.equals(getActionIntentReconnectAlarm())) { + log("Reconnect alarm. Previous state was " + mState); + + String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON); + if (mState == State.FAILED) { + Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION); + msg.arg1 = 0; // tearDown is false + msg.obj = reason; + sendMessage(msg); + } + sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA)); + } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + final android.net.NetworkInfo networkInfo = (NetworkInfo) + intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + mIsWifiConnected = (networkInfo != null && networkInfo.isConnected()); + } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; + + if (!enabled) { + // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION + // quit and won't report disconnected until next enabling. + mIsWifiConnected = false; + } + } + } + }; - /** + /** * Default constructor */ protected DataConnectionTracker(PhoneBase phone) { super(); - this.phone = phone; + mPhone = phone; + + IntentFilter filter = new IntentFilter(); + filter.addAction(getActionIntentReconnectAlarm()); + filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + + mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(), + Settings.Secure.MOBILE_DATA, 1) == 1; + + // TODO: Why is this registering the phone as the receiver of the intent + // and not its own handler? + mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); + + // This preference tells us 1) initial condition for "dataEnabled", + // and 2) whether the RIL will setup the baseband to auto-PS attach. + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()); + dataEnabled[APN_DEFAULT_ID] = + !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false); + if (dataEnabled[APN_DEFAULT_ID]) { + enabledCount++; + } + mAutoAttachOnCreation = dataEnabled[APN_DEFAULT_ID]; + } + + public void dispose() { + mPhone.getContext().unregisterReceiver(this.mIntentReceiver); } - public abstract void dispose(); + protected void broadcastMessenger() { + Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER); + intent.putExtra(EXTRA_MESSENGER, new Messenger(this)); + mPhone.getContext().sendBroadcast(intent); + } public Activity getActivity() { - return activity; + return mActivity; } public State getState() { - return state; + return mState; } public String getStateInString() { - switch (state) { + switch (mState) { case IDLE: return "IDLE"; case INITING: return "INIT"; case CONNECTING: return "CING"; @@ -220,6 +351,48 @@ public abstract class DataConnectionTracker extends Handler { } /** + * @return the data connections + */ + public ArrayList<DataConnection> getAllDataConnections() { + /** TODO: change return type to Collection? */ + return new ArrayList<DataConnection>(mDataConnections.values()); + } + + protected boolean isApnTypeActive(String type) { + // TODO: support simultaneous with List instead + return mActiveApn != null && mActiveApn.canHandleType(type); + } + + public String[] getActiveApnTypes() { + String[] result; + if (mActiveApn != null) { + result = mActiveApn.types; + } else { + result = new String[1]; + result[0] = Phone.APN_TYPE_DEFAULT; + } + return result; + } + + public String getActiveApnType() { + String result; + if (mActiveApn != null) { + result = apnIdToType(mActiveApn.id); + } else { + result = null; + } + return result; + } + + protected String getActiveApnString() { + String result = null; + if (mActiveApn != null) { + result = mActiveApn.apn; + } + return result; + } + + /** * The data connection is expected to be setup while device * 1. has Icc card * 2. registered for data service @@ -235,9 +408,9 @@ public abstract class DataConnectionTracker extends Handler { // the shared values. If it is not, then update it. public void setDataOnRoamingEnabled(boolean enabled) { if (getDataOnRoamingEnabled() != enabled) { - Settings.Secure.putInt(phone.getContext().getContentResolver(), + Settings.Secure.putInt(mPhone.getContext().getContentResolver(), Settings.Secure.DATA_ROAMING, enabled ? 1 : 0); - if (phone.getServiceState().getRoaming()) { + if (mPhone.getServiceState().getRoaming()) { if (enabled) { mRetryMgr.resetRetryCount(); } @@ -246,16 +419,19 @@ public abstract class DataConnectionTracker extends Handler { } } - //Retrieve the data roaming setting from the shared preferences. + // Retrieve the data roaming setting from the shared preferences. public boolean getDataOnRoamingEnabled() { try { - return Settings.Secure.getInt(phone.getContext().getContentResolver(), - Settings.Secure.DATA_ROAMING) > 0; + return Settings.Secure.getInt( + mPhone.getContext().getContentResolver(), Settings.Secure.DATA_ROAMING) > 0; } catch (SettingNotFoundException snfe) { return false; } } + + protected abstract String getActionIntentReconnectAlarm(); + // abstract handler methods protected abstract boolean onTrySetupData(String reason); protected abstract void onRoamingOff(); @@ -263,14 +439,14 @@ public abstract class DataConnectionTracker extends Handler { protected abstract void onRadioAvailable(); protected abstract void onRadioOffOrNotAvailable(); protected abstract void onDataSetupComplete(AsyncResult ar); - protected abstract void onDisconnectDone(AsyncResult ar); + protected abstract void onDisconnectDone(int connId, AsyncResult ar); protected abstract void onResetDone(AsyncResult ar); protected abstract void onVoiceCallStarted(); protected abstract void onVoiceCallEnded(); protected abstract void onCleanUpConnection(boolean tearDown, String reason); @Override - public void handleMessage (Message msg) { + public void handleMessage(Message msg) { switch (msg.what) { case EVENT_ENABLE_NEW_APN: @@ -280,7 +456,7 @@ public abstract class DataConnectionTracker extends Handler { case EVENT_TRY_SETUP_DATA: String reason = null; if (msg.obj instanceof String) { - reason = (String)msg.obj; + reason = (String) msg.obj; } onTrySetupData(reason); break; @@ -305,12 +481,13 @@ public abstract class DataConnectionTracker extends Handler { break; case EVENT_DATA_SETUP_COMPLETE: - cidActive = msg.arg1; + mCidActive = msg.arg1; onDataSetupComplete((AsyncResult) msg.obj); break; case EVENT_DISCONNECT_DONE: - onDisconnectDone((AsyncResult) msg.obj); + log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg); + onDisconnectDone(msg.arg1, (AsyncResult) msg.obj); break; case EVENT_VOICE_CALL_STARTED: @@ -323,17 +500,23 @@ public abstract class DataConnectionTracker extends Handler { case EVENT_CLEAN_UP_CONNECTION: boolean tearDown = (msg.arg1 == 0) ? false : true; - onCleanUpConnection(tearDown, (String)msg.obj); + onCleanUpConnection(tearDown, (String) msg.obj); break; - case EVENT_SET_MASTER_DATA_ENABLE: + case EVENT_SET_INTERNAL_DATA_ENABLE: { boolean enabled = (msg.arg1 == ENABLED) ? true : false; - onSetDataEnabled(enabled); + onSetInternalDataEnabled(enabled); break; - + } case EVENT_RESET_DONE: onResetDone((AsyncResult) msg.obj); break; + case CMD_SET_DATA_ENABLE: { + log("CMD_SET_DATA_ENABLE msg=" + msg); + boolean enabled = (msg.arg1 == ENABLED) ? true : false; + onSetDataEnabled(enabled); + break; + } default: Log.e("DATA", "Unidentified event = " + msg.what); @@ -342,21 +525,13 @@ public abstract class DataConnectionTracker extends Handler { } /** - * Report the current state of data connectivity (enabled or disabled) - * @return {@code false} if data connectivity has been explicitly disabled, - * {@code true} otherwise. - */ - public synchronized boolean getDataEnabled() { - return dataEnabled[APN_DEFAULT_ID]; - } - - /** * Report on whether data connectivity is enabled + * * @return {@code false} if data connectivity has been explicitly disabled, - * {@code true} otherwise. + * {@code true} otherwise. */ - public boolean getAnyDataEnabled() { - return (enabledCount != 0); + public synchronized boolean getAnyDataEnabled() { + return (mInternalDataEnabled && mDataEnabled && (enabledCount != 0)); } protected abstract void startNetStatPoll(); @@ -367,6 +542,8 @@ public abstract class DataConnectionTracker extends Handler { protected abstract void log(String s); + protected abstract void loge(String s); + protected int apnTypeToId(String type) { if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) { return APN_DEFAULT_ID; @@ -396,32 +573,136 @@ public abstract class DataConnectionTracker extends Handler { case APN_HIPRI_ID: return Phone.APN_TYPE_HIPRI; default: - Log.e(LOG_TAG, "Unknown id (" + id + ") in apnIdToType"); + log("Unknown id (" + id + ") in apnIdToType"); return Phone.APN_TYPE_DEFAULT; } } - protected abstract boolean isApnTypeActive(String type); - protected abstract boolean isApnTypeAvailable(String type); - protected abstract String[] getActiveApnTypes(); + protected abstract void setState(State s); - protected abstract String getActiveApnString(); + protected LinkProperties getLinkProperties(String apnType) { + int id = apnTypeToId(apnType); + if (isApnIdEnabled(id)) { + return new LinkProperties(mLinkProperties); + } else { + return new LinkProperties(); + } + } - public abstract ArrayList<DataConnection> getAllDataConnections(); + protected LinkCapabilities getLinkCapabilities(String apnType) { + int id = apnTypeToId(apnType); + if (isApnIdEnabled(id)) { + return new LinkCapabilities(mLinkCapabilities); + } else { + return new LinkCapabilities(); + } + } - protected abstract String getInterfaceName(String apnType); + /** + * Return the LinkProperties for the connection. + * + * @param connection + * @return a copy of the LinkProperties, is never null. + */ + protected LinkProperties getLinkProperties(DataConnection connection) { + return connection.getLinkProperties(); + } - protected abstract String getIpAddress(String apnType); + /** + * A capability is an Integer/String pair, the capabilities + * are defined in the class LinkSocket#Key. + * + * @param connection + * @return a copy of this connections capabilities, may be empty but never null. + */ + protected LinkCapabilities getLinkCapabilities(DataConnection connection) { + return connection.getLinkCapabilities(); + } - protected abstract String getGateway(String apnType); + // tell all active apns of the current condition + protected void notifyDataConnection(String reason) { + for (int id = 0; id < APN_NUM_TYPES; id++) { + if (dataEnabled[id]) { + mPhone.notifyDataConnection(reason, apnIdToType(id)); + } + } + notifyDataAvailability(reason); + } - protected abstract String[] getDnsServers(String apnType); + // a new APN has gone active and needs to send events to catch up with the + // current condition + private void notifyApnIdUpToCurrent(String reason, int apnId) { + switch (mState) { + case IDLE: + case INITING: + break; + case CONNECTING: + case SCANNING: + mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING); + break; + case CONNECTED: + case DISCONNECTING: + mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING); + mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED); + break; + } + } - protected abstract void setState(State s); + // since we normally don't send info to a disconnected APN, we need to do this specially + private void notifyApnIdDisconnected(String reason, int apnId) { + mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED); + } + + // disabled apn's still need avail/unavail notificiations - send them out + protected void notifyOffApnsOfAvailability(String reason, boolean availability) { + if (mAvailability == availability) return; + mAvailability = availability; + for (int id = 0; id < APN_NUM_TYPES; id++) { + if (!isApnIdEnabled(id)) { + notifyApnIdDisconnected(reason, id); + } + } + } + + // we had an availability change - tell the listeners + protected void notifyDataAvailability(String reason) { + // note that we either just turned all off because we lost availability + // or all were off and could now go on, so only have off apns to worry about + notifyOffApnsOfAvailability(reason, isDataPossible()); + } - protected synchronized boolean isEnabled(int id) { + /** + * The only circumstances under which we report that data connectivity is not + * possible are + * <ul> + * <li>Data is disallowed (roaming, power state, voice call, etc).</li> + * <li>The current data state is {@code DISCONNECTED} for a reason other than + * having explicitly disabled connectivity. In other words, data is not available + * because the phone is out of coverage or some like reason.</li> + * </ul> + * @return {@code true} if data connectivity is possible, {@code false} otherwise. + */ + protected boolean isDataPossible() { + boolean possible = (isDataAllowed() + && !(getAnyDataEnabled() && (mState == State.FAILED || mState == State.IDLE))); + if (!possible && DBG && isDataAllowed()) { + log("Data not possible. No coverage: dataState = " + mState); + } + return possible; + } + + protected abstract boolean isDataAllowed(); + + public boolean isApnTypeEnabled(String apnType) { + if (apnType == null) { + apnType = getActiveApnType(); + } + return isApnIdEnabled(apnTypeToId(apnType)); + } + + protected synchronized boolean isApnIdEnabled(int id) { if (id != APN_INVALID_ID) { return dataEnabled[id]; } @@ -430,13 +711,13 @@ public abstract class DataConnectionTracker extends Handler { /** * Ensure that we are connected to an APN of the specified type. - * @param type the APN type (currently the only valid values - * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}) - * @return the result of the operation. Success is indicated by - * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or - * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast - * will be sent by the ConnectivityManager when a connection to - * the APN has been established. + * + * @param type the APN type (currently the only valid values are + * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}) + * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or + * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a + * broadcast will be sent by the ConnectivityManager when a + * connection to the APN has been established. */ public synchronized int enableApnType(String type) { int id = apnTypeToId(type); @@ -444,41 +725,45 @@ public abstract class DataConnectionTracker extends Handler { return Phone.APN_REQUEST_FAILED; } - if (DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = " - + isApnTypeActive(type) + " and state = " + state); + if (DBG) { + log("enableApnType(" + type + "), isApnTypeActive = " + isApnTypeActive(type) + + ", isApnIdEnabled =" + isApnIdEnabled(id) + " and state = " + mState); + } if (!isApnTypeAvailable(type)) { - if (DBG) Log.d(LOG_TAG, "type not available"); + if (DBG) log("type not available"); return Phone.APN_TYPE_NOT_AVAILABLE; } - // just because it's active doesn't mean we had it explicitly requested before - // (a broad default may handle many types). make sure we mark it enabled - // so if the default is disabled we keep the connection for others - setEnabled(id, true); - - if (isApnTypeActive(type)) { - if (state == State.INITING) return Phone.APN_REQUEST_STARTED; - else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE; + if (isApnIdEnabled(id)) { + return Phone.APN_ALREADY_ACTIVE; + } else { + setEnabled(id, true); } return Phone.APN_REQUEST_STARTED; } /** - * The APN of the specified type is no longer needed. Ensure that if - * use of the default APN has not been explicitly disabled, we are connected - * to the default APN. + * The APN of the specified type is no longer needed. Ensure that if use of + * the default APN has not been explicitly disabled, we are connected to the + * default APN. + * * @param type the APN type. The only valid values are currently - * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}. - * @return + * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}. + * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or + * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a + * broadcast will be sent by the ConnectivityManager when a + * connection to the APN has been disconnected. A {@code + * Phone.APN_REQUEST_FAILED} is returned if the type parameter is + * invalid or if the apn wasn't enabled. */ public synchronized int disableApnType(String type) { - if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")"); + if (DBG) log("disableApnType(" + type + ")"); int id = apnTypeToId(type); if (id == APN_INVALID_ID) { return Phone.APN_REQUEST_FAILED; } - if (isEnabled(id)) { + if (isApnIdEnabled(id)) { setEnabled(id, false); if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { if (dataEnabled[APN_DEFAULT_ID]) { @@ -495,9 +780,10 @@ public abstract class DataConnectionTracker extends Handler { } private void setEnabled(int id, boolean enable) { - if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " + - dataEnabled[id] + " and enabledCount = " + enabledCount); - + if (DBG) { + log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id] + + " and enabledCount = " + enabledCount); + } Message msg = obtainMessage(EVENT_ENABLE_NEW_APN); msg.arg1 = id; msg.arg2 = (enable ? ENABLED : DISABLED); @@ -506,10 +792,10 @@ public abstract class DataConnectionTracker extends Handler { protected synchronized void onEnableApn(int apnId, int enabled) { if (DBG) { - Log.d(LOG_TAG, "EVENT_APN_ENABLE_REQUEST " + apnId + ", " + enabled); - Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] + - ", enabledCount = " + enabledCount + - ", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId))); + log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) + + ", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] + + ", enabledCount = " + enabledCount + ", isApnTypeActive = " + + isApnTypeActive(apnIdToType(apnId))); } if (enabled == ENABLED) { if (!dataEnabled[apnId]) { @@ -520,6 +806,8 @@ public abstract class DataConnectionTracker extends Handler { if (!isApnTypeActive(type)) { mRequestedApnType = type; onEnableNewApn(); + } else { + notifyApnIdUpToCurrent(Phone.REASON_APN_SWITCHED, apnId); } } else { // disable @@ -528,8 +816,17 @@ public abstract class DataConnectionTracker extends Handler { enabledCount--; if (enabledCount == 0) { onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); - } else if (dataEnabled[APN_DEFAULT_ID] == true && - !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { + } + + // send the disconnect msg manually, since the normal route wont send + // it (it's not enabled) + notifyApnIdDisconnected(Phone.REASON_DATA_DISABLED, apnId); + if (dataEnabled[APN_DEFAULT_ID] == true + && !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { + // TODO - this is an ugly way to restore the default conn - should be done + // by a real contention manager and policy that disconnects the lower pri + // stuff as enable requests come in and pops them back on as we disable back + // down to the lower pri stuff mRequestedApnType = Phone.APN_TYPE_DEFAULT; onEnableNewApn(); } @@ -547,36 +844,61 @@ public abstract class DataConnectionTracker extends Handler { } /** - * Prevent mobile data connections from being established, - * or once again allow mobile data connections. If the state - * toggles, then either tear down or set up data, as - * appropriate to match the new state. - * <p>This operation only affects the default APN, and if the same APN is - * currently being used for MMS traffic, the teardown will not happen - * even when {@code enable} is {@code false}.</p> - * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data + * Prevent mobile data connections from being established, or once again + * allow mobile data connections. If the state toggles, then either tear + * down or set up data, as appropriate to match the new state. + * + * @param enable indicates whether to enable ({@code true}) or disable ( + * {@code false}) data * @return {@code true} if the operation succeeded */ - public boolean setDataEnabled(boolean enable) { - if (DBG) Log.d(LOG_TAG, "setDataEnabled(" + enable + ")"); + public boolean setInternalDataEnabled(boolean enable) { + if (DBG) + log("setInternalDataEnabled(" + enable + ")"); - Message msg = obtainMessage(EVENT_SET_MASTER_DATA_ENABLE); + Message msg = obtainMessage(EVENT_SET_INTERNAL_DATA_ENABLE); msg.arg1 = (enable ? ENABLED : DISABLED); sendMessage(msg); return true; } - protected void onSetDataEnabled(boolean enable) { - if (mMasterDataEnabled != enable) { - mMasterDataEnabled = enable; - if (enable) { - mRetryMgr.resetRetryCount(); - onTrySetupData(Phone.REASON_DATA_ENABLED); - } else { - onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); - } + protected void onSetInternalDataEnabled(boolean enable) { + boolean prevEnabled = getAnyDataEnabled(); + if (mInternalDataEnabled != enable) { + synchronized (this) { + mInternalDataEnabled = enable; + } + if (prevEnabled != getAnyDataEnabled()) { + if (!prevEnabled) { + mRetryMgr.resetRetryCount(); + onTrySetupData(Phone.REASON_DATA_ENABLED); + } else { + onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); + } + } } } + public synchronized boolean getDataEnabled() { + return mDataEnabled; + } + protected void onSetDataEnabled(boolean enable) { + boolean prevEnabled = getAnyDataEnabled(); + if (mDataEnabled != enable) { + synchronized (this) { + mDataEnabled = enable; + } + Settings.Secure.putInt(mPhone.getContext().getContentResolver(), + Settings.Secure.MOBILE_DATA, enable ? 1 : 0); + if (prevEnabled != getAnyDataEnabled()) { + if (!prevEnabled) { + mRetryMgr.resetRetryCount(); + onTrySetupData(Phone.REASON_DATA_ENABLED); + } else { + onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); + } + } + } + } } diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java index 057ba0a..83db3d1 100644 --- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; @@ -92,26 +94,41 @@ public class DefaultPhoneNotifier implements PhoneNotifier { } } - public void notifyDataConnection(Phone sender, String reason) { + public void notifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { + doNotifyDataConnection(sender, reason, apnType, state); + } + + private void doNotifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { + // TODO + // use apnType as the key to which connection we're talking about. + // pass apnType back up to fetch particular for this one. TelephonyManager telephony = TelephonyManager.getDefault(); + LinkProperties linkProperties = null; + LinkCapabilities linkCapabilities = null; + if (state == Phone.DataState.CONNECTED) { + linkProperties = sender.getLinkProperties(apnType); + linkCapabilities = sender.getLinkCapabilities(apnType); + } try { mRegistry.notifyDataConnection( - convertDataState(sender.getDataConnectionState()), + convertDataState(state), sender.isDataConnectivityPossible(), reason, - sender.getActiveApn(), - sender.getActiveApnTypes(), - sender.getInterfaceName(null), + sender.getActiveApnHost(), + apnType, + linkProperties, + linkCapabilities, ((telephony!=null) ? telephony.getNetworkType() : - TelephonyManager.NETWORK_TYPE_UNKNOWN), - sender.getGateway(null)); + TelephonyManager.NETWORK_TYPE_UNKNOWN)); } catch (RemoteException ex) { // system process is dead } } - public void notifyDataConnectionFailed(Phone sender, String reason) { + public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) { try { - mRegistry.notifyDataConnectionFailed(reason); + mRegistry.notifyDataConnectionFailed(reason, apnType); } catch (RemoteException ex) { // system process is dead } @@ -127,6 +144,14 @@ public class DefaultPhoneNotifier implements PhoneNotifier { } } + public void notifyOtaspChanged(Phone sender, int otaspMode) { + try { + mRegistry.notifyOtaspChanged(otaspMode); + } catch (RemoteException ex) { + // system process is dead + } + } + private void log(String s) { Log.d(LOG_TAG, "[PhoneNotifier] " + s); } diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java index 30ee77c..e42827f 100644 --- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java @@ -16,11 +16,14 @@ package com.android.internal.telephony; -import android.telephony.SmsMessage; +import android.text.TextUtils; import android.util.SparseIntArray; import android.util.Log; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + /** * This class implements the character set mapping between * the GSM SMS 7-bit alphabet specified in TS 23.038 6.2.1 @@ -320,7 +323,7 @@ public class GsmAlphabet { gsmVal = (0x7f & (pdu[offset + byteOffset] >> shift)); - // if it crosses a byte boundry + // if it crosses a byte boundary if (shift > 1) { // set msb bits to 0 gsmVal &= 0x7f >> (shift - 1); @@ -355,6 +358,32 @@ public class GsmAlphabet { */ public static String gsm8BitUnpackedToString(byte[] data, int offset, int length) { + return gsm8BitUnpackedToString(data, offset, length, ""); + } + + /** + * Convert a GSM alphabet string that's stored in 8-bit unpacked + * format (as it often appears in SIM records) into a String + * + * Field may be padded with trailing 0xff's. The decode stops + * at the first 0xff encountered. + * + * Additionally, in some country(ex. Korea), there are non-ASCII or MBCS characters. + * If a character set is given, characters in data are treat as MBCS. + */ + public static String + gsm8BitUnpackedToString(byte[] data, int offset, int length, String characterset) { + boolean isMbcs = false; + Charset charset = null; + ByteBuffer mbcsBuffer = null; + + if (!TextUtils.isEmpty(characterset) + && !characterset.equalsIgnoreCase("us-ascii") + && Charset.isSupported(characterset)) { + isMbcs = true; + charset = Charset.forName(characterset); + mbcsBuffer = ByteBuffer.allocate(2); + } boolean prevWasEscape; StringBuilder ret = new StringBuilder(length); @@ -380,7 +409,15 @@ public class GsmAlphabet { if (prevWasEscape) { ret.append((char)gsmExtendedToChar.get(c, ' ')); } else { - ret.append((char)gsmToChar.get(c, ' ')); + if (!isMbcs || c < 0x80 || i + 1 >= offset + length) { + ret.append((char)gsmToChar.get(c, ' ')); + } else { + // isMbcs must be true. So both mbcsBuffer and charset are initialized. + mbcsBuffer.clear(); + mbcsBuffer.put(data, i++, 2); + mbcsBuffer.flip(); + ret.append(charset.decode(mbcsBuffer).toString()); + } } prevWasEscape = false; } diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl index 856d663..082c097 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -32,5 +32,6 @@ oneway interface IPhoneStateListener { void onDataConnectionStateChanged(int state, int networkType); void onDataActivity(int direction); void onSignalStrengthsChanged(in SignalStrength signalStrength); + void onOtaspChanged(in int otaspMode); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 2328717..3c4bb12 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -66,7 +66,7 @@ interface ITelephony { boolean showCallScreenWithDialpad(boolean showDialpad); /** - * End call or go to the Home screen + * End call if there is a call in progress, otherwise does nothing. * * @return whether it hung up */ @@ -239,9 +239,11 @@ interface ITelephony { String getCdmaEriText(); /** - * Returns true if CDMA provisioning needs to run. + * Returns true if OTA service provisioning needs to run. + * Only relevant on some technologies, others will always + * return false. */ - boolean getCdmaNeedsProvisioning(); + boolean needsOtaServiceProvisioning(); /** * Returns the unread count of voicemails diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 87e4b52..3c83e50 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -17,6 +17,8 @@ package com.android.internal.telephony; import android.content.Intent; +import android.net.LinkProperties; +import android.net.LinkCapabilities; import android.os.Bundle; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -32,8 +34,9 @@ interface ITelephonyRegistry { void notifyCallForwardingChanged(boolean cfi); void notifyDataActivity(int state); void notifyDataConnection(int state, boolean isDataConnectivityPossible, - String reason, String apn, in String[] apnTypes, String interfaceName, int networkType, - String gateway); - void notifyDataConnectionFailed(String reason); + String reason, String apn, String apnType, in LinkProperties linkProperties, + in LinkCapabilities linkCapabilities, int networkType); + void notifyDataConnectionFailed(String reason, String apnType); void notifyCellLocation(in Bundle cellLocation); + void notifyOtaspChanged(in int otaspMode); } diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java index 957eddd..df579b0 100644 --- a/telephony/java/com/android/internal/telephony/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/IccUtils.java @@ -16,13 +16,16 @@ package com.android.internal.telephony; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.Color; import android.util.Log; import com.android.internal.telephony.GsmAlphabet; - import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; /** * Various methods, useful for dealing with SIM data. @@ -150,6 +153,9 @@ public class IccUtils { */ public static String adnStringFieldToString(byte[] data, int offset, int length) { + if (length == 0) { + return ""; + } if (length >= 1) { if (data[offset] == (byte) 0x80) { int ucslen = (length - 1) / 2; @@ -225,7 +231,15 @@ public class IccUtils { return ret.toString(); } - return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length); + Resources resource = Resources.getSystem(); + String defaultCharset = ""; + try { + defaultCharset = + resource.getString(com.android.internal.R.string.gsm_alphabet_default_charset); + } catch (NotFoundException e) { + // Ignore Exception and defaultCharset is set to a empty string. + } + return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length, defaultCharset.trim()); } static int @@ -267,9 +281,11 @@ public class IccUtils { /** - * Converts a byte array into a String hexidecimal characters + * Converts a byte array into a String of hexadecimal characters. + * + * @param bytes an array of bytes * - * null returns null + * @return hex string representation of bytes array */ public static String bytesToHexString(byte[] bytes) { diff --git a/telephony/java/com/android/internal/telephony/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java index 5539057..c0bf7ec 100644 --- a/telephony/java/com/android/internal/telephony/MccTable.java +++ b/telephony/java/com/android/internal/telephony/MccTable.java @@ -23,346 +23,13 @@ import android.content.res.Configuration; import android.net.wifi.WifiManager; import android.os.RemoteException; import android.os.SystemProperties; -import android.provider.Settings; import android.text.TextUtils; import android.util.Log; -import java.util.Arrays; - -/** - * The table below is built from two resources: - * - * 1) ITU "Mobile Network Code (MNC) for the international - * identification plan for mobile terminals and mobile users" - * which is available as an annex to the ITU operational bulletin - * available here: http://www.itu.int/itu-t/bulletin/annex.html - * - * 2) The ISO 3166 country codes list, available here: - * http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html - * - * This table was verified (28 Aug 2009) against - * http://en.wikipedia.org/wiki/List_of_mobile_country_codes with the - * only unresolved discrepancy being that this list has an extra entry - * (461) for China. - * - * TODO: Complete the mappings for timezones and language/locale codes. - * - * The actual table data used in the Java code is generated from the - * below Python code for efficiency. The information is expected to - * be static, but if changes are required, the table in the python - * code can be modified and the trailing code run to re-generate the - * tables that are to be used by Java. - -mcc_table = [ - (202, 'gr', 2, 'Greece'), - (204, 'nl', 2, 'Europe/Amsterdam', 'nl', 13, 'Netherlands (Kingdom of the)'), - (206, 'be', 2, 'Belgium'), - (208, 'fr', 2, 'Europe/Paris', 'fr', 'France'), - (212, 'mc', 2, 'Monaco (Principality of)'), - (213, 'ad', 2, 'Andorra (Principality of)'), - (214, 'es', 2, 'Europe/Madrid', 'es', 'Spain'), - (216, 'hu', 2, 'Hungary (Republic of)'), - (218, 'ba', 2, 'Bosnia and Herzegovina'), - (219, 'hr', 2, 'Croatia (Republic of)'), - (220, 'rs', 2, 'Serbia and Montenegro'), - (222, 'it', 2, 'Europe/Rome', 'it', 'Italy'), - (225, 'va', 2, 'Europe/Rome', 'it', 'Vatican City State'), - (226, 'ro', 2, 'Romania'), - (228, 'ch', 2, 'Europe/Zurich', 'de', 'Switzerland (Confederation of)'), - (230, 'cz', 2, 'Europe/Prague', 'cs', 13, 'Czech Republic'), - (231, 'sk', 2, 'Slovak Republic'), - (232, 'at', 2, 'Europe/Vienna', 'de', 13, 'Austria'), - (234, 'gb', 2, 'Europe/London', 'en', 13, 'United Kingdom of Great Britain and Northern Ireland'), - (235, 'gb', 2, 'Europe/London', 'en', 13, 'United Kingdom of Great Britain and Northern Ireland'), - (238, 'dk', 2, 'Denmark'), - (240, 'se', 2, 'Sweden'), - (242, 'no', 2, 'Norway'), - (244, 'fi', 2, 'Finland'), - (246, 'lt', 2, 'Lithuania (Republic of)'), - (247, 'lv', 2, 'Latvia (Republic of)'), - (248, 'ee', 2, 'Estonia (Republic of)'), - (250, 'ru', 2, 'Russian Federation'), - (255, 'ua', 2, 'Ukraine'), - (257, 'by', 2, 'Belarus (Republic of)'), - (259, 'md', 2, 'Moldova (Republic of)'), - (260, 'pl', 2, 'Europe/Warsaw', 'Poland (Republic of)'), - (262, 'de', 2, 'Europe/Berlin', 'de', 13, 'Germany (Federal Republic of)'), - (266, 'gi', 2, 'Gibraltar'), - (268, 'pt', 2, 'Portugal'), - (270, 'lu', 2, 'Luxembourg'), - (272, 'ie', 2, 'Europe/Dublin', 'en', 'Ireland'), - (274, 'is', 2, 'Iceland'), - (276, 'al', 2, 'Albania (Republic of)'), - (278, 'mt', 2, 'Malta'), - (280, 'cy', 2, 'Cyprus (Republic of)'), - (282, 'ge', 2, 'Georgia'), - (283, 'am', 2, 'Armenia (Republic of)'), - (284, 'bg', 2, 'Bulgaria (Republic of)'), - (286, 'tr', 2, 'Turkey'), - (288, 'fo', 2, 'Faroe Islands'), - (289, 'ge', 2, 'Abkhazia (Georgia)'), - (290, 'gl', 2, 'Greenland (Denmark)'), - (292, 'sm', 2, 'San Marino (Republic of)'), - (293, 'sl', 2, 'Slovenia (Republic of)'), - (294, 'mk', 2, 'The Former Yugoslav Republic of Macedonia'), - (295, 'li', 2, 'Liechtenstein (Principality of)'), - (297, 'me', 2, 'Montenegro (Republic of)'), - (302, 'ca', 3, '', '', 11, 'Canada'), - (308, 'pm', 2, 'Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)'), - (310, 'us', 3, '', 'en', 11, 'United States of America'), - (311, 'us', 3, '', 'en', 11, 'United States of America'), - (312, 'us', 3, '', 'en', 11, 'United States of America'), - (313, 'us', 3, '', 'en', 11, 'United States of America'), - (314, 'us', 3, '', 'en', 11, 'United States of America'), - (315, 'us', 3, '', 'en', 11, 'United States of America'), - (316, 'us', 3, '', 'en', 11, 'United States of America'), - (330, 'pr', 2, 'Puerto Rico'), - (332, 'vi', 2, 'United States Virgin Islands'), - (334, 'mx', 3, 'Mexico'), - (338, 'jm', 3, 'Jamaica'), - (340, 'gp', 2, 'Guadeloupe (French Department of)'), - (342, 'bb', 3, 'Barbados'), - (344, 'ag', 3, 'Antigua and Barbuda'), - (346, 'ky', 3, 'Cayman Islands'), - (348, 'vg', 3, 'British Virgin Islands'), - (350, 'bm', 2, 'Bermuda'), - (352, 'gd', 2, 'Grenada'), - (354, 'ms', 2, 'Montserrat'), - (356, 'kn', 2, 'Saint Kitts and Nevis'), - (358, 'lc', 2, 'Saint Lucia'), - (360, 'vc', 2, 'Saint Vincent and the Grenadines'), - (362, 'nl', 2, 'Netherlands Antilles'), - (363, 'aw', 2, 'Aruba'), - (364, 'bs', 2, 'Bahamas (Commonwealth of the)'), - (365, 'ai', 3, 'Anguilla'), - (366, 'dm', 2, 'Dominica (Commonwealth of)'), - (368, 'cu', 2, 'Cuba'), - (370, 'do', 2, 'Dominican Republic'), - (372, 'ht', 2, 'Haiti (Republic of)'), - (374, 'tt', 2, 'Trinidad and Tobago'), - (376, 'tc', 2, 'Turks and Caicos Islands'), - (400, 'az', 2, 'Azerbaijani Republic'), - (401, 'kz', 2, 'Kazakhstan (Republic of)'), - (402, 'bt', 2, 'Bhutan (Kingdom of)'), - (404, 'in', 2, 'India (Republic of)'), - (405, 'in', 2, 'India (Republic of)'), - (410, 'pk', 2, 'Pakistan (Islamic Republic of)'), - (412, 'af', 2, 'Afghanistan'), - (413, 'lk', 2, 'Sri Lanka (Democratic Socialist Republic of)'), - (414, 'mm', 2, 'Myanmar (Union of)'), - (415, 'lb', 2, 'Lebanon'), - (416, 'jo', 2, 'Jordan (Hashemite Kingdom of)'), - (417, 'sy', 2, 'Syrian Arab Republic'), - (418, 'iq', 2, 'Iraq (Republic of)'), - (419, 'kw', 2, 'Kuwait (State of)'), - (420, 'sa', 2, 'Saudi Arabia (Kingdom of)'), - (421, 'ye', 2, 'Yemen (Republic of)'), - (422, 'om', 2, 'Oman (Sultanate of)'), - (423, 'ps', 2, 'Palestine'), - (424, 'ae', 2, 'United Arab Emirates'), - (425, 'il', 2, 'Israel (State of)'), - (426, 'bh', 2, 'Bahrain (Kingdom of)'), - (427, 'qa', 2, 'Qatar (State of)'), - (428, 'mn', 2, 'Mongolia'), - (429, 'np', 2, 'Nepal'), - (430, 'ae', 2, 'United Arab Emirates'), - (431, 'ae', 2, 'United Arab Emirates'), - (432, 'ir', 2, 'Iran (Islamic Republic of)'), - (434, 'uz', 2, 'Uzbekistan (Republic of)'), - (436, 'tj', 2, 'Tajikistan (Republic of)'), - (437, 'kg', 2, 'Kyrgyz Republic'), - (438, 'tm', 2, 'Turkmenistan'), - (440, 'jp', 2, 'Asia/Tokyo', 'ja', 14, 'Japan'), - (441, 'jp', 2, 'Asia/Tokyo', 'ja', 14, 'Japan'), - (450, 'kr', 2, 'Asia/Seoul', 'ko', 13, 'Korea (Republic of)'), - (452, 'vn', 2, 'Viet Nam (Socialist Republic of)'), - (454, 'hk', 2, '"Hong Kong, China"'), - (455, 'mo', 2, '"Macao, China"'), - (456, 'kh', 2, 'Cambodia (Kingdom of)'), - (457, 'la', 2, "Lao People's Democratic Republic"), - (460, 'cn', 2, "Asia/Beijing", 'zh', 13, "China (People's Republic of)"), - (461, 'cn', 2, "Asia/Beijing", 'zh', 13, "China (People's Republic of)"), - (466, 'tw', 2, "Taiwan (Republic of China)"), - (467, 'kp', 2, "Democratic People's Republic of Korea"), - (470, 'bd', 2, "Bangladesh (People's Republic of)"), - (472, 'mv', 2, 'Maldives (Republic of)'), - (502, 'my', 2, 'Malaysia'), - (505, 'au', 2, 'Australia/Sydney', 'en', 11, 'Australia'), - (510, 'id', 2, 'Indonesia (Republic of)'), - (514, 'tl', 2, 'Democratic Republic of Timor-Leste'), - (515, 'ph', 2, 'Philippines (Republic of the)'), - (520, 'th', 2, 'Thailand'), - (525, 'sg', 2, 'Asia/Singapore', 'en', 11, 'Singapore (Republic of)'), - (528, 'bn', 2, 'Brunei Darussalam'), - (530, 'nz', 2, 'Pacific/Auckland', 'en', 'New Zealand'), - (534, 'mp', 2, 'Northern Mariana Islands (Commonwealth of the)'), - (535, 'gu', 2, 'Guam'), - (536, 'nr', 2, 'Nauru (Republic of)'), - (537, 'pg', 2, 'Papua New Guinea'), - (539, 'to', 2, 'Tonga (Kingdom of)'), - (540, 'sb', 2, 'Solomon Islands'), - (541, 'vu', 2, 'Vanuatu (Republic of)'), - (542, 'fj', 2, 'Fiji (Republic of)'), - (543, 'wf', 2, "Wallis and Futuna (Territoire franais d'outre-mer)"), - (544, 'as', 2, 'American Samoa'), - (545, 'ki', 2, 'Kiribati (Republic of)'), - (546, 'nc', 2, "New Caledonia (Territoire franais d'outre-mer)"), - (547, 'pf', 2, "French Polynesia (Territoire franais d'outre-mer)"), - (548, 'ck', 2, 'Cook Islands'), - (549, 'ws', 2, 'Samoa (Independent State of)'), - (550, 'fm', 2, 'Micronesia (Federated States of)'), - (551, 'mh', 2, 'Marshall Islands (Republic of the)'), - (552, 'pw', 2, 'Palau (Republic of)'), - (602, 'eg', 2, 'Egypt (Arab Republic of)'), - (603, 'dz', 2, "Algeria (People's Democratic Republic of)"), - (604, 'ma', 2, 'Morocco (Kingdom of)'), - (605, 'tn', 2, 'Tunisia'), - (606, 'ly', 2, "Libya (Socialist People's Libyan Arab Jamahiriya)"), - (607, 'gm', 2, 'Gambia (Republic of the)'), - (608, 'sn', 2, 'Senegal (Republic of)'), - (609, 'mr', 2, 'Mauritania (Islamic Republic of)'), - (610, 'ml', 2, 'Mali (Republic of)'), - (611, 'gn', 2, 'Guinea (Republic of)'), - (612, 'ci', 2, "Cte d'Ivoire (Republic of)"), - (613, 'bf', 2, 'Burkina Faso'), - (614, 'ne', 2, 'Niger (Republic of the)'), - (615, 'tg', 2, 'Togolese Republic'), - (616, 'bj', 2, 'Benin (Republic of)'), - (617, 'mu', 2, 'Mauritius (Republic of)'), - (618, 'lr', 2, 'Liberia (Republic of)'), - (619, 'sl', 2, 'Sierra Leone'), - (620, 'gh', 2, 'Ghana'), - (621, 'ng', 2, 'Nigeria (Federal Republic of)'), - (622, 'td', 2, 'Chad (Republic of)'), - (623, 'cf', 2, 'Central African Republic'), - (624, 'cm', 2, 'Cameroon (Republic of)'), - (625, 'cv', 2, 'Cape Verde (Republic of)'), - (626, 'st', 2, 'Sao Tome and Principe (Democratic Republic of)'), - (627, 'gq', 2, 'Equatorial Guinea (Republic of)'), - (628, 'ga', 2, 'Gabonese Republic'), - (629, 'cg', 2, 'Congo (Republic of the)'), - (630, 'cg', 2, 'Democratic Republic of the Congo'), - (631, 'ao', 2, 'Angola (Republic of)'), - (632, 'gw', 2, 'Guinea-Bissau (Republic of)'), - (633, 'sc', 2, 'Seychelles (Republic of)'), - (634, 'sd', 2, 'Sudan (Republic of the)'), - (635, 'rw', 2, 'Rwanda (Republic of)'), - (636, 'et', 2, 'Ethiopia (Federal Democratic Republic of)'), - (637, 'so', 2, 'Somali Democratic Republic'), - (638, 'dj', 2, 'Djibouti (Republic of)'), - (639, 'ke', 2, 'Kenya (Republic of)'), - (640, 'tz', 2, 'Tanzania (United Republic of)'), - (641, 'ug', 2, 'Uganda (Republic of)'), - (642, 'bi', 2, 'Burundi (Republic of)'), - (643, 'mz', 2, 'Mozambique (Republic of)'), - (645, 'zm', 2, 'Zambia (Republic of)'), - (646, 'mg', 2, 'Madagascar (Republic of)'), - (647, 're', 2, 'Reunion (French Department of)'), - (648, 'zw', 2, 'Zimbabwe (Republic of)'), - (649, 'na', 2, 'Namibia (Republic of)'), - (650, 'mw', 2, 'Malawi'), - (651, 'ls', 2, 'Lesotho (Kingdom of)'), - (652, 'bw', 2, 'Botswana (Republic of)'), - (653, 'sz', 2, 'Swaziland (Kingdom of)'), - (654, 'km', 2, 'Comoros (Union of the)'), - (655, 'za', 2, 'Africa/Johannesburg', 'en', 'South Africa (Republic of)'), - (657, 'er', 2, 'Eritrea'), - (702, 'bz', 2, 'Belize'), - (704, 'gt', 2, 'Guatemala (Republic of)'), - (706, 'sv', 2, 'El Salvador (Republic of)'), - (708, 'hn', 3, 'Honduras (Republic of)'), - (710, 'ni', 2, 'Nicaragua'), - (712, 'cr', 2, 'Costa Rica'), - (714, 'pa', 2, 'Panama (Republic of)'), - (716, 'pe', 2, 'Peru'), - (722, 'ar', 3, 'Argentine Republic'), - (724, 'br', 2, 'Brazil (Federative Republic of)'), - (730, 'cl', 2, 'Chile'), - (732, 'co', 3, 'Colombia (Republic of)'), - (734, 've', 2, 'Venezuela (Bolivarian Republic of)'), - (736, 'bo', 2, 'Bolivia (Republic of)'), - (738, 'gy', 2, 'Guyana'), - (740, 'ec', 2, 'Ecuador'), - (742, 'gf', 2, 'French Guiana (French Department of)'), - (744, 'py', 2, 'Paraguay (Republic of)'), - (746, 'sr', 2, 'Suriname (Republic of)'), - (748, 'uy', 2, 'Uruguay (Eastern Republic of)'), - (750, 'fk', 2, 'Falkland Islands (Malvinas)')] - -get_mcc = lambda elt: elt[0] -get_iso = lambda elt: elt[1] -get_sd = lambda elt: elt[2] -get_tz = lambda elt: len(elt) > 4 and elt[3] or '' -get_lang = lambda elt: len(elt) > 5 and elt[4] or '' -get_wifi = lambda elt: len(elt) > 6 and elt[5] or 0 - -mcc_codes = ['0x%04x' % get_mcc(elt) for elt in mcc_table] -tz_set = sorted(x for x in set(get_tz(elt) for elt in mcc_table)) -lang_set = sorted(x for x in set(get_lang(elt) for elt in mcc_table)) - -def mk_ind_code(elt): - iso = get_iso(elt) - iso_code = ((ord(iso[0]) << 8) | ord(iso[1])) & 0xFFFF # 16 bits - wifi = get_wifi(elt) & 0x000F # 4 bits - sd = get_sd(elt) & 0x0003 # 2 bits - tz_ind = tz_set.index(get_tz(elt)) & 0x001F # 5 bits - lang_ind = lang_set.index(get_lang(elt)) & 0x000F # 4 bits - return (iso_code << 16) | (wifi << 11) | (sd << 9) | (tz_ind << 4) | lang_ind - -ind_codes = ['0x%08x' % mk_ind_code(elt) for elt in mcc_table] - -def fmt_list(title, l, batch_sz): - sl = [] - for i in range(len(l) / batch_sz + (len(l) % batch_sz and 1 or 0)): - j = i * batch_sz - sl.append((' ' * 8) + ', '.join(l[j:j + batch_sz])) - return ' private static final %s = {\n' % title + ',\n'.join(sl) + '\n };\n' - -def do_autogen_comment(extra_desc=[]): - print ' /' + '**\n * AUTO GENERATED (by the Python code above)' - for line in extra_desc: - print ' * %s' % line - print ' *' + '/' - -do_autogen_comment() -print fmt_list('String[] TZ_STRINGS', ['"%s"' % x for x in tz_set], 1) -do_autogen_comment() -print fmt_list('String[] LANG_STRINGS', ['"%s"' % x for x in lang_set], 10) -do_autogen_comment(['This table is a list of MCC codes. The index in this table', - 'of a given MCC code is the index of extra information about', - 'that MCC in the IND_CODES table.']) -print fmt_list('short[] MCC_CODES', mcc_codes, 10) -do_autogen_comment(['The values in this table are broken down as follows (msb to lsb):', - ' iso country code 16 bits', - ' (unused) 1 bit', - ' wifi channel 4 bits', - ' smalled digit 2 bits', - ' default timezone 5 bits', - ' default language 4 bits']) -print fmt_list('int[] IND_CODES', ind_codes, 6) - -def parse_ind_code(ind): - mcc = eval(mcc_codes[ind]) - code = eval(ind_codes[ind]) - iso_lsb = int((code >> 16) & 0x00FF) - iso_msb = int((code >> 24) & 0x00FF) - iso = '%s%s' % (chr(iso_msb), chr(iso_lsb)) - wifi = int((code >> 11) & 0x000F) - sd = int((code >> 9) & 0x0003) - tz_ind = (code >> 4) & 0x001F - lang_ind = (code >> 0) & 0x000F - return (mcc, iso, sd, tz_set[tz_ind], lang_set[lang_ind], wifi) - -fmt_str = 'mcc = %s, iso = %s, sd = %s, tz = %s, lang = %s, wifi = %s' -orig_table = [fmt_str % (get_mcc(elt), get_iso(elt), get_sd(elt), - get_tz(elt), get_lang(elt), get_wifi(elt)) - for elt in mcc_table] -derived_table = [fmt_str % parse_ind_code(i) for i in range(len(ind_codes))] -for i in range(len(orig_table)): - if orig_table[i] == derived_table[i]: continue - print 'MISMATCH ERROR : ', orig_table[i], " != ", derived_table[i] - -*/ +import java.util.ArrayList; +import java.util.Collections; +import java.util.Locale; +import libcore.icu.TimeZones; /** * Mobile Country Code @@ -371,202 +38,130 @@ for i in range(len(orig_table)): */ public final class MccTable { - /** - * AUTO GENERATED (by the Python code above) - */ - private static final String[] TZ_STRINGS = { - "", - "Africa/Johannesburg", - "Asia/Beijing", - "Asia/Seoul", - "Asia/Singapore", - "Asia/Tokyo", - "Australia/Sydney", - "Europe/Amsterdam", - "Europe/Berlin", - "Europe/Dublin", - "Europe/London", - "Europe/Madrid", - "Europe/Paris", - "Europe/Prague", - "Europe/Rome", - "Europe/Vienna", - "Europe/Warsaw", - "Europe/Zurich", - "Pacific/Auckland" - }; + static final String LOG_TAG = "MccTable"; - /** - * AUTO GENERATED (by the Python code above) - */ - private static final String[] LANG_STRINGS = { - "", "cs", "de", "en", "es", "fr", "it", "ja", "ko", "nl", - "zh" - }; + static ArrayList<MccEntry> table; - /** - * AUTO GENERATED (by the Python code above) - * This table is a list of MCC codes. The index in this table - * of a given MCC code is the index of extra information about - * that MCC in the IND_CODES table. - */ - private static final short[] MCC_CODES = { - 0x00ca, 0x00cc, 0x00ce, 0x00d0, 0x00d4, 0x00d5, 0x00d6, 0x00d8, 0x00da, 0x00db, - 0x00dc, 0x00de, 0x00e1, 0x00e2, 0x00e4, 0x00e6, 0x00e7, 0x00e8, 0x00ea, 0x00eb, - 0x00ee, 0x00f0, 0x00f2, 0x00f4, 0x00f6, 0x00f7, 0x00f8, 0x00fa, 0x00ff, 0x0101, - 0x0103, 0x0104, 0x0106, 0x010a, 0x010c, 0x010e, 0x0110, 0x0112, 0x0114, 0x0116, - 0x0118, 0x011a, 0x011b, 0x011c, 0x011e, 0x0120, 0x0121, 0x0122, 0x0124, 0x0125, - 0x0126, 0x0127, 0x0129, 0x012e, 0x0134, 0x0136, 0x0137, 0x0138, 0x0139, 0x013a, - 0x013b, 0x013c, 0x014a, 0x014c, 0x014e, 0x0152, 0x0154, 0x0156, 0x0158, 0x015a, - 0x015c, 0x015e, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016a, 0x016b, 0x016c, - 0x016d, 0x016e, 0x0170, 0x0172, 0x0174, 0x0176, 0x0178, 0x0190, 0x0191, 0x0192, - 0x0194, 0x0195, 0x019a, 0x019c, 0x019d, 0x019e, 0x019f, 0x01a0, 0x01a1, 0x01a2, - 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, - 0x01ad, 0x01ae, 0x01af, 0x01b0, 0x01b2, 0x01b4, 0x01b5, 0x01b6, 0x01b8, 0x01b9, - 0x01c2, 0x01c4, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01cc, 0x01cd, 0x01d2, 0x01d3, - 0x01d6, 0x01d8, 0x01f6, 0x01f9, 0x01fe, 0x0202, 0x0203, 0x0208, 0x020d, 0x0210, - 0x0212, 0x0216, 0x0217, 0x0218, 0x0219, 0x021b, 0x021c, 0x021d, 0x021e, 0x021f, - 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227, 0x0228, 0x025a, - 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, - 0x0265, 0x0266, 0x0267, 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, - 0x026f, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, 0x0278, - 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, 0x0280, 0x0281, 0x0282, - 0x0283, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, - 0x028e, 0x028f, 0x0291, 0x02be, 0x02c0, 0x02c2, 0x02c4, 0x02c6, 0x02c8, 0x02ca, - 0x02cc, 0x02d2, 0x02d4, 0x02da, 0x02dc, 0x02de, 0x02e0, 0x02e2, 0x02e4, 0x02e6, - 0x02e8, 0x02ea, 0x02ec, 0x02ee - }; + static class MccEntry implements Comparable<MccEntry> + { + int mcc; + String iso; + int smallestDigitsMnc; + String language; - /** - * AUTO GENERATED (by the Python code above) - * The values in this table are broken down as follows (msb to lsb): - * iso country code 16 bits - * (unused) 1 bit - * wifi channel 4 bits - * smalled digit 2 bits - * default timezone 5 bits - * default language 4 bits - */ - private static final int[] IND_CODES = { - 0x67720400, 0x6e6c6c79, 0x62650400, 0x667204c5, 0x6d630400, 0x61640400, - 0x657304b4, 0x68750400, 0x62610400, 0x68720400, 0x72730400, 0x697404e6, - 0x766104e6, 0x726f0400, 0x63680512, 0x637a6cd1, 0x736b0400, 0x61746cf2, - 0x67626ca3, 0x67626ca3, 0x646b0400, 0x73650400, 0x6e6f0400, 0x66690400, - 0x6c740400, 0x6c760400, 0x65650400, 0x72750400, 0x75610400, 0x62790400, - 0x6d640400, 0x706c0500, 0x64656c82, 0x67690400, 0x70740400, 0x6c750400, - 0x69650493, 0x69730400, 0x616c0400, 0x6d740400, 0x63790400, 0x67650400, - 0x616d0400, 0x62670400, 0x74720400, 0x666f0400, 0x67650400, 0x676c0400, - 0x736d0400, 0x736c0400, 0x6d6b0400, 0x6c690400, 0x6d650400, 0x63615e00, - 0x706d0400, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03, - 0x75735e03, 0x75735e03, 0x70720400, 0x76690400, 0x6d780600, 0x6a6d0600, - 0x67700400, 0x62620600, 0x61670600, 0x6b790600, 0x76670600, 0x626d0400, - 0x67640400, 0x6d730400, 0x6b6e0400, 0x6c630400, 0x76630400, 0x6e6c0400, - 0x61770400, 0x62730400, 0x61690600, 0x646d0400, 0x63750400, 0x646f0400, - 0x68740400, 0x74740400, 0x74630400, 0x617a0400, 0x6b7a0400, 0x62740400, - 0x696e0400, 0x696e0400, 0x706b0400, 0x61660400, 0x6c6b0400, 0x6d6d0400, - 0x6c620400, 0x6a6f0400, 0x73790400, 0x69710400, 0x6b770400, 0x73610400, - 0x79650400, 0x6f6d0400, 0x70730400, 0x61650400, 0x696c0400, 0x62680400, - 0x71610400, 0x6d6e0400, 0x6e700400, 0x61650400, 0x61650400, 0x69720400, - 0x757a0400, 0x746a0400, 0x6b670400, 0x746d0400, 0x6a707457, 0x6a707457, - 0x6b726c38, 0x766e0400, 0x686b0400, 0x6d6f0400, 0x6b680400, 0x6c610400, - 0x636e6c2a, 0x636e6c2a, 0x74770400, 0x6b700400, 0x62640400, 0x6d760400, - 0x6d790400, 0x61755c63, 0x69640400, 0x746c0400, 0x70680400, 0x74680400, - 0x73675c43, 0x626e0400, 0x6e7a0523, 0x6d700400, 0x67750400, 0x6e720400, - 0x70670400, 0x746f0400, 0x73620400, 0x76750400, 0x666a0400, 0x77660400, - 0x61730400, 0x6b690400, 0x6e630400, 0x70660400, 0x636b0400, 0x77730400, - 0x666d0400, 0x6d680400, 0x70770400, 0x65670400, 0x647a0400, 0x6d610400, - 0x746e0400, 0x6c790400, 0x676d0400, 0x736e0400, 0x6d720400, 0x6d6c0400, - 0x676e0400, 0x63690400, 0x62660400, 0x6e650400, 0x74670400, 0x626a0400, - 0x6d750400, 0x6c720400, 0x736c0400, 0x67680400, 0x6e670400, 0x74640400, - 0x63660400, 0x636d0400, 0x63760400, 0x73740400, 0x67710400, 0x67610400, - 0x63670400, 0x63670400, 0x616f0400, 0x67770400, 0x73630400, 0x73640400, - 0x72770400, 0x65740400, 0x736f0400, 0x646a0400, 0x6b650400, 0x747a0400, - 0x75670400, 0x62690400, 0x6d7a0400, 0x7a6d0400, 0x6d670400, 0x72650400, - 0x7a770400, 0x6e610400, 0x6d770400, 0x6c730400, 0x62770400, 0x737a0400, - 0x6b6d0400, 0x7a610413, 0x65720400, 0x627a0400, 0x67740400, 0x73760400, - 0x686e0600, 0x6e690400, 0x63720400, 0x70610400, 0x70650400, 0x61720600, - 0x62720400, 0x636c0400, 0x636f0600, 0x76650400, 0x626f0400, 0x67790400, - 0x65630400, 0x67660400, 0x70790400, 0x73720400, 0x75790400, 0x666b0400 - }; + MccEntry(int mnc, String iso, int smallestDigitsMCC) { + this(mnc, iso, smallestDigitsMCC, null); + } - static final String LOG_TAG = "MccTable"; + MccEntry(int mnc, String iso, int smallestDigitsMCC, String language) { + this.mcc = mnc; + this.iso = iso; + this.smallestDigitsMnc = smallestDigitsMCC; + this.language = language; + } + + + public int compareTo(MccEntry o) + { + return mcc - o.mcc; + } + } + + private static MccEntry + entryForMcc(int mcc) + { + int index; + + MccEntry m; + + m = new MccEntry(mcc, null, 0); + + index = Collections.binarySearch(table, m); - /** - * Given a Mobile Country Code, returns a default time zone ID - * if available. Returns null if unavailable. - */ - public static String defaultTimeZoneForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); if (index < 0) { return null; + } else { + return table.get(index); } - int indCode = IND_CODES[index]; - int tzInd = (indCode >>> 4) & 0x001F; - String tz = TZ_STRINGS[tzInd]; - if (tz == "") { + } + + /** + * Returns a default time zone ID for the given MCC. + * @param mcc Mobile Country Code + * @return default TimeZone ID, or null if not specified + */ + public static String defaultTimeZoneForMcc(int mcc) { + MccEntry entry; + + entry = entryForMcc(mcc); + if (entry == null || entry.iso == null) { return null; + } else { + Locale locale; + if (entry.language == null) { + locale = new Locale(entry.iso); + } else { + locale = new Locale(entry.language, entry.iso); + } + String[] tz = TimeZones.forLocale(locale); + if (tz.length == 0) return null; + return tz[0]; } - return tz; } /** - * Given a Mobile Country Code, returns an ISO two-character - * country code if available. Returns "" if unavailable. + * Given a GSM Mobile Country Code, returns + * an ISO two-character country code if available. + * Returns "" if unavailable. */ - public static String countryCodeForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { + public static String + countryCodeForMcc(int mcc) + { + MccEntry entry; + + entry = entryForMcc(mcc); + + if (entry == null) { return ""; + } else { + return entry.iso; } - int indCode = IND_CODES[index]; - byte[] iso = {(byte)((indCode >>> 24) & 0x00FF), (byte)((indCode >>> 16) & 0x00FF)}; - return new String(iso); } /** - * Given a GSM Mobile Country Code, returns an ISO 2-3 character - * language code if available. Returns null if unavailable. + * Given a GSM Mobile Country Code, returns + * an ISO 2-3 character language code if available. + * Returns null if unavailable. */ public static String defaultLanguageForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { - return null; - } - int indCode = IND_CODES[index]; - int langInd = indCode & 0x000F; - String lang = LANG_STRINGS[langInd]; - if (lang == "") { + MccEntry entry; + + entry = entryForMcc(mcc); + + if (entry == null) { return null; + } else { + return entry.language; } - return lang; } /** - * Given a GSM Mobile Country Code, returns the corresponding - * smallest number of digits field. Returns 2 if unavailable. + * Given a GSM Mobile Country Code, returns + * the smallest number of digits that M if available. + * Returns 2 if unavailable. */ - public static int smallestDigitsMccForMnc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { - return 2; - } - int indCode = IND_CODES[index]; - int smDig = (indCode >>> 9) & 0x0003; - return smDig; - } + public static int + smallestDigitsMccForMnc(int mcc) + { + MccEntry entry; - /** - * Given a GSM Mobile Country Code, returns the number of wifi - * channels allowed in that country. Returns 0 if unavailable. - */ - public static int wifiChannelsForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { - return 0; + entry = entryForMcc(mcc); + + if (entry == null) { + return 2; + } else { + return entry.smallestDigitsMnc; } - int indCode = IND_CODES[index]; - int wifi = (indCode >>> 11) & 0x000F; - return wifi; } /** @@ -592,7 +187,7 @@ public final class MccTable if (mcc != 0) { setTimezoneFromMccIfNeeded(phone, mcc); setLocaleFromMccIfNeeded(phone, mcc); - setWifiChannelsFromMcc(phone, mcc); + setWifiCountryCodeFromMcc(phone, mcc); } try { Configuration config = ActivityManagerNative.getDefault().getConfiguration(); @@ -648,14 +243,272 @@ public final class MccTable * @param phone PhoneBase to act on (get context from). * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) */ - private static void setWifiChannelsFromMcc(PhoneBase phone, int mcc) { - int wifiChannels = MccTable.wifiChannelsForMcc(mcc); - if (wifiChannels != 0) { + private static void setWifiCountryCodeFromMcc(PhoneBase phone, int mcc) { + String country = MccTable.countryCodeForMcc(mcc); + if (!country.isEmpty()) { Context context = phone.getContext(); - Log.d(LOG_TAG, "WIFI_NUM_ALLOWED_CHANNELS set to " + wifiChannels); + Log.d(LOG_TAG, "WIFI_COUNTRY_CODE set to " + country); WifiManager wM = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); //persist - wM.setNumAllowedChannels(wifiChannels, true); + wM.setCountryCode(country, true); } } + + static { + table = new ArrayList<MccEntry>(240); + + + /* + * The table below is built from two resources: + * + * 1) ITU "Mobile Network Code (MNC) for the international + * identification plan for mobile terminals and mobile users" + * which is available as an annex to the ITU operational bulletin + * available here: http://www.itu.int/itu-t/bulletin/annex.html + * + * 2) The ISO 3166 country codes list, available here: + * http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html + * + * This table has not been verified. + * + */ + + table.add(new MccEntry(202,"gr",2)); //Greece + table.add(new MccEntry(204,"nl",2,"nl")); //Netherlands (Kingdom of the) + table.add(new MccEntry(206,"be",2)); //Belgium + table.add(new MccEntry(208,"fr",2,"fr")); //France + table.add(new MccEntry(212,"mc",2)); //Monaco (Principality of) + table.add(new MccEntry(213,"ad",2)); //Andorra (Principality of) + table.add(new MccEntry(214,"es",2,"es")); //Spain + table.add(new MccEntry(216,"hu",2)); //Hungary (Republic of) + table.add(new MccEntry(218,"ba",2)); //Bosnia and Herzegovina + table.add(new MccEntry(219,"hr",2)); //Croatia (Republic of) + table.add(new MccEntry(220,"rs",2)); //Serbia and Montenegro + table.add(new MccEntry(222,"it",2,"it")); //Italy + table.add(new MccEntry(225,"va",2,"it")); //Vatican City State + table.add(new MccEntry(226,"ro",2)); //Romania + table.add(new MccEntry(228,"ch",2,"de")); //Switzerland (Confederation of) + table.add(new MccEntry(230,"cz",2,"cs")); //Czech Republic + table.add(new MccEntry(231,"sk",2)); //Slovak Republic + table.add(new MccEntry(232,"at",2,"de")); //Austria + table.add(new MccEntry(234,"gb",2,"en")); //United Kingdom of Great Britain and Northern Ireland + table.add(new MccEntry(235,"gb",2,"en")); //United Kingdom of Great Britain and Northern Ireland + table.add(new MccEntry(238,"dk",2)); //Denmark + table.add(new MccEntry(240,"se",2)); //Sweden + table.add(new MccEntry(242,"no",2)); //Norway + table.add(new MccEntry(244,"fi",2)); //Finland + table.add(new MccEntry(246,"lt",2)); //Lithuania (Republic of) + table.add(new MccEntry(247,"lv",2)); //Latvia (Republic of) + table.add(new MccEntry(248,"ee",2)); //Estonia (Republic of) + table.add(new MccEntry(250,"ru",2)); //Russian Federation + table.add(new MccEntry(255,"ua",2)); //Ukraine + table.add(new MccEntry(257,"by",2)); //Belarus (Republic of) + table.add(new MccEntry(259,"md",2)); //Moldova (Republic of) + table.add(new MccEntry(260,"pl",2)); //Poland (Republic of) + table.add(new MccEntry(262,"de",2,"de")); //Germany (Federal Republic of) + table.add(new MccEntry(266,"gi",2)); //Gibraltar + table.add(new MccEntry(268,"pt",2)); //Portugal + table.add(new MccEntry(270,"lu",2)); //Luxembourg + table.add(new MccEntry(272,"ie",2,"en")); //Ireland + table.add(new MccEntry(274,"is",2)); //Iceland + table.add(new MccEntry(276,"al",2)); //Albania (Republic of) + table.add(new MccEntry(278,"mt",2)); //Malta + table.add(new MccEntry(280,"cy",2)); //Cyprus (Republic of) + table.add(new MccEntry(282,"ge",2)); //Georgia + table.add(new MccEntry(283,"am",2)); //Armenia (Republic of) + table.add(new MccEntry(284,"bg",2)); //Bulgaria (Republic of) + table.add(new MccEntry(286,"tr",2)); //Turkey + table.add(new MccEntry(288,"fo",2)); //Faroe Islands + table.add(new MccEntry(289,"ge",2)); //Abkhazia (Georgia) + table.add(new MccEntry(290,"gl",2)); //Greenland (Denmark) + table.add(new MccEntry(292,"sm",2)); //San Marino (Republic of) + table.add(new MccEntry(293,"sl",2)); //Slovenia (Republic of) + table.add(new MccEntry(294,"mk",2)); //The Former Yugoslav Republic of Macedonia + table.add(new MccEntry(295,"li",2)); //Liechtenstein (Principality of) + table.add(new MccEntry(297,"me",2)); //Montenegro (Republic of) + table.add(new MccEntry(302,"ca",3,"")); //Canada + table.add(new MccEntry(308,"pm",2)); //Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise) + table.add(new MccEntry(310,"us",3,"en")); //United States of America + table.add(new MccEntry(311,"us",3,"en")); //United States of America + table.add(new MccEntry(312,"us",3,"en")); //United States of America + table.add(new MccEntry(313,"us",3,"en")); //United States of America + table.add(new MccEntry(314,"us",3,"en")); //United States of America + table.add(new MccEntry(315,"us",3,"en")); //United States of America + table.add(new MccEntry(316,"us",3,"en")); //United States of America + table.add(new MccEntry(330,"pr",2)); //Puerto Rico + table.add(new MccEntry(332,"vi",2)); //United States Virgin Islands + table.add(new MccEntry(334,"mx",3)); //Mexico + table.add(new MccEntry(338,"jm",3)); //Jamaica + table.add(new MccEntry(340,"gp",2)); //Guadeloupe (French Department of) + table.add(new MccEntry(342,"bb",3)); //Barbados + table.add(new MccEntry(344,"ag",3)); //Antigua and Barbuda + table.add(new MccEntry(346,"ky",3)); //Cayman Islands + table.add(new MccEntry(348,"vg",3)); //British Virgin Islands + table.add(new MccEntry(350,"bm",2)); //Bermuda + table.add(new MccEntry(352,"gd",2)); //Grenada + table.add(new MccEntry(354,"ms",2)); //Montserrat + table.add(new MccEntry(356,"kn",2)); //Saint Kitts and Nevis + table.add(new MccEntry(358,"lc",2)); //Saint Lucia + table.add(new MccEntry(360,"vc",2)); //Saint Vincent and the Grenadines + table.add(new MccEntry(362,"nl",2)); //Netherlands Antilles + table.add(new MccEntry(363,"aw",2)); //Aruba + table.add(new MccEntry(364,"bs",2)); //Bahamas (Commonwealth of the) + table.add(new MccEntry(365,"ai",3)); //Anguilla + table.add(new MccEntry(366,"dm",2)); //Dominica (Commonwealth of) + table.add(new MccEntry(368,"cu",2)); //Cuba + table.add(new MccEntry(370,"do",2)); //Dominican Republic + table.add(new MccEntry(372,"ht",2)); //Haiti (Republic of) + table.add(new MccEntry(374,"tt",2)); //Trinidad and Tobago + table.add(new MccEntry(376,"tc",2)); //Turks and Caicos Islands + table.add(new MccEntry(400,"az",2)); //Azerbaijani Republic + table.add(new MccEntry(401,"kz",2)); //Kazakhstan (Republic of) + table.add(new MccEntry(402,"bt",2)); //Bhutan (Kingdom of) + table.add(new MccEntry(404,"in",2)); //India (Republic of) + table.add(new MccEntry(405,"in",2)); //India (Republic of) + table.add(new MccEntry(410,"pk",2)); //Pakistan (Islamic Republic of) + table.add(new MccEntry(412,"af",2)); //Afghanistan + table.add(new MccEntry(413,"lk",2)); //Sri Lanka (Democratic Socialist Republic of) + table.add(new MccEntry(414,"mm",2)); //Myanmar (Union of) + table.add(new MccEntry(415,"lb",2)); //Lebanon + table.add(new MccEntry(416,"jo",2)); //Jordan (Hashemite Kingdom of) + table.add(new MccEntry(417,"sy",2)); //Syrian Arab Republic + table.add(new MccEntry(418,"iq",2)); //Iraq (Republic of) + table.add(new MccEntry(419,"kw",2)); //Kuwait (State of) + table.add(new MccEntry(420,"sa",2)); //Saudi Arabia (Kingdom of) + table.add(new MccEntry(421,"ye",2)); //Yemen (Republic of) + table.add(new MccEntry(422,"om",2)); //Oman (Sultanate of) + table.add(new MccEntry(423,"ps",2)); //Palestine + table.add(new MccEntry(424,"ae",2)); //United Arab Emirates + table.add(new MccEntry(425,"il",2)); //Israel (State of) + table.add(new MccEntry(426,"bh",2)); //Bahrain (Kingdom of) + table.add(new MccEntry(427,"qa",2)); //Qatar (State of) + table.add(new MccEntry(428,"mn",2)); //Mongolia + table.add(new MccEntry(429,"np",2)); //Nepal + table.add(new MccEntry(430,"ae",2)); //United Arab Emirates + table.add(new MccEntry(431,"ae",2)); //United Arab Emirates + table.add(new MccEntry(432,"ir",2)); //Iran (Islamic Republic of) + table.add(new MccEntry(434,"uz",2)); //Uzbekistan (Republic of) + table.add(new MccEntry(436,"tj",2)); //Tajikistan (Republic of) + table.add(new MccEntry(437,"kg",2)); //Kyrgyz Republic + table.add(new MccEntry(438,"tm",2)); //Turkmenistan + table.add(new MccEntry(440,"jp",2,"ja")); //Japan + table.add(new MccEntry(441,"jp",2,"ja")); //Japan + table.add(new MccEntry(450,"kr",2,"ko")); //Korea (Republic of) + table.add(new MccEntry(452,"vn",2)); //Viet Nam (Socialist Republic of) + table.add(new MccEntry(454,"hk",2)); //"Hong Kong, China" + table.add(new MccEntry(455,"mo",2)); //"Macao, China" + table.add(new MccEntry(456,"kh",2)); //Cambodia (Kingdom of) + table.add(new MccEntry(457,"la",2)); //Lao People's Democratic Republic + table.add(new MccEntry(460,"cn",2,"zh")); //China (People's Republic of) + table.add(new MccEntry(461,"cn",2,"zh")); //China (People's Republic of) + table.add(new MccEntry(466,"tw",2)); //"Taiwan, China" + table.add(new MccEntry(467,"kp",2)); //Democratic People's Republic of Korea + table.add(new MccEntry(470,"bd",2)); //Bangladesh (People's Republic of) + table.add(new MccEntry(472,"mv",2)); //Maldives (Republic of) + table.add(new MccEntry(502,"my",2)); //Malaysia + table.add(new MccEntry(505,"au",2,"en")); //Australia + table.add(new MccEntry(510,"id",2)); //Indonesia (Republic of) + table.add(new MccEntry(514,"tl",2)); //Democratic Republic of Timor-Leste + table.add(new MccEntry(515,"ph",2)); //Philippines (Republic of the) + table.add(new MccEntry(520,"th",2)); //Thailand + table.add(new MccEntry(525,"sg",2,"en")); //Singapore (Republic of) + table.add(new MccEntry(528,"bn",2)); //Brunei Darussalam + table.add(new MccEntry(530,"nz",2, "en")); //New Zealand + table.add(new MccEntry(534,"mp",2)); //Northern Mariana Islands (Commonwealth of the) + table.add(new MccEntry(535,"gu",2)); //Guam + table.add(new MccEntry(536,"nr",2)); //Nauru (Republic of) + table.add(new MccEntry(537,"pg",2)); //Papua New Guinea + table.add(new MccEntry(539,"to",2)); //Tonga (Kingdom of) + table.add(new MccEntry(540,"sb",2)); //Solomon Islands + table.add(new MccEntry(541,"vu",2)); //Vanuatu (Republic of) + table.add(new MccEntry(542,"fj",2)); //Fiji (Republic of) + table.add(new MccEntry(543,"wf",2)); //Wallis and Futuna (Territoire franais d'outre-mer) + table.add(new MccEntry(544,"as",2)); //American Samoa + table.add(new MccEntry(545,"ki",2)); //Kiribati (Republic of) + table.add(new MccEntry(546,"nc",2)); //New Caledonia (Territoire franais d'outre-mer) + table.add(new MccEntry(547,"pf",2)); //French Polynesia (Territoire franais d'outre-mer) + table.add(new MccEntry(548,"ck",2)); //Cook Islands + table.add(new MccEntry(549,"ws",2)); //Samoa (Independent State of) + table.add(new MccEntry(550,"fm",2)); //Micronesia (Federated States of) + table.add(new MccEntry(551,"mh",2)); //Marshall Islands (Republic of the) + table.add(new MccEntry(552,"pw",2)); //Palau (Republic of) + table.add(new MccEntry(602,"eg",2)); //Egypt (Arab Republic of) + table.add(new MccEntry(603,"dz",2)); //Algeria (People's Democratic Republic of) + table.add(new MccEntry(604,"ma",2)); //Morocco (Kingdom of) + table.add(new MccEntry(605,"tn",2)); //Tunisia + table.add(new MccEntry(606,"ly",2)); //Libya (Socialist People's Libyan Arab Jamahiriya) + table.add(new MccEntry(607,"gm",2)); //Gambia (Republic of the) + table.add(new MccEntry(608,"sn",2)); //Senegal (Republic of) + table.add(new MccEntry(609,"mr",2)); //Mauritania (Islamic Republic of) + table.add(new MccEntry(610,"ml",2)); //Mali (Republic of) + table.add(new MccEntry(611,"gn",2)); //Guinea (Republic of) + table.add(new MccEntry(612,"ci",2)); //Cte d'Ivoire (Republic of) + table.add(new MccEntry(613,"bf",2)); //Burkina Faso + table.add(new MccEntry(614,"ne",2)); //Niger (Republic of the) + table.add(new MccEntry(615,"tg",2)); //Togolese Republic + table.add(new MccEntry(616,"bj",2)); //Benin (Republic of) + table.add(new MccEntry(617,"mu",2)); //Mauritius (Republic of) + table.add(new MccEntry(618,"lr",2)); //Liberia (Republic of) + table.add(new MccEntry(619,"sl",2)); //Sierra Leone + table.add(new MccEntry(620,"gh",2)); //Ghana + table.add(new MccEntry(621,"ng",2)); //Nigeria (Federal Republic of) + table.add(new MccEntry(622,"td",2)); //Chad (Republic of) + table.add(new MccEntry(623,"cf",2)); //Central African Republic + table.add(new MccEntry(624,"cm",2)); //Cameroon (Republic of) + table.add(new MccEntry(625,"cv",2)); //Cape Verde (Republic of) + table.add(new MccEntry(626,"st",2)); //Sao Tome and Principe (Democratic Republic of) + table.add(new MccEntry(627,"gq",2)); //Equatorial Guinea (Republic of) + table.add(new MccEntry(628,"ga",2)); //Gabonese Republic + table.add(new MccEntry(629,"cg",2)); //Congo (Republic of the) + table.add(new MccEntry(630,"cg",2)); //Democratic Republic of the Congo + table.add(new MccEntry(631,"ao",2)); //Angola (Republic of) + table.add(new MccEntry(632,"gw",2)); //Guinea-Bissau (Republic of) + table.add(new MccEntry(633,"sc",2)); //Seychelles (Republic of) + table.add(new MccEntry(634,"sd",2)); //Sudan (Republic of the) + table.add(new MccEntry(635,"rw",2)); //Rwanda (Republic of) + table.add(new MccEntry(636,"et",2)); //Ethiopia (Federal Democratic Republic of) + table.add(new MccEntry(637,"so",2)); //Somali Democratic Republic + table.add(new MccEntry(638,"dj",2)); //Djibouti (Republic of) + table.add(new MccEntry(639,"ke",2)); //Kenya (Republic of) + table.add(new MccEntry(640,"tz",2)); //Tanzania (United Republic of) + table.add(new MccEntry(641,"ug",2)); //Uganda (Republic of) + table.add(new MccEntry(642,"bi",2)); //Burundi (Republic of) + table.add(new MccEntry(643,"mz",2)); //Mozambique (Republic of) + table.add(new MccEntry(645,"zm",2)); //Zambia (Republic of) + table.add(new MccEntry(646,"mg",2)); //Madagascar (Republic of) + table.add(new MccEntry(647,"re",2)); //Reunion (French Department of) + table.add(new MccEntry(648,"zw",2)); //Zimbabwe (Republic of) + table.add(new MccEntry(649,"na",2)); //Namibia (Republic of) + table.add(new MccEntry(650,"mw",2)); //Malawi + table.add(new MccEntry(651,"ls",2)); //Lesotho (Kingdom of) + table.add(new MccEntry(652,"bw",2)); //Botswana (Republic of) + table.add(new MccEntry(653,"sz",2)); //Swaziland (Kingdom of) + table.add(new MccEntry(654,"km",2)); //Comoros (Union of the) + table.add(new MccEntry(655,"za",2,"en")); //South Africa (Republic of) + table.add(new MccEntry(657,"er",2)); //Eritrea + table.add(new MccEntry(702,"bz",2)); //Belize + table.add(new MccEntry(704,"gt",2)); //Guatemala (Republic of) + table.add(new MccEntry(706,"sv",2)); //El Salvador (Republic of) + table.add(new MccEntry(708,"hn",3)); //Honduras (Republic of) + table.add(new MccEntry(710,"ni",2)); //Nicaragua + table.add(new MccEntry(712,"cr",2)); //Costa Rica + table.add(new MccEntry(714,"pa",2)); //Panama (Republic of) + table.add(new MccEntry(716,"pe",2)); //Peru + table.add(new MccEntry(722,"ar",3)); //Argentine Republic + table.add(new MccEntry(724,"br",2)); //Brazil (Federative Republic of) + table.add(new MccEntry(730,"cl",2)); //Chile + table.add(new MccEntry(732,"co",3)); //Colombia (Republic of) + table.add(new MccEntry(734,"ve",2)); //Venezuela (Bolivarian Republic of) + table.add(new MccEntry(736,"bo",2)); //Bolivia (Republic of) + table.add(new MccEntry(738,"gy",2)); //Guyana + table.add(new MccEntry(740,"ec",2)); //Ecuador + table.add(new MccEntry(742,"gf",2)); //French Guiana (French Department of) + table.add(new MccEntry(744,"py",2)); //Paraguay (Republic of) + table.add(new MccEntry(746,"sr",2)); //Suriname (Republic of) + table.add(new MccEntry(748,"uy",2)); //Uruguay (Eastern Republic of) + table.add(new MccEntry(750,"fk",2)); //Falkland Islands (Malvinas) + //table.add(new MccEntry(901,"",2)); //"International Mobile, shared code" + + Collections.sort(table); + } } diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index e426e94..25ad48d 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -17,10 +17,10 @@ package com.android.internal.telephony; import android.content.Context; -import android.content.SharedPreferences; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Handler; import android.os.Message; -import android.preference.PreferenceManager; import android.telephony.CellLocation; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -28,7 +28,6 @@ import android.telephony.SignalStrength; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.gsm.NetworkInfo; -import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -99,11 +98,12 @@ public interface Phone { static final String PHONE_NAME_KEY = "phoneName"; static final String FAILURE_REASON_KEY = "reason"; static final String STATE_CHANGE_REASON_KEY = "reason"; - static final String DATA_APN_TYPES_KEY = "apnType"; + static final String DATA_APN_TYPE_KEY = "apnType"; static final String DATA_APN_KEY = "apn"; + static final String DATA_LINK_PROPERTIES_KEY = "linkProperties"; + static final String DATA_LINK_CAPABILITIES_KEY = "linkCapabilities"; static final String DATA_IFACE_NAME_KEY = "iface"; - static final String DATA_GATEWAY_KEY = "gateway"; static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable"; static final String PHONE_IN_ECM_STATE = "phoneinECMState"; @@ -243,11 +243,19 @@ public interface Phone { CellLocation getCellLocation(); /** + * Get the current for the default apn DataState. No change notification + * exists at this interface -- use + * {@link android.telephony.PhoneStateListener} instead. + */ + DataState getDataConnectionState(); + + /** * Get the current DataState. No change notification exists at this * interface -- use * {@link android.telephony.PhoneStateListener} instead. + * @param apnType specify for which apn to get connection state info. */ - DataState getDataConnectionState(); + DataState getDataConnectionState(String apnType); /** * Get the current DataActivityState. No change notification exists at this @@ -301,16 +309,27 @@ public interface Phone { /** * Returns an array of string identifiers for the APN types serviced by the - * currently active or last connected APN. - * @return The string array. + * currently active. + * @return The string array will always return at least one entry, Phone.APN_TYPE_DEFAULT. + * TODO: Revisit if we always should return at least one entry. */ String[] getActiveApnTypes(); /** - * Returns a string identifier for currently active or last connected APN. - * @return The string name. + * Returns string for the active APN host. + * @return type as a string or null if none. + */ + String getActiveApnHost(); + + /** + * Return the LinkProperties for the named apn or null if not available */ - String getActiveApn(); + LinkProperties getLinkProperties(String apnType); + + /** + * Return the LinkCapabilities + */ + LinkCapabilities getLinkCapabilities(String apnType); /** * Get current signal strength. No change notification available on this @@ -1306,36 +1325,6 @@ public interface Phone { SimulatedRadioControl getSimulatedRadioControl(); /** - * Allow mobile data connections. - * @return {@code true} if the operation started successfully - * <br/>{@code false} if it - * failed immediately.<br/> - * Even in the {@code true} case, it may still fail later - * during setup, in which case an asynchronous indication will - * be supplied. - */ - boolean enableDataConnectivity(); - - /** - * Disallow mobile data connections, and terminate any that - * are in progress. - * @return {@code true} if the operation started successfully - * <br/>{@code false} if it - * failed immediately.<br/> - * Even in the {@code true} case, it may still fail later - * during setup, in which case an asynchronous indication will - * be supplied. - */ - boolean disableDataConnectivity(); - - /** - * Report the current state of data connectivity (enabled or disabled) - * @return {@code false} if data connectivity has been explicitly disabled, - * {@code true} otherwise. - */ - boolean isDataConnectivityEnabled(); - - /** * Enables the specified APN type. Only works for "special" APN types, * i.e., not the default APN. * @param type The desired APN type. Cannot be {@link #APN_TYPE_DEFAULT}. @@ -1373,29 +1362,6 @@ public interface Phone { boolean isDataConnectivityPossible(); /** - * Returns the name of the network interface used by the specified APN type. - */ - String getInterfaceName(String apnType); - - /** - * Returns the IP address of the network interface used by the specified - * APN type. - */ - String getIpAddress(String apnType); - - /** - * Returns the gateway for the network interface used by the specified APN - * type. - */ - String getGateway(String apnType); - - /** - * Returns the DNS servers for the network interface used by the specified - * APN type. - */ - public String[] getDnsServers(String apnType); - - /** * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones. */ String getDeviceId(); @@ -1540,6 +1506,11 @@ public interface Phone { boolean isOtaSpNumber(String dialStr); /** + * Returns true if OTA Service Provisioning needs to be performed. + */ + boolean needsOtaServiceProvisioning(); + + /** * Register for notifications when CDMA call waiting comes * * @param h Handler that receives the notification message. diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 1674ad6..b64b45d 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -21,6 +21,8 @@ import android.app.IActivityManager; import android.content.Context; import android.content.res.Configuration; import android.content.SharedPreferences; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Handler; @@ -35,10 +37,8 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; -import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; -import java.util.List; import java.util.Locale; @@ -115,6 +115,7 @@ public abstract class PhoneBase extends Handler implements Phone { int mCallRingContinueToken = 0; int mCallRingDelay; public boolean mIsTheCurrentActivePhone = true; + boolean mIsVoiceCapable = true; /** * Set a system property, unless we're in unit test mode @@ -205,6 +206,15 @@ public abstract class PhoneBase extends Handler implements Phone { mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false); mCM.setOnCallRing(this, EVENT_CALL_RING, null); + /* "Voice capable" means that this device supports circuit-switched + * (i.e. voice) phone calls over the telephony network, and is allowed + * to display the in-call UI while a cellular voice call is active. + * This will be false on "data only" devices which can't make voice + * calls and don't support any in-call UI. + */ + mIsVoiceCapable = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable); + /** * Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs * to be generated locally. Ideally all ring tones should be loops @@ -558,11 +568,6 @@ public abstract class PhoneBase extends Handler implements Phone { String c = carrierLocales[i].toString(); if (carrier.equals(c)) { String l = carrierLocales[i+1].toString(); - int wifiChannels = 0; - try { - wifiChannels = Integer.parseInt( - carrierLocales[i+2].toString()); - } catch (NumberFormatException e) { } String language = l.substring(0, 2); String country = ""; @@ -571,15 +576,15 @@ public abstract class PhoneBase extends Handler implements Phone { } setSystemLocale(language, country); - if (wifiChannels != 0) { + if (!country.isEmpty()) { try { Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS); + Settings.Secure.WIFI_COUNTRY_CODE); } catch (Settings.SettingNotFoundException e) { // note this is not persisting WifiManager wM = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - wM.setNumAllowedChannels(wifiChannels, false); + wM.setCountryCode(country, false); } } return; @@ -741,8 +746,24 @@ public abstract class PhoneBase extends Handler implements Phone { mNotifier.notifyMessageWaitingChanged(this); } - public void notifyDataConnection(String reason) { - mNotifier.notifyDataConnection(this, reason); + public void notifyDataConnection(String reason, String apnType, + Phone.DataState state) { + mNotifier.notifyDataConnection(this, reason, apnType, state); + } + + public void notifyDataConnection(String reason, String apnType) { + mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType)); + } + + public void notifyDataConnection() { + String types[] = getActiveApnTypes(); + for (String apnType : types) { + mNotifier.notifyDataConnection(this, null, apnType, getDataConnectionState(apnType)); + } + } + + public void notifyOtaspChanged(int otaspMode) { + mNotifier.notifyOtaspChanged(this, otaspMode); } public abstract String getPhoneName(); @@ -828,9 +849,19 @@ public abstract class PhoneBase extends Handler implements Phone { logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady"); } + /** + * Returns true if OTA Service Provisioning needs to be performed. + * If not overridden return false. + */ + public boolean needsOtaServiceProvisioning() { + return false; + } + + /** + * Return true if number is an OTASP number. + * If not overridden return false. + */ public boolean isOtaSpNumber(String dialStr) { - // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. - logUnexpectedCdmaMethodCall("isOtaSpNumber"); return false; } @@ -920,32 +951,20 @@ public abstract class PhoneBase extends Handler implements Phone { logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse"); } - public String getInterfaceName(String apnType) { - return mDataConnection.getInterfaceName(apnType); - } - - public String getIpAddress(String apnType) { - return mDataConnection.getIpAddress(apnType); - } - - public boolean isDataConnectivityEnabled() { - return mDataConnection.getDataEnabled(); + public String[] getActiveApnTypes() { + return mDataConnection.getActiveApnTypes(); } - public String getGateway(String apnType) { - return mDataConnection.getGateway(apnType); + public String getActiveApnHost() { + return mDataConnection.getActiveApnString(); } - public String[] getDnsServers(String apnType) { - return mDataConnection.getDnsServers(apnType); + public LinkProperties getLinkProperties(String apnType) { + return mDataConnection.getLinkProperties(apnType); } - public String[] getActiveApnTypes() { - return mDataConnection.getActiveApnTypes(); - } - - public String getActiveApn() { - return mDataConnection.getActiveApnString(); + public LinkCapabilities getLinkCapabilities(String apnType) { + return mDataConnection.getLinkCapabilities(apnType); } public int enableApnType(String type) { @@ -956,6 +975,10 @@ public abstract class PhoneBase extends Handler implements Phone { return mDataConnection.disableApnType(type); } + public boolean isDataConnectivityPossible() { + return ((mDataConnection != null) && (mDataConnection.isDataPossible())); + } + /** * simulateDataConnection * @@ -984,7 +1007,7 @@ public abstract class PhoneBase extends Handler implements Phone { } mDataConnection.setState(dcState); - notifyDataConnection(null); + notifyDataConnection(null, Phone.APN_TYPE_DEFAULT); } /** @@ -993,6 +1016,8 @@ public abstract class PhoneBase extends Handler implements Phone { * version scoped to their packages */ protected void notifyNewRingingConnectionP(Connection cn) { + if (!mIsVoiceCapable) + return; AsyncResult ar = new AsyncResult(null, cn, null); mNewRingingConnectionRegistrants.notifyRegistrants(ar); } @@ -1001,6 +1026,8 @@ public abstract class PhoneBase extends Handler implements Phone { * Notify registrants of a RING event. */ private void notifyIncomingRing() { + if (!mIsVoiceCapable) + return; AsyncResult ar = new AsyncResult(null, this, null); mIncomingRingRegistrants.notifyRegistrants(ar); } @@ -1009,7 +1036,8 @@ public abstract class PhoneBase extends Handler implements Phone { * Send the incoming call Ring notification if conditions are right. */ private void sendIncomingCallRingNotification(int token) { - if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) { + if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing && + (token == mCallRingContinueToken)) { Log.d(LOG_TAG, "Sending notifyIncomingRing"); notifyIncomingRing(); sendMessageDelayed( @@ -1018,7 +1046,8 @@ public abstract class PhoneBase extends Handler implements Phone { Log.d(LOG_TAG, "Ignoring ring notification request," + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing + " token=" + token - + " mCallRingContinueToken=" + mCallRingContinueToken); + + " mCallRingContinueToken=" + mCallRingContinueToken + + " mIsVoiceCapable=" + mIsVoiceCapable); } } @@ -1038,6 +1067,10 @@ public abstract class PhoneBase extends Handler implements Phone { "called, CDMAPhone inactive."); } + public DataState getDataConnectionState() { + return getDataConnectionState(APN_TYPE_DEFAULT); + } + /** * Common error logger method for unexpected calls to GSM/WCDMA-only methods. */ diff --git a/telephony/java/com/android/internal/telephony/PhoneNotifier.java b/telephony/java/com/android/internal/telephony/PhoneNotifier.java index e96eeae..28a8d22 100644 --- a/telephony/java/com/android/internal/telephony/PhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/PhoneNotifier.java @@ -33,10 +33,13 @@ public interface PhoneNotifier { public void notifyCallForwardingChanged(Phone sender); - public void notifyDataConnection(Phone sender, String reason); + /** TODO - reason should never be null */ + public void notifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state); - public void notifyDataConnectionFailed(Phone sender, String reason); + public void notifyDataConnectionFailed(Phone sender, String reason, String apnType); public void notifyDataActivity(Phone sender); + public void notifyOtaspChanged(Phone sender, int otaspMode); } diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index 77f1e6c..219efbb 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -20,13 +20,12 @@ package com.android.internal.telephony; import android.app.ActivityManagerNative; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Handler; import android.os.Message; import android.os.SystemProperties; -import android.preference.PreferenceManager; import android.telephony.CellLocation; -import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.util.Log; @@ -34,7 +33,6 @@ import android.util.Log; import com.android.internal.telephony.cdma.CDMAPhone; import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.NetworkInfo; -import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -172,7 +170,11 @@ public class PhoneProxy extends Handler implements Phone { } public DataState getDataConnectionState() { - return mActivePhone.getDataConnectionState(); + return mActivePhone.getDataConnectionState(Phone.APN_TYPE_DEFAULT); + } + + public DataState getDataConnectionState(String apnType) { + return mActivePhone.getDataConnectionState(apnType); } public DataActivityState getDataActivityState() { @@ -207,8 +209,16 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getActiveApnTypes(); } - public String getActiveApn() { - return mActivePhone.getActiveApn(); + public String getActiveApnHost() { + return mActivePhone.getActiveApnHost(); + } + + public LinkProperties getLinkProperties(String apnType) { + return mActivePhone.getLinkProperties(apnType); + } + + public LinkCapabilities getLinkCapabilities(String apnType) { + return mActivePhone.getLinkCapabilities(apnType); } public SignalStrength getSignalStrength() { @@ -640,14 +650,6 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getSimulatedRadioControl(); } - public boolean enableDataConnectivity() { - return mActivePhone.enableDataConnectivity(); - } - - public boolean disableDataConnectivity() { - return mActivePhone.disableDataConnectivity(); - } - public int enableApnType(String type) { return mActivePhone.enableApnType(type); } @@ -656,30 +658,10 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.disableApnType(type); } - public boolean isDataConnectivityEnabled() { - return mActivePhone.isDataConnectivityEnabled(); - } - public boolean isDataConnectivityPossible() { return mActivePhone.isDataConnectivityPossible(); } - public String getInterfaceName(String apnType) { - return mActivePhone.getInterfaceName(apnType); - } - - public String getIpAddress(String apnType) { - return mActivePhone.getIpAddress(apnType); - } - - public String getGateway(String apnType) { - return mActivePhone.getGateway(apnType); - } - - public String[] getDnsServers(String apnType) { - return mActivePhone.getDnsServers(apnType); - } - public String getDeviceId() { return mActivePhone.getDeviceId(); } @@ -768,6 +750,10 @@ public class PhoneProxy extends Handler implements Phone { mActivePhone.exitEmergencyCallbackMode(); } + public boolean needsOtaServiceProvisioning(){ + return mActivePhone.needsOtaServiceProvisioning(); + } + public boolean isOtaSpNumber(String dialStr){ return mActivePhone.isOtaSpNumber(dialStr); } diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index af483db..c97ba6e 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -286,9 +286,8 @@ public final class RIL extends BaseCommands implements CommandsInterface { } - //***** Handler implemementation - - public void + //***** Handler implementation + @Override public void handleMessage(Message msg) { RILRequest rr = (RILRequest)(msg.obj); RILRequest req = null; @@ -786,7 +785,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { send(rr); } - public void + @Deprecated public void getPDPContextList(Message result) { getDataCallList(result); } @@ -1271,33 +1270,6 @@ public final class RIL extends BaseCommands implements CommandsInterface { } /** - * @deprecated - */ - public void - setupDefaultPDP(String apn, String user, String password, Message result) { - int radioTechnology; - int authType; - String profile = ""; //profile number, NULL for GSM/UMTS - - radioTechnology = RILConstants.SETUP_DATA_TECH_GSM; - //TODO(): Add to the APN database, AuthType is set to CHAP/PAP - authType = (user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP - : RILConstants.SETUP_DATA_AUTH_NONE; - - setupDataCall(Integer.toString(radioTechnology), profile, apn, user, - password, Integer.toString(authType), result); - - } - - /** - * @deprecated - */ - public void - deactivateDefaultPDP(int cid, Message result) { - deactivateDataCall(cid, result); - } - - /** * The preferred new alternative to setupDefaultPDP that is * CDMA-compatible. * @@ -1305,10 +1277,18 @@ public final class RIL extends BaseCommands implements CommandsInterface { public void setupDataCall(String radioTechnology, String profile, String apn, String user, String password, String authType, Message result) { + setupDataCallWithProtocol(radioTechnology, profile, apn, user, password, + authType, "IP", result); + } + + public void + setupDataCallWithProtocol(String radioTechnology, String profile, + String apn, String user, String password, String authType, + String protocolType, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); - rr.mp.writeInt(6); + rr.mp.writeInt(7); rr.mp.writeString(radioTechnology); rr.mp.writeString(profile); @@ -1316,25 +1296,27 @@ public final class RIL extends BaseCommands implements CommandsInterface { rr.mp.writeString(user); rr.mp.writeString(password); rr.mp.writeString(authType); + rr.mp.writeString(protocolType); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + radioTechnology + " " + profile + " " + apn + " " + user + " " - + password + " " + authType); + + password + " " + authType + " " + protocolType); send(rr); } public void - deactivateDataCall(int cid, Message result) { + deactivateDataCall(int cid, int reason, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DATA_CALL, result); - rr.mp.writeInt(1); + rr.mp.writeInt(2); rr.mp.writeString(Integer.toString(cid)); + rr.mp.writeString(Integer.toString(reason)); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + - requestToString(rr.mRequest) + " " + cid); + requestToString(rr.mRequest) + " " + cid + " " + reason); send(rr); } @@ -2919,7 +2901,11 @@ public final class RIL extends BaseCommands implements CommandsInterface { dataCall.active = p.readInt(); dataCall.type = p.readString(); dataCall.apn = p.readString(); - dataCall.address = p.readString(); + String address = p.readString(); + if (address != null) { + address = address.split(" ")[0]; + } + dataCall.address = address; response.add(dataCall); } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 888f721..305e15f 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -96,6 +96,10 @@ public interface RILConstants { int SETUP_DATA_AUTH_CHAP = 2; int SETUP_DATA_AUTH_PAP_CHAP = 3; + /* Deactivate data call reasons */ + int DEACTIVATE_REASON_NONE = 0; + int DEACTIVATE_REASON_RADIO_OFF = 1; + /* cat include/telephony/ril.h | \ egrep '^#define' | \ diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java index f93e494..ec49a19 100644 --- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java @@ -258,6 +258,7 @@ public abstract class SMSDispatcher extends Handler { mCm.unregisterForOn(this); } + @Override protected void finalize() { Log.d(TAG, "SMSDispatcher finalized"); } @@ -933,14 +934,14 @@ public abstract class SMSDispatcher extends Handler { */ static protected class SmsTracker { // fields need to be public for derived SmsDispatchers - public HashMap mData; + public HashMap<String, Object> mData; public int mRetryCount; public int mMessageRef; public PendingIntent mSentIntent; public PendingIntent mDeliveryIntent; - SmsTracker(HashMap data, PendingIntent sentIntent, + SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent) { mData = data; mSentIntent = sentIntent; @@ -949,7 +950,7 @@ public abstract class SMSDispatcher extends Handler { } } - protected SmsTracker SmsTrackerFactory(HashMap data, PendingIntent sentIntent, + protected SmsTracker SmsTrackerFactory(HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent) { return new SmsTracker(data, sentIntent, deliveryIntent); } diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java index e8bbe5e..3f9ffc3 100644 --- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java @@ -53,6 +53,12 @@ public abstract class ServiceStateTracker extends Handler { public SignalStrength mSignalStrength; + /* The otaspMode passed to PhoneStateListener#onOtaspChanged */ + static public final int OTASP_UNINITIALIZED = 0; + static public final int OTASP_UNKNOWN = 1; + static public final int OTASP_NEEDED = 2; + static public final int OTASP_NOT_NEEDED = 3; + /** * A unique identifier to track requests associated with a poll * and ignore stale responses. The value is a count-down of @@ -268,9 +274,11 @@ public abstract class ServiceStateTracker extends Handler { public abstract void handleMessage(Message msg); + protected abstract Phone getPhone(); protected abstract void handlePollStateResult(int what, AsyncResult ar); protected abstract void updateSpnDisplay(); protected abstract void setPowerStateToDesired(); + protected abstract void log(String s); /** * Clean up existing voice and data connection then turn off radio power. diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java index 7872eec..7a65162 100644 --- a/telephony/java/com/android/internal/telephony/SmsHeader.java +++ b/telephony/java/com/android/internal/telephony/SmsHeader.java @@ -30,7 +30,7 @@ import java.util.ArrayList; */ public class SmsHeader { - // TODO(cleanup): this datastructure is generally referred to as + // TODO(cleanup): this data structure is generally referred to as // the 'user data header' or UDH, and so the class name should // change to reflect this... diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java index af6c5f8..cbd8606 100644 --- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java +++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java @@ -16,7 +16,6 @@ package com.android.internal.telephony; -import android.util.Log; import com.android.internal.telephony.SmsHeader; import java.util.Arrays; @@ -366,13 +365,13 @@ public abstract class SmsMessageBase { /** * Try to parse this message as an email gateway message * There are two ways specified in TS 23.040 Section 3.8 : - * - SMS message "may have its TP-PID set for internet electronic mail - MT + * - SMS message "may have its TP-PID set for Internet electronic mail - MT * SMS format: [<from-address><space>]<message> - "Depending on the * nature of the gateway, the destination/origination address is either * derived from the content of the SMS TP-OA or TP-DA field, or the * TP-OA/TP-DA field contains a generic gateway address and the to/from * address is added at the beginning as shown above." (which is supported here) - * - Multiple addreses separated by commas, no spaces, Subject field delimited + * - Multiple addresses separated by commas, no spaces, Subject field delimited * by '()' or '##' and '#' Section 9.2.3.24.11 (which are NOT supported here) */ protected void extractEmailAddressFromMessageBody() { diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index a113787..136d5b1 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -45,7 +45,7 @@ public interface TelephonyProperties * CDMA networks. */ static final String PROPERTY_OPERATOR_ALPHA = "gsm.operator.alpha"; - //TODO: most of these proprieties are generic, substitute gsm. with phone. bug 1856959 + //TODO: most of these properties are generic, substitute gsm. with phone. bug 1856959 /** Numeric name (MCC+MNC) of current registered operator.<p> * Availability: when registered to a network. Result may be unreliable on @@ -83,12 +83,12 @@ public interface TelephonyProperties /** The MCC+MNC (mobile country code+mobile network code) of the * provider of the SIM. 5 or 6 decimal digits. - * Availablity: SIM state must be "READY" + * Availability: SIM state must be "READY" */ static String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric"; /** PROPERTY_ICC_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name. - * Availablity: SIM state must be "READY" + * Availability: SIM state must be "READY" */ static String PROPERTY_ICC_OPERATOR_ALPHA = "gsm.sim.operator.alpha"; @@ -127,7 +127,7 @@ public interface TelephonyProperties "ro.telephony.call_ring.multiple"; /** - * The number of milli-seconds between CALL_RING notifications. + * The number of milliseconds between CALL_RING notifications. */ static final String PROPERTY_CALL_RING_DELAY = "ro.telephony.call_ring.delay"; diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index f31bf24..1e77589 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -61,6 +61,7 @@ import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneProxy; import com.android.internal.telephony.PhoneSubInfo; +import com.android.internal.telephony.ServiceStateTracker; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.UUSInfo; @@ -83,10 +84,6 @@ public class CDMAPhone extends PhoneBase { static final String LOG_TAG = "CDMA"; private static final boolean DBG = true; - // Min values used to by needsActivation - private static final String UNACTIVATED_MIN2_VALUE = "000000"; - private static final String UNACTIVATED_MIN_VALUE = "1111110111"; - // Default Emergency Callback Mode exit timer private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000; @@ -481,10 +478,6 @@ public class CDMAPhone extends PhoneBase { return mSST.cellLoc; } - public boolean disableDataConnectivity() { - return mDataConnection.setDataEnabled(false); - } - public CdmaCall getForegroundCall() { return mCT.foregroundCall; } @@ -515,14 +508,6 @@ public class CDMAPhone extends PhoneBase { return false; } - public boolean isDataConnectivityPossible() { - boolean noData = mDataConnection.getDataEnabled() && - getDataConnectionState() == DataState.DISCONNECTED; - return !noData && getIccCard().getState() == IccCard.State.READY && - getServiceState().getState() == ServiceState.STATE_IN_SERVICE && - (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming()); - } - /** * Removes the given MMI from the pending list and notifies registrants that * it is complete. @@ -613,7 +598,7 @@ public class CDMAPhone extends PhoneBase { } } - public DataState getDataConnectionState() { + public DataState getDataConnectionState(String apnType) { DataState ret = DataState.DISCONNECTED; if (mSST == null) { @@ -625,6 +610,8 @@ public class CDMAPhone extends PhoneBase { // If we're out of service, open TCP sockets may still work // but no data will flow ret = DataState.DISCONNECTED; + } else if (mDataConnection.isApnTypeEnabled(apnType) == false) { + ret = DataState.DISCONNECTED; } else { switch (mDataConnection.getState()) { case FAILED: @@ -770,21 +757,6 @@ public class CDMAPhone extends PhoneBase { return ret; } - public boolean enableDataConnectivity() { - - // block data activities when phone is in emergency callback mode - if (mIsPhoneInEcmState) { - Intent intent = new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS); - ActivityManagerNative.broadcastStickyIntent(intent, null); - return false; - } else if ((mCT.state == Phone.State.OFFHOOK) && mCT.isInEmergencyCall()) { - // Do not allow data call to be enabled when emergency call is going on - return false; - } else { - return mDataConnection.setDataEnabled(true); - } - } - public boolean getIccRecordsLoaded() { return mRuimRecords.getRecordsLoaded(); } @@ -878,26 +850,6 @@ public class CDMAPhone extends PhoneBase { mRuimRecords.setVoiceMessageWaiting(1, mwi); } - /** - * Returns true if CDMA OTA Service Provisioning needs to be performed. - */ - /* package */ boolean - needsOtaServiceProvisioning() { - String cdmaMin = getCdmaMin(); - boolean needsProvisioning; - if (cdmaMin == null || (cdmaMin.length() < 6)) { - if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: illegal cdmaMin='" - + cdmaMin + "' assume provisioning needed."); - needsProvisioning = true; - } else { - needsProvisioning = (cdmaMin.equals(UNACTIVATED_MIN_VALUE) - || cdmaMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) - || SystemProperties.getBoolean("test_cdma_setup", false); - } - if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: ret=" + needsProvisioning); - return needsProvisioning; - } - @Override public void exitEmergencyCallbackMode() { if (mWakeLock.isHeld()) { @@ -950,7 +902,7 @@ public class CDMAPhone extends PhoneBase { // send an Intent sendEmergencyCallbackModeChange(); // Re-initiate data connection - mDataConnection.setDataEnabled(true); + mDataConnection.setInternalDataEnabled(true); } } @@ -963,13 +915,13 @@ public class CDMAPhone extends PhoneBase { switch(action) { case CANCEL_ECM_TIMER: removeCallbacks(mExitEcmRunnable); - mEcmTimerResetRegistrants.notifyResult(new Boolean(true)); + mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE); break; case RESTART_ECM_TIMER: long delayInMillis = SystemProperties.getLong( TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE); postDelayed(mExitEcmRunnable, delayInMillis); - mEcmTimerResetRegistrants.notifyResult(new Boolean(false)); + mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE); break; default: Log.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action); @@ -1191,6 +1143,14 @@ public class CDMAPhone extends PhoneBase { mSMS.setCellBroadcastConfig(configValuesArray, response); } + /** + * Returns true if OTA Service Provisioning needs to be performed. + */ + @Override + public boolean needsOtaServiceProvisioning() { + return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED; + } + private static final String IS683A_FEATURE_CODE = "*228"; private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4; private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2; diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java index 3669e60..a89f783 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java @@ -354,6 +354,24 @@ public final class CdmaCallTracker extends CallTracker { || (foregroundCall.getState() == CdmaCall.State.ACTIVE) || !backgroundCall.getState().isAlive()); + if (!ret) { + log(String.format("canDial is false\n" + + "((serviceState=%d) != ServiceState.STATE_POWER_OFF)::=%s\n" + + "&& pendingMO == null::=%s\n" + + "&& !ringingCall.isRinging()::=%s\n" + + "&& !disableCall.equals(\"true\")::=%s\n" + + "&& (!foregroundCall.getState().isAlive()::=%s\n" + + " || foregroundCall.getState() == CdmaCall.State.ACTIVE::=%s\n" + + " ||!backgroundCall.getState().isAlive())::=%s)", + serviceState, + serviceState != ServiceState.STATE_POWER_OFF, + pendingMO == null, + !ringingCall.isRinging(), + !disableCall.equals("true"), + !foregroundCall.getState().isAlive(), + foregroundCall.getState() == CdmaCall.State.ACTIVE, + !backgroundCall.getState().isAlive())); + } return ret; } @@ -1040,7 +1058,7 @@ public final class CdmaCallTracker extends CallTracker { if (PhoneNumberUtils.isEmergencyNumber(dialString)) { if (Phone.DEBUG_PHONE) log("disableDataCallInEmergencyCall"); mIsInEmergencyCall = true; - phone.disableDataConnectivity(); + phone.mDataConnection.setInternalDataEnabled(false); } } @@ -1057,8 +1075,7 @@ public final class CdmaCallTracker extends CallTracker { } if (inEcm.compareTo("false") == 0) { // Re-initiate data connection - // TODO - can this be changed to phone.enableDataConnectivity(); - phone.mDataConnection.setDataEnabled(true); + phone.mDataConnection.setInternalDataEnabled(true); } } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java index 95cb1c6..c645da5 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java @@ -20,9 +20,9 @@ import android.os.Message; import android.util.Log; import com.android.internal.telephony.DataConnection; -import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.RetryManager; /** * {@hide} @@ -39,23 +39,27 @@ public class CdmaDataConnection extends DataConnection { // ***** Constructor - private CdmaDataConnection(CDMAPhone phone, String name) { - super(phone, name); + private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) { + super(phone, name, rm); } /** * Create the connection object * - * @param phone + * @param phone the Phone + * @param id the connection id + * @param rm the RetryManager * @return CdmaDataConnection that was created. */ - static CdmaDataConnection makeDataConnection(CDMAPhone phone) { + static CdmaDataConnection makeDataConnection(CDMAPhone phone, int id, RetryManager rm) { synchronized (mCountLock) { mCount += 1; } - CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDataConnection-" + mCount); + CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, + "CdmaDataConnection-" + mCount, rm); cdmaDc.start(); if (DBG) cdmaDc.log("Made " + cdmaDc.getName()); + cdmaDc.mId = id; return cdmaDc; } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index 9f2a44b..60df7df 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -18,23 +18,13 @@ package com.android.internal.telephony.cdma; import android.app.AlarmManager; import android.app.PendingIntent; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.IConnectivityManager; -import android.net.NetworkInfo; import android.net.TrafficStats; -import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; -import android.preference.PreferenceManager; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.cdma.CdmaCellLocation; @@ -42,16 +32,15 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; +import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.DataConnection.FailCause; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.EventLogTags; -import com.android.internal.telephony.gsm.ApnSetting; -import com.android.internal.telephony.Phone; import com.android.internal.telephony.RetryManager; -import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.Phone; import java.util.ArrayList; @@ -63,20 +52,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private CDMAPhone mCdmaPhone; - // Indicates baseband will not auto-attach - private boolean noAutoAttach = false; - private boolean mIsScreenOn = true; - //useful for debugging - boolean failNextConnect = false; + boolean mFailNextConnect = false; - /** - * dataConnectionList holds all the Data connection - */ - private ArrayList<DataConnection> dataConnectionList; - - /** Currently active CdmaDataConnection */ - private CdmaDataConnection mActiveDataConnection; + /** The DataConnection being setup */ + private CdmaDataConnection mPendingDataConnection; private boolean mPendingRestartRadio = false; private static final int TIME_DELAYED_TO_RESTART_RADIO = @@ -87,10 +67,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { */ private static final int DATA_CONNECTION_POOL_SIZE = 1; - private static final int POLL_CONNECTION_MILLIS = 5 * 1000; private static final String INTENT_RECONNECT_ALARM = - "com.android.internal.telephony.cdma-reconnect"; - private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason"; + "com.android.internal.telephony.cdma-reconnect"; /** * Constants for the data connection activity: @@ -111,51 +89,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { Phone.APN_TYPE_MMS, Phone.APN_TYPE_HIPRI }; - // if we have no active Apn this is null - protected ApnSetting mActiveApn; - - // Possibly promote to base class, the only difference is - // the INTENT_RECONNECT_ALARM action is a different string. - // Do consider technology changes if it is promoted. - BroadcastReceiver mIntentReceiver = new BroadcastReceiver () - { - @Override - public void onReceive(Context context, Intent intent) - { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_SCREEN_ON)) { - mIsScreenOn = true; - stopNetStatPoll(); - startNetStatPoll(); - } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { - mIsScreenOn = false; - stopNetStatPoll(); - startNetStatPoll(); - } else if (action.equals((INTENT_RECONNECT_ALARM))) { - Log.d(LOG_TAG, "Data reconnect alarm. Previous state was " + state); - - String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON); - if (state == State.FAILED) { - cleanUpConnection(false, reason); - } - trySetupData(reason); - } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - final android.net.NetworkInfo networkInfo = (NetworkInfo) - intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); - mIsWifiConnected = (networkInfo != null && networkInfo.isConnected()); - } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; - - if (!enabled) { - // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION - // quit and wont report disconnected til next enalbing. - mIsWifiConnected = false; - } - } - } - }; - + private static final int mDefaultApnId = DataConnectionTracker.APN_DEFAULT_ID; /* Constructor */ @@ -176,88 +110,54 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null); p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null); - IntentFilter filter = new IntentFilter(); - filter.addAction(INTENT_RECONNECT_ALARM); - filter.addAction(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - - // TODO: Why is this registering the phone as the receiver of the intent - // and not its own handler? - p.getContext().registerReceiver(mIntentReceiver, filter, null, p); - mDataConnectionTracker = this; createAllDataConnectionList(); - - // This preference tells us 1) initial condition for "dataEnabled", - // and 2) whether the RIL will setup the baseband to auto-PS attach. - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext()); - - boolean dataEnabledSetting = true; - try { - dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager. - getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled(); - } catch (Exception e) { - // nothing to do - use the old behavior and leave data on - } - dataEnabled[APN_DEFAULT_ID] = - !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false) && - dataEnabledSetting; - if (dataEnabled[APN_DEFAULT_ID]) { - enabledCount++; - } - noAutoAttach = !dataEnabled[APN_DEFAULT_ID]; - - if (!mRetryMgr.configure(SystemProperties.get("ro.cdma.data_retry_config"))) { - if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) { - // Should never happen, log an error and default to a simple linear sequence. - Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG=" - + DEFAULT_DATA_RETRY_CONFIG); - mRetryMgr.configure(20, 2000, 1000); - } - } + broadcastMessenger(); } + @Override public void dispose() { + super.dispose(); + // Unregister from all events - phone.mCM.unregisterForAvailable(this); - phone.mCM.unregisterForOffOrNotAvailable(this); + mPhone.mCM.unregisterForAvailable(this); + mPhone.mCM.unregisterForOffOrNotAvailable(this); mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this); - phone.mCM.unregisterForNVReady(this); - phone.mCM.unregisterForDataStateChanged(this); + mPhone.mCM.unregisterForNVReady(this); + mPhone.mCM.unregisterForDataStateChanged(this); mCdmaPhone.mCT.unregisterForVoiceCallEnded(this); mCdmaPhone.mCT.unregisterForVoiceCallStarted(this); mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this); mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this); mCdmaPhone.mSST.unregisterForRoamingOn(this); mCdmaPhone.mSST.unregisterForRoamingOff(this); - phone.mCM.unregisterForCdmaOtaProvision(this); + mPhone.mCM.unregisterForCdmaOtaProvision(this); - phone.getContext().unregisterReceiver(this.mIntentReceiver); destroyAllDataConnectionList(); } + @Override protected void finalize() { - if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized"); + if(DBG) log("CdmaDataConnectionTracker finalized"); } + @Override + protected String getActionIntentReconnectAlarm() { + return INTENT_RECONNECT_ALARM; + } + + @Override protected void setState(State s) { if (DBG) log ("setState: " + s); - if (state != s) { + if (mState != s) { EventLog.writeEvent(EventLogTags.CDMA_DATA_STATE_CHANGE, - state.toString(), s.toString()); - state = s; + mState.toString(), s.toString()); + mState = s; } } @Override - protected boolean isApnTypeActive(String type) { - return mActiveApn != null && mActiveApn.canHandleType(type); - } - - @Override protected boolean isApnTypeAvailable(String type) { for (String s : mSupportedApnTypes) { if (TextUtils.equals(type, s)) { @@ -267,21 +167,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { return false; } - protected String[] getActiveApnTypes() { - String[] result; - if (mActiveApn != null) { - result = mActiveApn.types; - } else { - result = new String[1]; - result[0] = Phone.APN_TYPE_DEFAULT; - } - return result; - } - - protected String getActiveApnString() { - return null; - } - /** * The data connection is expected to be setup while device * 1. has ruim card or non-volatile data store @@ -291,84 +176,98 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { * * @return false while no data connection if all above requirements are met. */ + @Override public boolean isDataConnectionAsDesired() { - boolean roaming = phone.getServiceState().getRoaming(); + boolean roaming = mPhone.getServiceState().getRoaming(); - if (((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || + if (((mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || mCdmaPhone.mRuimRecords.getRecordsLoaded()) && (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() == ServiceState.STATE_IN_SERVICE) && (!roaming || getDataOnRoamingEnabled()) && !mIsWifiConnected ) { - return (state == State.CONNECTED); + return (mState == State.CONNECTED); } return true; } - private boolean isDataAllowed() { - boolean roaming = phone.getServiceState().getRoaming(); - return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled()) && mMasterDataEnabled; + @Override + protected boolean isDataAllowed() { + int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState(); + boolean roaming = (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()); + boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState(); + + boolean allowed = + (psState == ServiceState.STATE_IN_SERVICE || + mAutoAttachOnCreation) && + (mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY || + mCdmaPhone.mRuimRecords.getRecordsLoaded()) && + (mCdmaPhone.mSST.isConcurrentVoiceAndData() || + mPhone.getState() == Phone.State.IDLE) && + !roaming && + mInternalDataEnabled && + desiredPowerState && + !mPendingRestartRadio && + !mCdmaPhone.needsOtaServiceProvisioning(); + if (!allowed && DBG) { + String reason = ""; + if (!((psState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) { + reason += " - psState= " + psState; + } + if (!(mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY || + mCdmaPhone.mRuimRecords.getRecordsLoaded())) { + reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded"; + } + if (!(mCdmaPhone.mSST.isConcurrentVoiceAndData() || + mPhone.getState() == Phone.State.IDLE)) { + reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState(); + } + if (roaming) reason += " - Roaming"; + if (!mInternalDataEnabled) reason += " - mInternalDataEnabled= false"; + if (!desiredPowerState) reason += " - desiredPowerState= false"; + if (mPendingRestartRadio) reason += " - mPendingRestartRadio= true"; + if (mCdmaPhone.needsOtaServiceProvisioning()) reason += " - needs Provisioning"; + log("Data not allowed due to" + reason); + } + return allowed; } private boolean trySetupData(String reason) { if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason)); - if (phone.getSimulatedRadioControl() != null) { + if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); + notifyOffApnsOfAvailability(reason, true); - Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected"); + log("(fix?) We're on the simulator; assuming data is connected"); return true; } int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState(); - boolean roaming = phone.getServiceState().getRoaming(); + boolean roaming = mPhone.getServiceState().getRoaming(); boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState(); - if ((state == State.IDLE || state == State.SCANNING) - && (psState == ServiceState.STATE_IN_SERVICE) - && ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || - mCdmaPhone.mRuimRecords.getRecordsLoaded()) - && (mCdmaPhone.mSST.isConcurrentVoiceAndData() || - phone.getState() == Phone.State.IDLE ) - && isDataAllowed() - && desiredPowerState - && !mPendingRestartRadio - && !mCdmaPhone.needsOtaServiceProvisioning()) { - - return setupData(reason); - + if ((mState == State.IDLE || mState == State.SCANNING) && + isDataAllowed() && getAnyDataEnabled()) { + boolean retValue = setupData(reason); + notifyOffApnsOfAvailability(reason, retValue); + return retValue; } else { - if (DBG) { - log("trySetupData: Not ready for data: " + - " dataState=" + state + - " PS state=" + psState + - " radio state=" + phone.mCM.getRadioState() + - " ruim=" + mCdmaPhone.mRuimRecords.getRecordsLoaded() + - " concurrentVoice&Data=" + mCdmaPhone.mSST.isConcurrentVoiceAndData() + - " phoneState=" + phone.getState() + - " dataEnabled=" + getAnyDataEnabled() + - " roaming=" + roaming + - " dataOnRoamingEnable=" + getDataOnRoamingEnabled() + - " desiredPowerState=" + desiredPowerState + - " PendingRestartRadio=" + mPendingRestartRadio + - " MasterDataEnabled=" + mMasterDataEnabled + - " needsOtaServiceProvisioning=" + mCdmaPhone.needsOtaServiceProvisioning()); - } + notifyOffApnsOfAvailability(reason, false); return false; } } /** - * If tearDown is true, this only tears down a CONNECTED session. Presently, - * there is no mechanism for abandoning an INITING/CONNECTING session, - * but would likely involve cancelling pending async requests or - * setting a flag or new state to ignore them when they came in - * @param tearDown true if the underlying DataConnection should be - * disconnected. - * @param reason reason for the clean up. + * Cleanup all connections. + * + * TODO: Cleanup only a specified connection passed as a parameter. + * + * @param tearDown true if the underlying DataConnection should be disconnected. + * @param reason for the clean up. */ private void cleanUpConnection(boolean tearDown, String reason) { if (DBG) log("cleanUpConnection: reason: " + reason); @@ -376,19 +275,21 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { // Clear the reconnect alarm, if set. if (mReconnectIntent != null) { AlarmManager am = - (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); + (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); am.cancel(mReconnectIntent); mReconnectIntent = null; } setState(State.DISCONNECTING); + notifyDataAvailability(reason); boolean notificationDeferred = false; - for (DataConnection conn : dataConnectionList) { + for (DataConnection conn : mDataConnections.values()) { if(conn != null) { if (tearDown) { if (DBG) log("cleanUpConnection: teardown, call conn.disconnect"); - conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason)); + conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, + conn.getDataConnectionId(), 0, reason)); notificationDeferred = true; } else { if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously"); @@ -407,10 +308,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } private CdmaDataConnection findFreeDataConnection() { - for (DataConnection connBase : dataConnectionList) { - CdmaDataConnection conn = (CdmaDataConnection) connBase; - if (conn.isInactive()) { - return conn; + for (DataConnection dc : mDataConnections.values()) { + if (dc.isInactive()) { + return (CdmaDataConnection) dc; } } return null; @@ -424,15 +324,20 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { return false; } - mActiveDataConnection = conn; + /** TODO: We probably want the connection being setup to a parameter passed around */ + mPendingDataConnection = conn; String[] types; + int apnId; if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) { types = new String[1]; types[0] = Phone.APN_TYPE_DUN; + apnId = DataConnectionTracker.APN_DUN_ID; } else { types = mDefaultApnTypes; + apnId = mDefaultApnId; } - mActiveApn = new ApnSetting(0, "", "", "", "", "", "", "", "", "", "", 0, types); + mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "", "", 0, types); + if (DBG) log("setupData: mActiveApn=" + mActiveApn); Message msg = obtainMessage(); msg.what = EVENT_DATA_SETUP_COMPLETE; @@ -440,40 +345,43 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { conn.connect(msg, mActiveApn); setState(State.INITING); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); return true; } private void notifyDefaultData(String reason) { setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); startNetStatPoll(); mRetryMgr.resetRetryCount(); } private void resetPollStats() { - txPkts = -1; - rxPkts = -1; - sentSinceLastRecv = 0; - netStatPollPeriod = POLL_NETSTAT_MILLIS; + mTxPkts = -1; + mRxPkts = -1; + mSentSinceLastRecv = 0; + mNetStatPollPeriod = POLL_NETSTAT_MILLIS; mNoRecvPollCount = 0; } + @Override protected void startNetStatPoll() { - if (state == State.CONNECTED && netStatPollEnabled == false) { - Log.d(LOG_TAG, "[DataConnection] Start poll NetStat"); + if (mState == State.CONNECTED && mNetStatPollEnabled == false) { + log("[DataConnection] Start poll NetStat"); resetPollStats(); - netStatPollEnabled = true; + mNetStatPollEnabled = true; mPollNetStat.run(); } } + @Override protected void stopNetStatPoll() { - netStatPollEnabled = false; + mNetStatPollEnabled = false; removeCallbacks(mPollNetStat); - Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat"); + log("[DataConnection] Stop poll NetStat"); } + @Override protected void restartRadio() { if (DBG) log("Cleanup connection and wait " + (TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio"); @@ -490,73 +398,73 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { Activity newActivity; - preTxPkts = txPkts; - preRxPkts = rxPkts; + preTxPkts = mTxPkts; + preRxPkts = mRxPkts; - txPkts = TrafficStats.getMobileTxPackets(); - rxPkts = TrafficStats.getMobileRxPackets(); + mTxPkts = TrafficStats.getMobileTxPackets(); + mRxPkts = TrafficStats.getMobileRxPackets(); - //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts)); + //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts)); - if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) { - sent = txPkts - preTxPkts; - received = rxPkts - preRxPkts; + if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) { + sent = mTxPkts - preTxPkts; + received = mRxPkts - preRxPkts; if ( sent > 0 && received > 0 ) { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; newActivity = Activity.DATAINANDOUT; } else if (sent > 0 && received == 0) { - if (phone.getState() == Phone.State.IDLE) { - sentSinceLastRecv += sent; + if (mPhone.getState() == Phone.State.IDLE) { + mSentSinceLastRecv += sent; } else { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; } newActivity = Activity.DATAOUT; } else if (sent == 0 && received > 0) { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; newActivity = Activity.DATAIN; } else if (sent == 0 && received == 0) { - newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE; + newActivity = (mActivity == Activity.DORMANT) ? mActivity : Activity.NONE; } else { - sentSinceLastRecv = 0; - newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE; + mSentSinceLastRecv = 0; + newActivity = (mActivity == Activity.DORMANT) ? mActivity : Activity.NONE; } - if (activity != newActivity) { - activity = newActivity; - phone.notifyDataActivity(); + if (mActivity != newActivity && mIsScreenOn) { + mActivity = newActivity; + mPhone.notifyDataActivity(); } } - if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) { + if (mSentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) { // Packets sent without ack exceeded threshold. if (mNoRecvPollCount == 0) { EventLog.writeEvent( EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED, - sentSinceLastRecv); + mSentSinceLastRecv); } if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) { mNoRecvPollCount++; // Slow down the poll interval to let things happen - netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS; + mNetStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS; } else { - if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) + + if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) + " pkts since last received"); // We've exceeded the threshold. Restart the radio. - netStatPollEnabled = false; + mNetStatPollEnabled = false; stopNetStatPoll(); restartRadio(); EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, NO_RECV_POLL_LIMIT); } } else { mNoRecvPollCount = 0; - netStatPollPeriod = POLL_NETSTAT_MILLIS; + mNetStatPollPeriod = POLL_NETSTAT_MILLIS; } - if (netStatPollEnabled) { - mDataConnectionTracker.postDelayed(this, netStatPollPeriod); + if (mNetStatPollEnabled) { + mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod); } } }; @@ -588,7 +496,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) { - if (state == State.FAILED) { + if (mState == State.FAILED) { /** * For now With CDMA we never try to reconnect on * error and instead just continue to retry @@ -596,15 +504,15 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { * TODO: Make this configurable? */ int nextReconnectDelay = mRetryMgr.getRetryTimer(); - Log.d(LOG_TAG, "Data Connection activate failed. Scheduling next attempt for " + log("Data Connection activate failed. Scheduling next attempt for " + (nextReconnectDelay / 1000) + "s"); AlarmManager am = - (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); + (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(INTENT_RECONNECT_ALARM); intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason); mReconnectIntent = PendingIntent.getBroadcast( - phone.getContext(), 0, intent, 0); + mPhone.getContext(), 0, intent, 0); am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + nextReconnectDelay, mReconnectIntent); @@ -612,7 +520,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { mRetryMgr.increaseRetryCount(); if (!shouldPostNotification(lastFailCauseCode)) { - Log.d(LOG_TAG,"NOT Posting Data Connection Unavailable notification " + log("NOT Posting Data Connection Unavailable notification " + "-- likely transient error"); } else { notifyNoData(lastFailCauseCode); @@ -622,24 +530,25 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private void notifyNoData(FailCause lastFailCauseCode) { setState(State.FAILED); + notifyDataAvailability(null); } private void gotoIdleAndNotifyDataConnection(String reason) { if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason); setState(State.IDLE); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; } protected void onRecordsLoaded() { - if (state == State.FAILED) { + if (mState == State.FAILED) { cleanUpConnection(false, null); } sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED)); } protected void onNVReady() { - if (state == State.FAILED) { + if (mState == State.FAILED) { cleanUpConnection(false, null); } sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA)); @@ -650,12 +559,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { */ @Override protected void onEnableNewApn() { - cleanUpConnection(true, Phone.REASON_APN_SWITCHED); + cleanUpConnection(true, Phone.REASON_APN_SWITCHED); } /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected boolean onTrySetupData(String reason) { return trySetupData(reason); } @@ -663,6 +573,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onRoamingOff() { trySetupData(Phone.REASON_ROAMING_OFF); } @@ -670,6 +581,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onRoamingOn() { if (getDataOnRoamingEnabled()) { trySetupData(Phone.REASON_ROAMING_ON); @@ -682,17 +594,20 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onRadioAvailable() { - if (phone.getSimulatedRadioControl() != null) { + if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(null); + notifyDataConnection(null); - Log.i(LOG_TAG, "We're on the simulator; assuming data is connected"); + log("We're on the simulator; assuming data is connected"); } - if (state != State.IDLE) { + notifyDataAvailability(null); + + if (mState != State.IDLE) { cleanUpConnection(true, null); } } @@ -700,13 +615,14 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onRadioOffOrNotAvailable() { mRetryMgr.resetRetryCount(); - if (phone.getSimulatedRadioControl() != null) { + if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved - Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless"); + log("We're on the simulator; assuming radio off is meaningless"); } else { if (DBG) log("Radio is off and clean up all connection"); cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF); @@ -716,6 +632,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onDataSetupComplete(AsyncResult ar) { String reason = null; if (ar.userObj instanceof String) { @@ -723,6 +640,10 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } if (ar.exception == null) { + // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected + mLinkProperties = getLinkProperties(mPendingDataConnection); + mLinkCapabilities = getLinkCapabilities(mPendingDataConnection); + // everything is setup notifyDefaultData(reason); } else { @@ -741,8 +662,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * Called when EVENT_DISCONNECT_DONE is received. */ - protected void onDisconnectDone(AsyncResult ar) { - if(DBG) log("EVENT_DISCONNECT_DONE"); + @Override + protected void onDisconnectDone(int connId, AsyncResult ar) { + if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId); String reason = null; if (ar.userObj instanceof String) { reason = (String) ar.userObj; @@ -762,7 +684,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { onRestartRadio(); } - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; if (retryAfterDisconnected(reason)) { trySetupData(reason); @@ -786,25 +708,29 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onVoiceCallStarted() { - if (state == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) { + if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) { stopNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); + notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); + notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED); } } /** * @override com.android.internal.telephony.DataConnectionTracker */ + @Override protected void onVoiceCallEnded() { - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); + notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); } else { // clean slate after call end. resetPollStats(); } + notifyDataAvailability(Phone.REASON_VOICE_CALL_ENDED); } else { mRetryMgr.resetRetryCount(); // in case data setup was attempted when we were on a voice call @@ -812,39 +738,49 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } } - /** - * @override com.android.internal.telephony.DataConnectionTracker - */ + @Override protected void onCleanUpConnection(boolean tearDown, String reason) { cleanUpConnection(tearDown, reason); } private void createAllDataConnectionList() { - dataConnectionList = new ArrayList<DataConnection>(); CdmaDataConnection dataConn; - for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) { - dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone); - dataConnectionList.add(dataConn); - } + /** TODO: Use one retry manager for all connections for now */ + RetryManager rm = mRetryMgr; + if (!rm.configure(SystemProperties.get("ro.cdma.data_retry_config"))) { + if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) { + // Should never happen, log an error and default to a simple linear sequence. + log("Could not configure using DEFAULT_DATA_RETRY_CONFIG=" + + DEFAULT_DATA_RETRY_CONFIG); + rm.configure(20, 2000, 1000); + } + } + + for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) { + int id = mUniqueIdGenerator.getAndIncrement(); + + dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm); + mDataConnections.put(id, dataConn); + } } private void destroyAllDataConnectionList() { - if(dataConnectionList != null) { - dataConnectionList.removeAll(dataConnectionList); + if(mDataConnections != null) { + mDataConnections.clear(); } } private void onCdmaDataDetached() { - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED); + notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED); } else { - if (state == State.FAILED) { + if (mState == State.FAILED) { cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED); mRetryMgr.resetRetryCount(); - CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation()); + CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation()); EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED, loc != null ? loc.getBaseStationId() : -1, TelephonyManager.getDefault().getNetworkType()); @@ -871,8 +807,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private void onRestartRadio() { if (mPendingRestartRadio) { - Log.d(LOG_TAG, "************TURN OFF RADIO**************"); - phone.mCM.setRadioPower(false, null); + log("************TURN OFF RADIO**************"); + mPhone.mCM.setRadioPower(false, null); /* Note: no need to call setRadioPower(true). Assuming the desired * radio power state is still ON (as tracked by ServiceStateTracker), * ServiceStateTracker will call setRadioPower when it receives the @@ -885,7 +821,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } private void writeEventLogCdmaDataDrop() { - CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation()); + CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation()); EventLog.writeEvent(EventLogTags.CDMA_DATA_DROP, loc != null ? loc.getBaseStationId() : -1, TelephonyManager.getDefault().getNetworkType()); @@ -901,7 +837,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { return; } - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { boolean isActiveOrDormantConnectionPresent = false; int connectionState = DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE; @@ -917,7 +853,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { if (!isActiveOrDormantConnectionPresent) { // No active or dormant connection - Log.i(LOG_TAG, "onDataStateChanged: No active connection" + log("onDataStateChanged: No active connection" + "state is CONNECTED, disconnecting/cleanup"); writeEventLogCdmaDataDrop(); cleanUpConnection(true, null); @@ -926,59 +862,27 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { switch (connectionState) { case DATA_CONNECTION_ACTIVE_PH_LINK_UP: - Log.v(LOG_TAG, "onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore"); - activity = Activity.NONE; - phone.notifyDataActivity(); + log("onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore"); + mActivity = Activity.NONE; + mPhone.notifyDataActivity(); startNetStatPoll(); break; case DATA_CONNECTION_ACTIVE_PH_LINK_DOWN: - Log.v(LOG_TAG, "onDataStateChanged active=LINK_DOWN && CONNECTED, dormant"); - activity = Activity.DORMANT; - phone.notifyDataActivity(); + log("onDataStateChanged active=LINK_DOWN && CONNECTED, dormant"); + mActivity = Activity.DORMANT; + mPhone.notifyDataActivity(); stopNetStatPoll(); break; default: - Log.v(LOG_TAG, "onDataStateChanged: IGNORE unexpected DataCallState.active=" + log("onDataStateChanged: IGNORE unexpected DataCallState.active=" + connectionState); } } else { // TODO: Do we need to do anything? - Log.i(LOG_TAG, "onDataStateChanged: not connected, state=" + state + " ignoring"); - } - } - - protected String getInterfaceName(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getInterface(); - } - return null; - } - - protected String getIpAddress(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getIpAddress(); - } - return null; - } - - protected String getGateway(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getGatewayAddress(); + log("onDataStateChanged: not connected, state=" + mState + " ignoring"); } - return null; - } - - protected String[] getDnsServers(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getDnsServers(); - } - return null; - } - - public ArrayList<DataConnection> getAllDataConnections() { - return dataConnectionList; } private void startDelayedRetry(FailCause cause, String reason) { @@ -986,10 +890,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { reconnectAfterFail(cause, reason); } + @Override public void handleMessage (Message msg) { - if (!phone.mIsTheCurrentActivePhone) { - Log.d(LOG_TAG, "Ignore CDMA msgs since CDMA phone is inactive"); + if (!mPhone.mIsTheCurrentActivePhone) { + log("Ignore CDMA msgs since CDMA phone is inactive"); return; } @@ -1026,7 +931,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } } + @Override protected void log(String s) { Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s); } + + @Override + protected void loge(String s) { + Log.e(LOG_TAG, "[CdmaDataConnectionTracker] " + s); + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java index d6fc134..53555d8 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java @@ -70,6 +70,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { * @param ar AsyncResult passed into the message handler. ar.result should * be a String representing the status report PDU, as ASCII hex. */ + @Override protected void handleStatusReport(AsyncResult ar) { Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!"); } @@ -92,6 +93,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected int dispatchMessage(SmsMessageBase smsb) { // If sms is null, means there was a parsing error. @@ -335,6 +337,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendData(String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -343,6 +346,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -351,6 +355,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendMultipartText(String destAddr, String scAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { @@ -359,7 +364,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { * TODO(cleanup): There is no real code difference between * this and the GSM version, and hence it should be moved to * the base class or consolidated somehow, provided calling - * the proper submitpdu stuff can be arranged. + * the proper submit pdu stuff can be arranged. */ int refNumber = getNextConcatenatedRef() & 0x00FF; @@ -432,8 +437,9 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendSms(SmsTracker tracker) { - HashMap map = tracker.mData; + HashMap<String, Object> map = tracker.mData; // byte smsc[] = (byte[]) map.get("smsc"); // unused for CDMA byte pdu[] = (byte[]) map.get("pdu"); @@ -444,11 +450,13 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendMultipartSms (SmsTracker tracker) { Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented"); } /** {@inheritDoc} */ + @Override protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ // FIXME unit test leaves cm == null. this should change @@ -469,16 +477,19 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void activateCellBroadcastSms(int activate, Message response) { mCm.setCdmaBroadcastActivation((activate == 0), response); } /** {@inheritDoc} */ + @Override protected void getCellBroadcastSmsConfig(Message response) { mCm.getCdmaBroadcastConfig(response); } /** {@inheritDoc} */ + @Override protected void setCellBroadcastConfig(int[] configValuesArray, Message response) { mCm.setCdmaBroadcastConfig(configValuesArray, response); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index d2a4bd8..de15408 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -16,6 +16,17 @@ package com.android.internal.telephony.cdma; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.CommandsInterface; +import com.android.internal.telephony.DataConnectionTracker; +import com.android.internal.telephony.EventLogTags; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.MccTable; +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.telephony.TelephonyProperties; + import android.app.AlarmManager; import android.content.ContentResolver; import android.content.Context; @@ -38,19 +49,8 @@ import android.telephony.cdma.CdmaCellLocation; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; -import android.util.Config; import android.util.TimeUtils; -import com.android.internal.telephony.CommandException; -import com.android.internal.telephony.CommandsInterface; -import com.android.internal.telephony.DataConnectionTracker; -import com.android.internal.telephony.EventLogTags; -import com.android.internal.telephony.IccCard; -import com.android.internal.telephony.MccTable; -import com.android.internal.telephony.ServiceStateTracker; -import com.android.internal.telephony.TelephonyIntents; -import com.android.internal.telephony.TelephonyProperties; - import java.util.Arrays; import java.util.Calendar; import java.util.Date; @@ -66,6 +66,13 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { CdmaCellLocation cellLoc; CdmaCellLocation newCellLoc; + // Min values used to by getOtasp() + private static final String UNACTIVATED_MIN2_VALUE = "000000"; + private static final String UNACTIVATED_MIN_VALUE = "1111110111"; + + // Current Otasp value + int mCurrentOtaspMode = OTASP_UNINITIALIZED; + /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */ private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing", @@ -121,10 +128,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { private PowerManager.WakeLock mWakeLock; private static final String WAKELOCK_TAG = "ServiceStateTracker"; - /** Track of SPN display rules, so we only broadcast intent if something changes. */ - private String curSpn = null; - private int curSpnRule = 0; - /** Contains the name of the registered network in CDMA (either ONS or ERI text). */ private String curPlmn = null; @@ -447,6 +450,13 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { if (!mIsMinInfoReady) { mIsMinInfoReady = true; } + int otaspMode = getOtasp(); + if (mCurrentOtaspMode != otaspMode) { + Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" + + mCurrentOtaspMode + " new otaspMode=" + otaspMode); + mCurrentOtaspMode = otaspMode; + phone.notifyOtaspChanged(mCurrentOtaspMode); + } phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI, null); } else { @@ -559,45 +569,24 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF; synchronized (this) { - if (networkType == ServiceState.RADIO_TECHNOLOGY_1xRTT) { - /* - * In 1x CDMA , during radio power off modem will disconnect the - * data call and sends the power down registration message along - * with the data call release message to the network - */ - - msg.arg1 = 0; // tearDown is false since modem does it anyway for 1X - dcTracker.sendMessage(msg); - - Log.w(LOG_TAG, "Turn off the radio right away"); - hangupAndPowerOff(); - } else { - if (!mPendingRadioPowerOffAfterDataOff) { - DataConnectionTracker.State currentState = dcTracker.getState(); - if (currentState != DataConnectionTracker.State.CONNECTED - && currentState != DataConnectionTracker.State.DISCONNECTING - && currentState != DataConnectionTracker.State.INITING) { - - msg.arg1 = 0; // tearDown is false as it is not needed. - dcTracker.sendMessage(msg); - - if (DBG) - log("Data disconnected, turn off radio right away."); - hangupAndPowerOff(); + if (!mPendingRadioPowerOffAfterDataOff) { + DataConnectionTracker.State currentState = dcTracker.getState(); + if (currentState != DataConnectionTracker.State.CONNECTED + && currentState != DataConnectionTracker.State.DISCONNECTING + && currentState != DataConnectionTracker.State.INITING) { + msg.arg1 = 0; // tearDown is false as it is not needed. + dcTracker.sendMessage(msg); + if (DBG) log("Data disconnected, turn off radio right away."); + hangupAndPowerOff(); + } else { + msg.arg1 = 1; // tearDown is true + dcTracker.sendMessage(msg); + if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) { + if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio."); + mPendingRadioPowerOffAfterDataOff = true; } else { - // clean data connection - msg.arg1 = 1; // tearDown is true - dcTracker.sendMessage(msg); - - if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) { - if (DBG) { - log("Wait upto 30s for data to disconnect, then turn off radio."); - } - mPendingRadioPowerOffAfterDataOff = true; - } else { - Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away."); - hangupAndPowerOff(); - } + Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away."); + hangupAndPowerOff(); } } } @@ -606,43 +595,37 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { @Override protected void updateSpnDisplay() { - String spn = ""; - boolean showSpn = false; - String plmn = ""; - boolean showPlmn = false; - int rule = 0; - if (cm.getRadioState().isRUIMReady()) { - // TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition - // Character Encoding, Language Indicator and SPN has to be set - // rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric()); - // spn = phone.mSIMRecords.getServiceProvideName(); - plmn = ss.getOperatorAlphaLong(); // mOperatorAlphaLong contains the ONS - // showSpn = (rule & ... - showPlmn = true; // showPlmn = (rule & ... - - } else { - // In this case there is no SPN available from RUIM, we show the ERI text - plmn = ss.getOperatorAlphaLong(); // mOperatorAlphaLong contains the ERI text - showPlmn = true; - } - - if (rule != curSpnRule - || !TextUtils.equals(spn, curSpn) - || !TextUtils.equals(plmn, curPlmn)) { + // TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition + // Character Encoding, Language Indicator and SPN has to be set, something like below: + // if (cm.getRadioState().isRUIMReady()) { + // rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric()); + // spn = phone.mSIMRecords.getServiceProvideName(); + // } + + // mOperatorAlphaLong contains the ERI text + String plmn = ss.getOperatorAlphaLong(); + if (!TextUtils.equals(plmn, curPlmn)) { + boolean showPlmn = !TextUtils.isEmpty(plmn); + Log.d(LOG_TAG, + String.format("updateSpnDisplay: changed sending intent" + + " showPlmn='%b' plmn='%s'", showPlmn, plmn)); Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn); - intent.putExtra(Intents.EXTRA_SPN, spn); + intent.putExtra(Intents.EXTRA_SHOW_SPN, false); + intent.putExtra(Intents.EXTRA_SPN, ""); intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn); intent.putExtra(Intents.EXTRA_PLMN, plmn); phone.getContext().sendStickyBroadcast(intent); } - curSpnRule = rule; - curSpn = spn; curPlmn = plmn; } + @Override + protected Phone getPhone() { + return phone; + } + /** * Handle the result of one of the pollState()-related requests */ @@ -1008,7 +991,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { mNeedFixZone = false; if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1140,7 +1123,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) { - phone.notifyDataConnection(null); + phone.notifyDataConnection(); } if (hasRoamingOn) { @@ -1460,7 +1443,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1550,6 +1533,14 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } } + private boolean getAutoTimeZone() { + try { + return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0; + } catch (SettingNotFoundException snfe) { + return true; + } + } + private void saveNitzTimeZone(String zoneId) { mSavedTimeZone = zoneId; } @@ -1634,10 +1625,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { return false; } - protected void log(String s) { - Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s); - } - public String getMdnNumber() { return mMdn; } @@ -1693,6 +1680,32 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } } + /** + * Returns OTASP_UNKNOWN, OTASP_NEEDED or OTASP_NOT_NEEDED + */ + int getOtasp() { + int provisioningState; + if (mMin == null || (mMin.length() < 6)) { + if (DBG) Log.d(LOG_TAG, "getOtasp: bad mMin='" + mMin + "'"); + provisioningState = OTASP_UNKNOWN; + } else { + if ((mMin.equals(UNACTIVATED_MIN_VALUE) + || mMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) + || SystemProperties.getBoolean("test_cdma_setup", false)) { + provisioningState = OTASP_NEEDED; + } else { + provisioningState = OTASP_NOT_NEEDED; + } + } + if (DBG) Log.d(LOG_TAG, "getOtasp: state=" + provisioningState); + return provisioningState; + } + + @Override + protected void log(String s) { + Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s); + } + private void hangupAndPowerOff() { // hang up all active voice calls phone.mCT.ringingCall.hangupIfAlive(); diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java index f4a6d11..29f3bc1 100644 --- a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java @@ -68,8 +68,7 @@ public class RuimSmsInterfaceManager extends IccSmsInterfaceManager { ar = (AsyncResult)msg.obj; synchronized (mLock) { if (ar.exception == null) { - mSms = (List<SmsRawData>) - buildValidRawData((ArrayList<byte[]>) ar.result); + mSms = buildValidRawData((ArrayList<byte[]>) ar.result); } else { if(DBG) log("Cannot load Sms records"); if (mSms != null) diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 54cf612..4911644 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -18,11 +18,8 @@ package com.android.internal.telephony.cdma; import android.os.Parcel; import android.os.SystemProperties; -import android.text.format.Time; import android.util.Config; import android.util.Log; -import com.android.internal.telephony.EncodeException; -import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; @@ -35,7 +32,6 @@ import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.HexDump; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java index ab79fe9..cf06dab 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java @@ -21,7 +21,6 @@ import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER; import android.util.Log; -import android.util.SparseIntArray; import android.telephony.SmsMessage; @@ -30,10 +29,8 @@ import android.text.format.Time; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsHeader; -import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; -import com.android.internal.util.HexDump; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.BitwiseOutputStream; @@ -45,13 +42,13 @@ public final class BearerData { private final static String LOG_TAG = "SMS"; /** - * Bearer Data Subparameter Indentifiers + * Bearer Data Subparameter Identifiers * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1) * NOTE: Commented subparameter types are not implemented. */ private final static byte SUBPARAM_MESSAGE_IDENTIFIER = 0x00; private final static byte SUBPARAM_USER_DATA = 0x01; - private final static byte SUBPARAM_USER_REPONSE_CODE = 0x02; + private final static byte SUBPARAM_USER_RESPONSE_CODE = 0x02; private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP = 0x03; private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE = 0x04; private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE = 0x05; @@ -697,7 +694,7 @@ public final class BearerData { /* * TODO(cleanup): CdmaSmsAddress encoding should make use of * CdmaSmsAddress.parse provided that DTMF encoding is unified, - * and the difference in 4bit vs 8bit is resolved. + * and the difference in 4-bit vs. 8-bit is resolved. */ private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException { @@ -805,6 +802,7 @@ public final class BearerData { * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details) * * @param bData an instance of BearerData. + * * @return byte array of raw encoded SMS bearer data. */ public static byte[] encode(BearerData bData) { @@ -915,7 +913,7 @@ public final class BearerData { private static String decodeUtf16(byte[] data, int offset, int numFields) throws CodingException { - // Start reading from the next 16-bit aligned boundry after offset. + // Start reading from the next 16-bit aligned boundary after offset. int padding = offset % 2; numFields -= (offset + padding) / 2; try { @@ -961,7 +959,7 @@ public final class BearerData { private static String decode7bitGsm(byte[] data, int offset, int numFields) throws CodingException { - // Start reading from the next 7-bit aligned boundry after offset. + // Start reading from the next 7-bit aligned boundary after offset. int offsetBits = offset * 8; int offsetSeptets = (offsetBits + 6) / 7; numFields -= offsetSeptets; @@ -1554,7 +1552,7 @@ public final class BearerData { case SUBPARAM_USER_DATA: decodeSuccess = decodeUserData(bData, inStream); break; - case SUBPARAM_USER_REPONSE_CODE: + case SUBPARAM_USER_RESPONSE_CODE: decodeSuccess = decodeUserResponseCode(bData, inStream); break; case SUBPARAM_REPLY_OPTION: diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java index 4f00163..4a60231 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java @@ -19,7 +19,7 @@ package com.android.internal.telephony.cdma.sms; import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress; -public final class SmsEnvelope{ +public final class SmsEnvelope { /** * Message Types * (See 3GPP2 C.S0015-B 3.4.1) diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java index 3959c67..628f11a 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -287,7 +287,7 @@ public class GSMPhone extends PhoneBase { return mPendingMMIs; } - public DataState getDataConnectionState() { + public DataState getDataConnectionState(String apnType) { DataState ret = DataState.DISCONNECTED; if (mSST == null) { @@ -300,6 +300,8 @@ public class GSMPhone extends PhoneBase { // If we're out of service, open TCP sockets may still work // but no data will flow ret = DataState.DISCONNECTED; + } else if (mDataConnection.isApnTypeEnabled(apnType) == false) { + ret = DataState.DISCONNECTED; } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */ switch (mDataConnection.getState()) { case FAILED: @@ -401,8 +403,8 @@ public class GSMPhone extends PhoneBase { } /*package*/ void - notifyDataConnectionFailed(String reason) { - mNotifier.notifyDataConnectionFailed(this, reason); + notifyDataConnectionFailed(String reason, String apnType) { + mNotifier.notifyDataConnectionFailed(this, reason, apnType); } /*package*/ void @@ -1082,35 +1084,6 @@ public class GSMPhone extends PhoneBase { mDataConnection.setDataOnRoamingEnabled(enable); } - public boolean enableDataConnectivity() { - return mDataConnection.setDataEnabled(true); - } - - public boolean disableDataConnectivity() { - return mDataConnection.setDataEnabled(false); - } - - /** - * The only circumstances under which we report that data connectivity is not - * possible are - * <ul> - * <li>Data roaming is disallowed and we are roaming.</li> - * <li>The current data state is {@code DISCONNECTED} for a reason other than - * having explicitly disabled connectivity. In other words, data is not available - * because the phone is out of coverage or some like reason.</li> - * </ul> - * @return {@code true} if data connectivity is possible, {@code false} otherwise. - */ - public boolean isDataConnectivityPossible() { - // TODO: Currently checks if any GPRS connection is active. Should it only - // check for "default"? - boolean noData = mDataConnection.getDataEnabled() && - getDataConnectionState() == DataState.DISCONNECTED; - return !noData && getIccCard().getState() == SimCard.State.READY && - getServiceState().getState() == ServiceState.STATE_IN_SERVICE && - (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming()); - } - /** * Removes the given MMI from the pending list and notifies * registrants that it is complete. diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index 09d46dd..dfba8d6 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -20,9 +20,11 @@ import android.os.Message; import android.util.Log; import android.util.Patterns; +import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.RetryManager; /** * {@hide} @@ -53,23 +55,27 @@ public class GsmDataConnection extends DataConnection { private ApnSetting apn; //***** Constructor - private GsmDataConnection(GSMPhone phone, String name) { - super(phone, name); + private GsmDataConnection(GSMPhone phone, String name, RetryManager rm) { + super(phone, name, rm); } /** * Create the connection object * - * @param phone + * @param phone the Phone + * @param id the connection id + * @param rm the RetryManager * @return GsmDataConnection that was created. */ - static GsmDataConnection makeDataConnection(GSMPhone phone) { + static GsmDataConnection makeDataConnection(GSMPhone phone, int id, RetryManager rm) { synchronized (mCountLock) { mCount += 1; } - GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount); + GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount, rm); gsmDc.start(); if (DBG) gsmDc.log("Made " + gsmDc.getName()); + gsmDc.mId = id; + gsmDc.mRetryMgr = rm; return gsmDc; } @@ -180,8 +186,8 @@ public class GsmDataConnection extends DataConnection { @Override protected boolean isDnsOk(String[] domainNameServers) { - if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1]) - && !((GSMPhone) phone).isDnsCheckDisabled()) { + if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1]) + && !((GSMPhone) phone).isDnsCheckDisabled()) { // Work around a race condition where QMI does not fill in DNS: // Deactivate PDP and let DataConnectionTracker retry. // Do not apply the race condition workaround for MMS APN @@ -189,6 +195,9 @@ public class GsmDataConnection extends DataConnection { // Otherwise, the default APN will not be restored anymore. if (!apn.types[0].equals(Phone.APN_TYPE_MMS) || !isIpAddress(apn.mmsProxy)) { + log(String.format( + "isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s", + apn.types[0], Phone.APN_TYPE_MMS, apn.mmsProxy, isIpAddress(apn.mmsProxy))); return false; } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index ab9cf2a..cd0d9e3 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -18,28 +18,19 @@ package com.android.internal.telephony.gsm; import android.app.AlarmManager; import android.app.PendingIntent; -import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; import android.database.ContentObserver; import android.database.Cursor; -import android.net.ConnectivityManager; -import android.net.IConnectivityManager; -import android.net.NetworkInfo; +import android.net.ProxyProperties; import android.net.TrafficStats; import android.net.Uri; -import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; -import android.preference.PreferenceManager; import android.provider.Settings; import android.provider.Telephony; import android.telephony.ServiceState; @@ -49,6 +40,7 @@ import android.util.EventLog; import android.util.Log; import com.android.internal.R; +import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnectionTracker; @@ -58,7 +50,11 @@ import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.DataConnection.FailCause; import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.HashMap; /** * {@hide} @@ -83,23 +79,18 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { //***** Instance Variables - // Indicates baseband will not auto-attach - private boolean noAutoAttach = false; - private boolean mReregisterOnReconnectFailure = false; private ContentResolver mResolver; - private boolean mPingTestActive = false; // Count of PDP reset attempts; reset when we see incoming, // call reRegisterNetwork, or pingTest succeeds. private int mPdpResetCount = 0; - private boolean mIsScreenOn = true; /** Delay between APN attempts */ protected static final int APN_DELAY_MILLIS = 5000; //useful for debugging - boolean failNextConnect = false; + boolean mFailNextConnect = false; /** * allApns holds all apns for this sim spn, retrieved from @@ -107,104 +98,46 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * * Create once after simcard info is loaded */ - private ArrayList<ApnSetting> allApns = null; + private ArrayList<ApnSetting> mAllApns = null; /** * waitingApns holds all apns that are waiting to be connected * * It is a subset of allApns and has the same format */ - private ArrayList<ApnSetting> waitingApns = null; - private int waitingApnsPermanentFailureCountDown = 0; - private ApnSetting preferredApn = null; + private ArrayList<ApnSetting> mWaitingApns = null; + private int mWaitingApnsPermanentFailureCountDown = 0; + private ApnSetting mPreferredApn = null; - /* Currently active APN */ - protected ApnSetting mActiveApn; + /** The DataConnection being setup */ + private GsmDataConnection mPendingDataConnection; - /** - * pdpList holds all the PDP connection, i.e. IP Link in GPRS - */ - private ArrayList<DataConnection> pdpList; - - /** Currently active DataConnection */ - private GsmDataConnection mActivePdp; + /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */ + private HashMap<String, Integer> mApnToDataConnectionId = + new HashMap<String, Integer>(); /** Is packet service restricted by network */ private boolean mIsPsRestricted = false; //***** Constants - // TODO: Increase this to match the max number of simultaneous - // PDP contexts we plan to support. - /** - * Pool size of DataConnection objects. - */ - private static final int PDP_CONNECTION_POOL_SIZE = 1; - private static final int POLL_PDP_MILLIS = 5 * 1000; private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect"; - private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason"; static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn"); static final String APN_ID = "apn_id"; private boolean canSetPreferApn = false; - // for tracking retries on the default APN - private RetryManager mDefaultRetryManager; - // for tracking retries on a secondary APN - private RetryManager mSecondaryRetryManager; - - BroadcastReceiver mIntentReceiver = new BroadcastReceiver () - { - @Override - public void onReceive(Context context, Intent intent) - { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_SCREEN_ON)) { - mIsScreenOn = true; - stopNetStatPoll(); - startNetStatPoll(); - } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { - mIsScreenOn = false; - stopNetStatPoll(); - startNetStatPoll(); - } else if (action.equals((INTENT_RECONNECT_ALARM))) { - Log.d(LOG_TAG, "GPRS reconnect alarm. Previous state was " + state); - - String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON); - if (state == State.FAILED) { - Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION); - msg.arg1 = 0; // tearDown is false - msg.obj = (String) reason; - sendMessage(msg); - } - sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA)); - } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - final android.net.NetworkInfo networkInfo = (NetworkInfo) - intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); - mIsWifiConnected = (networkInfo != null && networkInfo.isConnected()); - } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; - - if (!enabled) { - // when wifi got disabled, the NETWORK_STATE_CHANGED_ACTION - // quit and won't report disconnected til next enabling. - mIsWifiConnected = false; - } - } - } - }; - /** Watches for changes to the APN db. */ - private ApnChangeObserver apnObserver; + private ApnChangeObserver mApnObserver; //***** Constructor GsmDataConnectionTracker(GSMPhone p) { super(p); mGsmPhone = p; + p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null); p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); @@ -218,73 +151,27 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null); p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null); - IntentFilter filter = new IntentFilter(); - filter.addAction(INTENT_RECONNECT_ALARM); - filter.addAction(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - - // TODO: Why is this registering the phone as the receiver of the intent - // and not its own handler? - p.getContext().registerReceiver(mIntentReceiver, filter, null, p); - - mDataConnectionTracker = this; - mResolver = phone.getContext().getContentResolver(); + mResolver = mPhone.getContext().getContentResolver(); - apnObserver = new ApnChangeObserver(); + mApnObserver = new ApnChangeObserver(); p.getContext().getContentResolver().registerContentObserver( - Telephony.Carriers.CONTENT_URI, true, apnObserver); - - createAllPdpList(); - - // This preference tells us 1) initial condition for "dataEnabled", - // and 2) whether the RIL will setup the baseband to auto-PS attach. - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext()); - boolean dataEnabledSetting = true; - try { - dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager. - getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled(); - } catch (Exception e) { - // nothing to do - use the old behavior and leave data on - } - dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false) && - dataEnabledSetting; - if (dataEnabled[APN_DEFAULT_ID]) { - enabledCount++; - } - noAutoAttach = !dataEnabled[APN_DEFAULT_ID]; - - if (!mRetryMgr.configure(SystemProperties.get("ro.gsm.data_retry_config"))) { - if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) { - // Should never happen, log an error and default to a simple linear sequence. - Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG=" - + DEFAULT_DATA_RETRY_CONFIG); - mRetryMgr.configure(20, 2000, 1000); - } - } - - mDefaultRetryManager = mRetryMgr; - mSecondaryRetryManager = new RetryManager(); + Telephony.Carriers.CONTENT_URI, true, mApnObserver); - if (!mSecondaryRetryManager.configure(SystemProperties.get( - "ro.gsm.2nd_data_retry_config"))) { - if (!mSecondaryRetryManager.configure(SECONDARY_DATA_RETRY_CONFIG)) { - // Should never happen, log an error and default to a simple sequence. - Log.e(LOG_TAG, "Could note configure using SECONDARY_DATA_RETRY_CONFIG=" - + SECONDARY_DATA_RETRY_CONFIG); - mSecondaryRetryManager.configure("max_retries=3, 333, 333, 333"); - } - } + /** Create the default connection */ + createDataConnection(Phone.APN_TYPE_DEFAULT); + broadcastMessenger(); } + @Override public void dispose() { + super.dispose(); + //Unregister for all events - phone.mCM.unregisterForAvailable(this); - phone.mCM.unregisterForOffOrNotAvailable(this); + mPhone.mCM.unregisterForAvailable(this); + mPhone.mCM.unregisterForOffOrNotAvailable(this); mGsmPhone.mSIMRecords.unregisterForRecordsLoaded(this); - phone.mCM.unregisterForDataStateChanged(this); + mPhone.mCM.unregisterForDataStateChanged(this); mGsmPhone.mCT.unregisterForVoiceCallEnded(this); mGsmPhone.mCT.unregisterForVoiceCallStarted(this); mGsmPhone.mSST.unregisterForGprsAttached(this); @@ -294,46 +181,33 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { mGsmPhone.mSST.unregisterForPsRestrictedEnabled(this); mGsmPhone.mSST.unregisterForPsRestrictedDisabled(this); - phone.getContext().unregisterReceiver(this.mIntentReceiver); - phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver); + mPhone.getContext().getContentResolver().unregisterContentObserver(this.mApnObserver); - destroyAllPdpList(); + destroyDataConnections(); } + @Override protected void finalize() { - if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized"); + if(DBG) log("finalize"); } - protected void setState(State s) { - if (DBG) log ("setState: " + s); - if (state != s) { - EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, state.toString(), s.toString()); - state = s; - } - - if (state == State.FAILED) { - if (waitingApns != null) - waitingApns.clear(); // when teardown the connection and set to IDLE - } + @Override + protected String getActionIntentReconnectAlarm() { + return INTENT_RECONNECT_ALARM; } - public String[] getActiveApnTypes() { - String[] result; - if (mActiveApn != null) { - result = mActiveApn.types; - } else { - result = new String[1]; - result[0] = Phone.APN_TYPE_DEFAULT; + @Override + protected void setState(State s) { + if (DBG) log ("setState: " + s); + if (mState != s) { + EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, mState.toString(), s.toString()); + mState = s; } - return result; - } - protected String getActiveApnString() { - String result = null; - if (mActiveApn != null) { - result = mActiveApn.apn; + if (mState == State.FAILED) { + if (mWaitingApns != null) + mWaitingApns.clear(); // when tear down the connection and set to IDLE } - return result; } /** @@ -345,33 +219,28 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * * @return false while no data connection if all above requirements are met. */ + @Override public boolean isDataConnectionAsDesired() { - boolean roaming = phone.getServiceState().getRoaming(); + boolean roaming = mPhone.getServiceState().getRoaming(); if (mGsmPhone.mSIMRecords.getRecordsLoaded() && mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE && (!roaming || getDataOnRoamingEnabled()) && !mIsWifiConnected && !mIsPsRestricted ) { - return (state == State.CONNECTED); + return (mState == State.CONNECTED); } return true; } @Override - protected boolean isApnTypeActive(String type) { - // TODO: support simultaneous with List instead - return mActiveApn != null && mActiveApn.canHandleType(type); - } - - @Override protected boolean isApnTypeAvailable(String type) { if (type.equals(Phone.APN_TYPE_DUN)) { return (fetchDunApn() != null); } - if (allApns != null) { - for (ApnSetting apn : allApns) { + if (mAllApns != null) { + for (ApnSetting apn : mAllApns) { if (apn.canHandleType(type)) { return true; } @@ -380,20 +249,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return false; } - /** - * Formerly this method was ArrayList<GsmDataConnection> getAllPdps() - */ - public ArrayList<DataConnection> getAllDataConnections() { - ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone(); - return pdps; - } - - private boolean isDataAllowed() { - boolean roaming = phone.getServiceState().getRoaming(); - return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled()) && - mMasterDataEnabled; - } - //****** Called from ServiceStateTracker /** * Invoked when ServiceStateTracker observes a transition from GPRS @@ -405,15 +260,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * when GPRS detaches, but we should stop the network polling. */ stopNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_GPRS_DETACHED); + notifyDataConnection(Phone.REASON_GPRS_DETACHED); } private void onGprsAttached() { - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_GPRS_ATTACHED); + notifyDataConnection(Phone.REASON_GPRS_ATTACHED); } else { - if (state == State.FAILED) { + if (mState == State.FAILED) { cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED); mRetryMgr.resetRetryCount(); } @@ -421,75 +276,92 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + @Override + protected boolean isDataAllowed() { + int gprsState = mGsmPhone.mSST.getCurrentGprsState(); + boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState(); + + boolean allowed = + (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) && + mGsmPhone.mSIMRecords.getRecordsLoaded() && + mPhone.getState() == Phone.State.IDLE && + mInternalDataEnabled && + (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) && + !mIsPsRestricted && + desiredPowerState; + if (!allowed && DBG) { + String reason = ""; + if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) { + reason += " - gprs= " + gprsState; + } + if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded"; + if (mPhone.getState() != Phone.State.IDLE) { + reason += " - PhoneState= " + mPhone.getState(); + } + if (!mInternalDataEnabled) reason += " - mInternalDataEnabled= false"; + if (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()) { + reason += " - Roaming and data roaming not enabled"; + } + if (mIsPsRestricted) reason += " - mIsPsRestricted= true"; + if (!desiredPowerState) reason += " - desiredPowerState= false"; + log("Data not allowed due to" + reason); + } + return allowed; + } + private boolean trySetupData(String reason) { if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason)); - Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted); + log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted); - if (phone.getSimulatedRadioControl() != null) { + if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); - Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected"); + log("(fix?) We're on the simulator; assuming data is connected"); return true; } int gprsState = mGsmPhone.mSST.getCurrentGprsState(); boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState(); - if ((state == State.IDLE || state == State.SCANNING) - && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach) - && mGsmPhone.mSIMRecords.getRecordsLoaded() - && phone.getState() == Phone.State.IDLE - && isDataAllowed() - && !mIsPsRestricted - && desiredPowerState ) { - - if (state == State.IDLE) { - waitingApns = buildWaitingApns(); - waitingApnsPermanentFailureCountDown = waitingApns.size(); - if (waitingApns.isEmpty()) { + if (((mState == State.IDLE) || (mState == State.SCANNING)) && + isDataAllowed() && getAnyDataEnabled()) { + + if (mState == State.IDLE) { + mWaitingApns = buildWaitingApns(mRequestedApnType); + mWaitingApnsPermanentFailureCountDown = mWaitingApns.size(); + if (mWaitingApns.isEmpty()) { if (DBG) log("No APN found"); notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); + notifyOffApnsOfAvailability(reason, false); return false; } else { - log ("Create from allApns : " + apnListToString(allApns)); + log ("Create from allApns : " + apnListToString(mAllApns)); } } if (DBG) { - log ("Setup waitngApns : " + apnListToString(waitingApns)); + log ("Setup waitngApns : " + apnListToString(mWaitingApns)); } - return setupData(reason); + boolean retValue = setupData(reason); + notifyOffApnsOfAvailability(reason, retValue); + return retValue; } else { - if (DBG) - log("trySetupData: Not ready for data: " + - " dataState=" + state + - " gprsState=" + gprsState + - " sim=" + mGsmPhone.mSIMRecords.getRecordsLoaded() + - " UMTS=" + mGsmPhone.mSST.isConcurrentVoiceAndData() + - " phoneState=" + phone.getState() + - " isDataAllowed=" + isDataAllowed() + - " dataEnabled=" + getAnyDataEnabled() + - " roaming=" + phone.getServiceState().getRoaming() + - " dataOnRoamingEnable=" + getDataOnRoamingEnabled() + - " ps restricted=" + mIsPsRestricted + - " desiredPowerState=" + desiredPowerState + - " MasterDataEnabled=" + mMasterDataEnabled); + notifyOffApnsOfAvailability(reason, false); return false; } } /** - * If tearDown is true, this only tears down a CONNECTED session. Presently, - * there is no mechanism for abandoning an INITING/CONNECTING session, - * but would likely involve cancelling pending async requests or - * setting a flag or new state to ignore them when they came in - * @param tearDown true if the underlying GsmDataConnection should be - * disconnected. - * @param reason reason for the clean up. + * Cleanup all connections. + * + * TODO: Cleanup only a specified connection passed as a parameter. + * + * @param tearDown true if the underlying DataConnection should be disconnected. + * @param reason for the clean up. */ private void cleanUpConnection(boolean tearDown, String reason) { if (DBG) log("Clean up connection due to " + reason); @@ -497,7 +369,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // Clear the reconnect alarm, if set. if (mReconnectIntent != null) { AlarmManager am = - (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); + (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); am.cancel(mReconnectIntent); mReconnectIntent = null; } @@ -505,10 +377,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { setState(State.DISCONNECTING); boolean notificationDeferred = false; - for (DataConnection conn : pdpList) { + for (DataConnection conn : mDataConnections.values()) { if (tearDown) { if (DBG) log("cleanUpConnection: teardown, call conn.disconnect"); - conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason)); + conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, + conn.getDataConnectionId(), 0, reason)); notificationDeferred = true; } else { if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously"); @@ -566,87 +439,49 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return result; } - private GsmDataConnection findFreePdp() { - for (DataConnection conn : pdpList) { - GsmDataConnection pdp = (GsmDataConnection) conn; - if (pdp.isInactive()) { - return pdp; + private GsmDataConnection findFreeDataConnection() { + for (DataConnection dc : mDataConnections.values()) { + if (dc.isInactive()) { + log("found free GsmDataConnection"); + return (GsmDataConnection) dc; } } + log("NO free GsmDataConnection"); return null; } private boolean setupData(String reason) { ApnSetting apn; - GsmDataConnection pdp; + GsmDataConnection gdc; apn = getNextApn(); if (apn == null) return false; - pdp = findFreePdp(); - if (pdp == null) { + gdc = findFreeDataConnection(); + if (gdc == null) { if (DBG) log("setupData: No free GsmDataConnection found!"); return false; } mActiveApn = apn; - mActivePdp = pdp; + mPendingDataConnection = gdc; Message msg = obtainMessage(); msg.what = EVENT_DATA_SETUP_COMPLETE; msg.obj = reason; - pdp.connect(msg, apn); + gdc.connect(msg, apn); setState(State.INITING); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); return true; } - protected String getInterfaceName(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getInterface(); - } - return null; - } - - protected String getIpAddress(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getIpAddress(); - } - return null; - } - - public String getGateway(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getGatewayAddress(); - } - return null; - } - - protected String[] getDnsServers(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getDnsServers(); - } - return null; - } - - private boolean - pdpStatesHasCID (ArrayList<DataCallState> states, int cid) { + private boolean dataCallStatesHasCID (ArrayList<DataCallState> states, int cid) { for (int i = 0, s = states.size() ; i < s ; i++) { if (states.get(i).cid == cid) return true; } - return false; } - private boolean - pdpStatesHasActiveCID (ArrayList<DataCallState> states, int cid) { + private boolean dataCallStatesHasActiveCID (ArrayList<DataCallState> states, int cid) { for (int i = 0, s = states.size() ; i < s ; i++) { if ((states.get(i).cid == cid) && (states.get(i).active != 0)) { return true; @@ -662,7 +497,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void onApnChanged() { boolean isConnected; - isConnected = (state != State.IDLE && state != State.FAILED); + isConnected = (mState != State.IDLE && mState != State.FAILED); // The "current" may no longer be valid. MMS depends on this to send properly. mGsmPhone.updateCurrentCarrierInProvider(); @@ -670,7 +505,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // TODO: It'd be nice to only do this if the changed entrie(s) // match the current operator. createAllApnList(); - if (state != State.DISCONNECTING) { + if (mState != State.DISCONNECTING) { cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED); if (!isConnected) { // reset reconnect timer @@ -687,10 +522,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * via an unsolicited response (which could have happened at any * previous state */ - protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) { - ArrayList<DataCallState> pdpStates; + private void onDataStateChanged (AsyncResult ar, boolean explicitPoll) { + ArrayList<DataCallState> dataCallStates; - pdpStates = (ArrayList<DataCallState>)(ar.result); + dataCallStates = (ArrayList<DataCallState>)(ar.result); if (ar.exception != null) { // This is probably "radio not available" or something @@ -699,42 +534,42 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return; } - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { // The way things are supposed to work, the PDP list // should not contain the CID after it disconnects. // However, the way things really work, sometimes the PDP // context is still listed with active = false, which // makes it hard to distinguish an activating context from // an activated-and-then deactivated one. - if (!pdpStatesHasCID(pdpStates, cidActive)) { + if (!dataCallStatesHasCID(dataCallStates, mCidActive)) { // It looks like the PDP context has deactivated. // Tear everything down and try to reconnect. - Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting"); + log("PDP connection has dropped. Reconnecting"); // Add an event log when the network drops PDP - GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); + GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation()); EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, loc != null ? loc.getCid() : -1, TelephonyManager.getDefault().getNetworkType()); cleanUpConnection(true, null); return; - } else if (!pdpStatesHasActiveCID(pdpStates, cidActive)) { + } else if (!dataCallStatesHasActiveCID(dataCallStates, mCidActive)) { // Here, we only consider this authoritative if we asked for the // PDP list. If it was an unsolicited response, we poll again // to make sure everyone agrees on the initial state. if (!explicitPoll) { // We think it disconnected but aren't sure...poll from our side - phone.mCM.getPDPContextList( + mPhone.mCM.getPDPContextList( this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); } else { - Log.i(LOG_TAG, "PDP connection has dropped (active=false case). " + log("PDP connection has dropped (active=false case). " + " Reconnecting"); // Log the network drop on the event log. - GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); + GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation()); EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, loc != null ? loc.getCid() : -1, TelephonyManager.getDefault().getNetworkType()); @@ -747,7 +582,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void notifyDefaultData(String reason) { setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); startNetStatPoll(); // reset reconnect timer mRetryMgr.resetRetryCount(); @@ -757,42 +592,30 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void gotoIdleAndNotifyDataConnection(String reason) { if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason); setState(State.IDLE); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; } - /** - * This is a kludge to deal with the fact that - * the PDP state change notification doesn't always work - * with certain RIL impl's/basebands - * - */ - private void startPeriodicPdpPoll() { - removeMessages(EVENT_POLL_PDP); - - sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS); - } - private void resetPollStats() { - txPkts = -1; - rxPkts = -1; - sentSinceLastRecv = 0; - netStatPollPeriod = POLL_NETSTAT_MILLIS; + mTxPkts = -1; + mRxPkts = -1; + mSentSinceLastRecv = 0; + mNetStatPollPeriod = POLL_NETSTAT_MILLIS; mNoRecvPollCount = 0; } private void doRecovery() { - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { int maxPdpReset = Settings.Secure.getInt(mResolver, Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT, DEFAULT_MAX_PDP_RESET_FAIL); if (mPdpResetCount < maxPdpReset) { mPdpResetCount++; - EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, sentSinceLastRecv); + EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv); cleanUpConnection(true, Phone.REASON_PDP_RESET); } else { mPdpResetCount = 0; - EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, sentSinceLastRecv); + EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv); mGsmPhone.mSST.reRegisterNetwork(null); } // TODO: Add increasingly drastic recovery steps, eg, @@ -800,23 +623,26 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + @Override protected void startNetStatPoll() { - if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) { - Log.d(LOG_TAG, "[DataConnection] Start poll NetStat"); + if (mState == State.CONNECTED && mNetStatPollEnabled == false) { + log("[DataConnection] Start poll NetStat"); resetPollStats(); - netStatPollEnabled = true; + mNetStatPollEnabled = true; mPollNetStat.run(); } } + @Override protected void stopNetStatPoll() { - netStatPollEnabled = false; + mNetStatPollEnabled = false; removeCallbacks(mPollNetStat); - Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat"); + log("[DataConnection] Stop poll NetStat"); } + @Override protected void restartRadio() { - Log.d(LOG_TAG, "************TURN OFF RADIO**************"); + log("************TURN OFF RADIO**************"); cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF); mGsmPhone.mSST.powerOffRadioSafely(); /* Note: no need to call setRadioPower(true). Assuming the desired @@ -840,43 +666,43 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { Activity newActivity; - preTxPkts = txPkts; - preRxPkts = rxPkts; + preTxPkts = mTxPkts; + preRxPkts = mRxPkts; - txPkts = TrafficStats.getMobileTxPackets(); - rxPkts = TrafficStats.getMobileRxPackets(); + mTxPkts = TrafficStats.getMobileTxPackets(); + mRxPkts = TrafficStats.getMobileRxPackets(); - //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts)); + //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts)); - if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) { - sent = txPkts - preTxPkts; - received = rxPkts - preRxPkts; + if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) { + sent = mTxPkts - preTxPkts; + received = mRxPkts - preRxPkts; if ( sent > 0 && received > 0 ) { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; newActivity = Activity.DATAINANDOUT; mPdpResetCount = 0; } else if (sent > 0 && received == 0) { - if (phone.getState() == Phone.State.IDLE) { - sentSinceLastRecv += sent; + if (mPhone.getState() == Phone.State.IDLE) { + mSentSinceLastRecv += sent; } else { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; } newActivity = Activity.DATAOUT; } else if (sent == 0 && received > 0) { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; newActivity = Activity.DATAIN; mPdpResetCount = 0; } else if (sent == 0 && received == 0) { newActivity = Activity.NONE; } else { - sentSinceLastRecv = 0; + mSentSinceLastRecv = 0; newActivity = Activity.NONE; } - if (activity != newActivity && mIsScreenOn) { - activity = newActivity; - phone.notifyDataActivity(); + if (mActivity != newActivity && mIsScreenOn) { + mActivity = newActivity; + mPhone.notifyDataActivity(); } } @@ -884,11 +710,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, NUMBER_SENT_PACKETS_OF_HANG); - if (sentSinceLastRecv >= watchdogTrigger) { + if (mSentSinceLastRecv >= watchdogTrigger) { // we already have NUMBER_SENT_PACKETS sent without ack if (mNoRecvPollCount == 0) { EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED, - sentSinceLastRecv); + mSentSinceLastRecv); } int noRecvPollLimit = Settings.Secure.getInt(mResolver, @@ -898,77 +724,38 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // It's possible the PDP context went down and we weren't notified. // Start polling the context list in an attempt to recover. if (DBG) log("no DATAIN in a while; polling PDP"); - phone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); + mPhone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); mNoRecvPollCount++; // Slow down the poll interval to let things happen - netStatPollPeriod = Settings.Secure.getInt(mResolver, + mNetStatPollPeriod = Settings.Secure.getInt(mResolver, Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, POLL_NETSTAT_SLOW_MILLIS); } else { - if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) + - " pkts since last received"); - // We've exceeded the threshold. Run ping test as a final check; - // it will proceed with recovery if ping fails. + if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) + + " pkts since last received start recovery process"); stopNetStatPoll(); - Thread pingTest = new Thread() { - public void run() { - runPingTest(); - } - }; - mPingTestActive = true; - pingTest.start(); + sendMessage(obtainMessage(EVENT_START_RECOVERY)); } } else { mNoRecvPollCount = 0; if (mIsScreenOn) { - netStatPollPeriod = Settings.Secure.getInt(mResolver, + mNetStatPollPeriod = Settings.Secure.getInt(mResolver, Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS); } else { - netStatPollPeriod = Settings.Secure.getInt(mResolver, + mNetStatPollPeriod = Settings.Secure.getInt(mResolver, Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS, POLL_NETSTAT_SCREEN_OFF_MILLIS); } } - if (netStatPollEnabled) { - mDataConnectionTracker.postDelayed(this, netStatPollPeriod); + if (mNetStatPollEnabled) { + mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod); } } }; - private void runPingTest () { - int status = -1; - try { - String address = Settings.Secure.getString(mResolver, - Settings.Secure.PDP_WATCHDOG_PING_ADDRESS); - int deadline = Settings.Secure.getInt(mResolver, - Settings.Secure.PDP_WATCHDOG_PING_DEADLINE, DEFAULT_PING_DEADLINE); - if (DBG) log("pinging " + address + " for " + deadline + "s"); - if (address != null && !NULL_IP.equals(address)) { - Process p = Runtime.getRuntime() - .exec("ping -c 1 -i 1 -w "+ deadline + " " + address); - status = p.waitFor(); - } - } catch (IOException e) { - Log.w(LOG_TAG, "ping failed: IOException"); - } catch (Exception e) { - Log.w(LOG_TAG, "exception trying to ping"); - } - - if (status == 0) { - // ping succeeded. False alarm. Reset netStatPoll. - // ("-1" for this event indicates a false alarm) - EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1); - mPdpResetCount = 0; - sendMessage(obtainMessage(EVENT_START_NETSTAT_POLL)); - } else { - // ping failed. Proceed with recovery. - sendMessage(obtainMessage(EVENT_START_RECOVERY)); - } - } - /** * Returns true if the last fail cause is something that * seems like it deserves an error notification. @@ -995,20 +782,21 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) { - if (state == State.FAILED) { + if (mState == State.FAILED) { + /** TODO: Retrieve retry manager from connection itself */ if (!mRetryMgr.isRetryNeeded()) { if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { // if no more retries on a secondary APN attempt, tell the world and revert. - phone.notifyDataConnection(Phone.REASON_APN_FAILED); + notifyDataConnection(Phone.REASON_APN_FAILED); onEnableApn(apnTypeToId(mRequestedApnType), DISABLED); return; } if (mReregisterOnReconnectFailure) { - // We've re-registerd once now just retry forever. + // We've re-registered once now just retry forever. mRetryMgr.retryForeverUsingLastTimeout(); } else { // Try to re-register to the network. - Log.d(LOG_TAG, "PDP activate failed, Reregistering to the network"); + log("PDP activate failed, Reregistering to the network"); mReregisterOnReconnectFailure = true; mGsmPhone.mSST.reRegisterNetwork(null); mRetryMgr.resetRetryCount(); @@ -1017,15 +805,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } int nextReconnectDelay = mRetryMgr.getRetryTimer(); - Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for " + log("PDP activate failed. Scheduling next attempt for " + (nextReconnectDelay / 1000) + "s"); AlarmManager am = - (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); + (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(INTENT_RECONNECT_ALARM); intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason); mReconnectIntent = PendingIntent.getBroadcast( - phone.getContext(), 0, intent, 0); + mPhone.getContext(), 0, intent, 0); am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + nextReconnectDelay, mReconnectIntent); @@ -1033,7 +821,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { mRetryMgr.increaseRetryCount(); if (!shouldPostNotification(lastFailCauseCode)) { - Log.d(LOG_TAG,"NOT Posting GPRS Unavailable notification " + log("NOT Posting GPRS Unavailable notification " + "-- likely transient error"); } else { notifyNoData(lastFailCauseCode); @@ -1045,9 +833,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { setState(State.FAILED); } - protected void onRecordsLoaded() { + private void onRecordsLoaded() { createAllApnList(); - if (state == State.FAILED) { + if (mState == State.FAILED) { cleanUpConnection(false, null); } sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED)); @@ -1055,19 +843,29 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { @Override protected void onEnableNewApn() { + log("onEnableNewApn E"); // change our retry manager to use the appropriate numbers for the new APN if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { - mRetryMgr = mDefaultRetryManager; + log("onEnableNewApn default type"); + mRetryMgr = mPendingDataConnection.getRetryMgr(); + mRetryMgr.resetRetryCount(); + } else if (mApnToDataConnectionId.get(mRequestedApnType) == null) { + log("onEnableNewApn mRequestedApnType=" + mRequestedApnType + + " missing, make a new connection"); + int id = createDataConnection(mRequestedApnType); + mRetryMgr = mDataConnections.get(id).getRetryMgr(); + mRetryMgr.resetRetryCount(); } else { - mRetryMgr = mSecondaryRetryManager; + log("oneEnableNewApn connection already exists, nothing to setup"); } - mRetryMgr.resetRetryCount(); // TODO: To support simultaneous PDP contexts, this should really only call // cleanUpConnection if it needs to free up a GsmDataConnection. cleanUpConnection(true, Phone.REASON_APN_SWITCHED); + log("onEnableNewApn X"); } + @Override protected boolean onTrySetupData(String reason) { return trySetupData(reason); } @@ -1087,31 +885,33 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + @Override protected void onRadioAvailable() { - if (phone.getSimulatedRadioControl() != null) { + if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(null); + notifyDataConnection(null); - Log.i(LOG_TAG, "We're on the simulator; assuming data is connected"); + log("We're on the simulator; assuming data is connected"); } - if (state != State.IDLE) { + if (mState != State.IDLE) { cleanUpConnection(true, null); } } + @Override protected void onRadioOffOrNotAvailable() { // Make sure our reconnect delay starts at the initial value // next time the radio comes on mRetryMgr.resetRetryCount(); mReregisterOnReconnectFailure = false; - if (phone.getSimulatedRadioControl() != null) { + if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved - Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless"); + log("We're on the simulator; assuming radio off is meaningless"); } else { if (DBG) log("Radio is off and clean up all connection"); // TODO: Should we reset mRequestedApnType to "default"? @@ -1119,20 +919,41 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + @Override protected void onDataSetupComplete(AsyncResult ar) { + /** TODO: Which connection is completing should be a parameter */ String reason = null; if (ar.userObj instanceof String) { reason = (String) ar.userObj; } if (ar.exception == null) { + if(DBG) { + log(String.format("onDataSetupComplete: success apn=%s", mWaitingApns.get(0).apn)); + } + // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected + mLinkProperties = getLinkProperties(mPendingDataConnection); + mLinkCapabilities = getLinkCapabilities(mPendingDataConnection); + + ApnSetting apn = mPendingDataConnection.getApn(); + if (apn.proxy != null && apn.proxy.length() != 0) { + try { + ProxyProperties proxy = new ProxyProperties(apn.proxy, + Integer.parseInt(apn.port), null); + mLinkProperties.setHttpProxy(proxy); + } catch (NumberFormatException e) { + loge("NumberFormatException making ProxyProperties (" + apn.port + + "): " + e); + } + } + // everything is setup if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { SystemProperties.set("gsm.defaultpdpcontext.active", "true"); - if (canSetPreferApn && preferredApn == null) { - Log.d(LOG_TAG, "PREFERRED APN is null"); - preferredApn = mActiveApn; - setPreferredApn(preferredApn.id); + if (canSetPreferApn && mPreferredApn == null) { + log("PREFERRED APN is null"); + mPreferredApn = mActiveApn; + setPreferredApn(mPreferredApn.id); } } else { SystemProperties.set("gsm.defaultpdpcontext.active", "false"); @@ -1146,28 +967,36 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } else { GsmDataConnection.FailCause cause; cause = (GsmDataConnection.FailCause) (ar.result); - if(DBG) log("PDP setup failed " + cause); - // Log this failure to the Event Logs. + if (DBG) { + String apnString; + try { + apnString = mWaitingApns.get(0).apn; + } catch (Exception e) { + apnString = "<unknown>"; + } + log(String.format("onDataSetupComplete: error apn=%s cause=%s", apnString, cause)); + } if (cause.isEventLoggable()) { - GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); + // Log this failure to the Event Logs. + GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation()); EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL, cause.ordinal(), loc != null ? loc.getCid() : -1, TelephonyManager.getDefault().getNetworkType()); } // Count permanent failures and remove the APN we just tried - waitingApnsPermanentFailureCountDown -= cause.isPermanentFail() ? 1 : 0; - waitingApns.remove(0); - if (DBG) log(String.format("onDataSetupComplete: waitingApns.size=%d" + - " waitingApnsPermanenatFailureCountDown=%d", - waitingApns.size(), waitingApnsPermanentFailureCountDown)); + mWaitingApnsPermanentFailureCountDown -= cause.isPermanentFail() ? 1 : 0; + mWaitingApns.remove(0); + if (DBG) log(String.format("onDataSetupComplete: mWaitingApns.size=%d" + + " mWaitingApnsPermanenatFailureCountDown=%d", + mWaitingApns.size(), mWaitingApnsPermanentFailureCountDown)); // See if there are more APN's to try - if (waitingApns.isEmpty()) { - if (waitingApnsPermanentFailureCountDown == 0) { + if (mWaitingApns.isEmpty()) { + if (mWaitingApnsPermanentFailureCountDown == 0) { if (DBG) log("onDataSetupComplete: Permanent failures stop retrying"); notifyNoData(cause); - phone.notifyDataConnection(Phone.REASON_APN_FAILED); + notifyDataConnection(Phone.REASON_APN_FAILED); } else { if (DBG) log("onDataSetupComplete: Not all permanent failures, retry"); startDelayedRetry(cause, reason); @@ -1185,14 +1014,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { /** * Called when EVENT_DISCONNECT_DONE is received. */ - protected void onDisconnectDone(AsyncResult ar) { + @Override + protected void onDisconnectDone(int connId, AsyncResult ar) { + if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId); String reason = null; - if(DBG) log("EVENT_DISCONNECT_DONE"); if (ar.userObj instanceof String) { reason = (String) ar.userObj; } setState(State.IDLE); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; if (retryAfterDisconnected(reason)) { trySetupData(reason); @@ -1213,25 +1043,27 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } protected void onPollPdp() { - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { // only poll when connected - phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); + mPhone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS); } } + @Override protected void onVoiceCallStarted() { - if (state == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) { + if (mState == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) { stopNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); + notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); } } + @Override protected void onVoiceCallEnded() { - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); + notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); } else { // clean slate after call end. resetPollStats(); @@ -1245,74 +1077,92 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + @Override protected void onCleanUpConnection(boolean tearDown, String reason) { cleanUpConnection(tearDown, reason); } /** - * Based on the sim operator numeric, create a list for all possible pdps - * with all apns associated with that pdp - * - * + * Based on the sim operator numeric, create a list for all possible + * Data Connections and setup the preferredApn. */ private void createAllApnList() { - allApns = new ArrayList<ApnSetting>(); + mAllApns = new ArrayList<ApnSetting>(); String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric(); if (operator != null) { String selection = "numeric = '" + operator + "'"; - Cursor cursor = phone.getContext().getContentResolver().query( + Cursor cursor = mPhone.getContext().getContentResolver().query( Telephony.Carriers.CONTENT_URI, null, selection, null, null); if (cursor != null) { if (cursor.getCount() > 0) { - allApns = createApnList(cursor); - // TODO: Figure out where this fits in. This basically just - // writes the pap-secrets file. No longer tied to GsmDataConnection - // object. Not used on current platform (no ppp). - //GsmDataConnection pdp = pdpList.get(pdp_name); - //if (pdp != null && pdp.dataLink != null) { - // pdp.dataLink.setPasswordInfo(cursor); - //} + mAllApns = createApnList(cursor); } cursor.close(); } } - if (allApns.isEmpty()) { + if (mAllApns.isEmpty()) { if (DBG) log("No APN found for carrier: " + operator); - preferredApn = null; + mPreferredApn = null; notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); } else { - preferredApn = getPreferredApn(); - Log.d(LOG_TAG, "Get PreferredAPN"); - if (preferredApn != null && !preferredApn.numeric.equals(operator)) { - preferredApn = null; + mPreferredApn = getPreferredApn(); + log("Get PreferredAPN"); + if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) { + mPreferredApn = null; setPreferredApn(-1); } } } - private void createAllPdpList() { - pdpList = new ArrayList<DataConnection>(); - DataConnection pdp; + /** Return the id for a new data connection */ + private int createDataConnection(String apnType) { + log("createDataConnection(" + apnType + ") E"); + RetryManager rm = new RetryManager(); + + if (apnType.equals(Phone.APN_TYPE_DEFAULT)) { + if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) { + if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) { + // Should never happen, log an error and default to a simple linear sequence. + log("Could not configure using DEFAULT_DATA_RETRY_CONFIG=" + + DEFAULT_DATA_RETRY_CONFIG); + rm.configure(20, 2000, 1000); + } + } + } else { + if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) { + if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) { + // Should never happen, log an error and default to a simple sequence. + log("Could note configure using SECONDARY_DATA_RETRY_CONFIG=" + + SECONDARY_DATA_RETRY_CONFIG); + rm.configure("max_retries=3, 333, 333, 333"); + } + } + } - for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) { - pdp = GsmDataConnection.makeDataConnection(mGsmPhone); - pdpList.add(pdp); - } + int id = mUniqueIdGenerator.getAndIncrement(); + DataConnection conn = GsmDataConnection.makeDataConnection(mGsmPhone, id, rm); + mDataConnections.put(id, conn); + mApnToDataConnectionId.put(apnType, id); + + log("createDataConnection(" + apnType + ") X id=" + id); + return id; } - private void destroyAllPdpList() { - if(pdpList != null) { - GsmDataConnection pdp; - pdpList.removeAll(pdpList); + private void destroyDataConnections() { + if(mDataConnections != null) { + log("destroyDataConnectionList clear mDataConnectionList"); + mDataConnections.clear(); + } else { + log("destroyDataConnectionList mDataConnecitonList is empty, ignore"); } } private ApnSetting fetchDunApn() { - Context c = phone.getContext(); + Context c = mPhone.getContext(); String apnData = Settings.Secure.getString(c.getContentResolver(), Settings.Secure.TETHER_DUN_APN); ApnSetting dunSetting = ApnSetting.fromString(apnData); @@ -1323,14 +1173,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } /** + * Build a list of APNs to be used to create PDP's. * + * @param requestedApnType * @return waitingApns list to be used to create PDP * error when waitingApns.isEmpty() */ - private ArrayList<ApnSetting> buildWaitingApns() { + private ArrayList<ApnSetting> buildWaitingApns(String requestedApnType) { ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>(); - if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) { + if (requestedApnType.equals(Phone.APN_TYPE_DUN)) { ApnSetting dun = fetchDunApn(); if (dun != null) apnList.add(dun); return apnList; @@ -1338,24 +1190,24 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric(); - if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { - if (canSetPreferApn && preferredApn != null) { - Log.i(LOG_TAG, "Preferred APN:" + operator + ":" - + preferredApn.numeric + ":" + preferredApn); - if (preferredApn.numeric.equals(operator)) { - Log.i(LOG_TAG, "Waiting APN set to preferred APN"); - apnList.add(preferredApn); + if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { + if (canSetPreferApn && mPreferredApn != null) { + log("Preferred APN:" + operator + ":" + + mPreferredApn.numeric + ":" + mPreferredApn); + if (mPreferredApn.numeric.equals(operator)) { + log("Waiting APN set to preferred APN"); + apnList.add(mPreferredApn); return apnList; } else { setPreferredApn(-1); - preferredApn = null; + mPreferredApn = null; } } } - if (allApns != null) { - for (ApnSetting apn : allApns) { - if (apn.canHandleType(mRequestedApnType)) { + if (mAllApns != null) { + for (ApnSetting apn : mAllApns) { + if (apn.canHandleType(requestedApnType)) { apnList.add(apn); } } @@ -1368,7 +1220,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * @return the first apn found in waitingApns, null if none */ private ApnSetting getNextApn() { - ArrayList<ApnSetting> list = waitingApns; + ArrayList<ApnSetting> list = mWaitingApns; ApnSetting apn = null; if (list != null) { @@ -1399,7 +1251,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return; } - ContentResolver resolver = phone.getContext().getContentResolver(); + ContentResolver resolver = mPhone.getContext().getContentResolver(); resolver.delete(PREFERAPN_URI, null, null); if (pos >= 0) { @@ -1410,11 +1262,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } private ApnSetting getPreferredApn() { - if (allApns.isEmpty()) { + if (mAllApns.isEmpty()) { return null; } - Cursor cursor = phone.getContext().getContentResolver().query( + Cursor cursor = mPhone.getContext().getContentResolver().query( PREFERAPN_URI, new String[] { "_id", "name", "apn" }, null, null, Telephony.Carriers.DEFAULT_SORT_ORDER); @@ -1428,7 +1280,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { int pos; cursor.moveToFirst(); pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)); - for(ApnSetting p:allApns) { + for(ApnSetting p:mAllApns) { if (p.id == pos && p.canHandleType(mRequestedApnType)) { cursor.close(); return p; @@ -1443,11 +1295,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return null; } + @Override public void handleMessage (Message msg) { - if (DBG) Log.d(LOG_TAG,"GSMDataConnTrack handleMessage "+msg); + if (DBG) log("GSMDataConnTrack handleMessage "+msg); if (!mGsmPhone.mIsTheCurrentActivePhone) { - Log.d(LOG_TAG, "Ignore GSM msgs since GSM phone is inactive"); + log("Ignore GSM msgs since GSM phone is inactive"); return; } @@ -1465,11 +1318,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { break; case EVENT_DATA_STATE_CHANGED: - onPdpStateChanged((AsyncResult) msg.obj, false); + onDataStateChanged((AsyncResult) msg.obj, false); break; case EVENT_GET_PDP_LIST_COMPLETE: - onPdpStateChanged((AsyncResult) msg.obj, true); + onDataStateChanged((AsyncResult) msg.obj, true); break; case EVENT_POLL_PDP: @@ -1477,12 +1330,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { break; case EVENT_START_NETSTAT_POLL: - mPingTestActive = false; startNetStatPoll(); break; case EVENT_START_RECOVERY: - mPingTestActive = false; doRecovery(); break; @@ -1497,7 +1348,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * PDP context and notify us with PDP_CONTEXT_CHANGED. * But we should stop the network polling and prevent reset PDP. */ - Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); + log("[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); stopNetStatPoll(); mIsPsRestricted = true; break; @@ -1507,12 +1358,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * When PS restrict is removed, we need setup PDP connection if * PDP connection is down. */ - Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted); + log("[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted); mIsPsRestricted = false; - if (state == State.CONNECTED) { + if (mState == State.CONNECTED) { startNetStatPoll(); } else { - if (state == State.FAILED) { + if (mState == State.FAILED) { cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED); mRetryMgr.resetRetryCount(); mReregisterOnReconnectFailure = false; @@ -1528,7 +1379,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + @Override protected void log(String s) { Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s); } + + @Override + protected void loge(String s) { + Log.e(LOG_TAG, "[GsmDataConnectionTracker] " + s); + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java index 40ee0b0..70f8f86 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java @@ -64,6 +64,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { * @param ar AsyncResult passed into the message handler. ar.result should * be a String representing the status report PDU, as ASCII hex. */ + @Override protected void handleStatusReport(AsyncResult ar) { String pduString = (String) ar.result; SmsMessage sms = SmsMessage.newFromCDS(pduString); @@ -92,6 +93,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { /** {@inheritDoc} */ + @Override protected int dispatchMessage(SmsMessageBase smsb) { // If sms is null, means there was a parsing error. @@ -159,6 +161,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendData(String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -167,6 +170,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -175,6 +179,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendMultipartText(String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { @@ -314,8 +319,9 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendSms(SmsTracker tracker) { - HashMap map = tracker.mData; + HashMap<String, Object> map = tracker.mData; byte smsc[] = (byte[]) map.get("smsc"); byte pdu[] = (byte[]) map.get("pdu"); @@ -330,12 +336,13 @@ final class GsmSMSDispatcher extends SMSDispatcher { * * @param tracker holds the multipart Sms tracker ready to be sent */ + @Override protected void sendMultipartSms (SmsTracker tracker) { ArrayList<String> parts; ArrayList<PendingIntent> sentIntents; ArrayList<PendingIntent> deliveryIntents; - HashMap map = tracker.mData; + HashMap<String, Object> map = tracker.mData; String destinationAddress = (String) map.get("destination"); String scAddress = (String) map.get("scaddress"); @@ -350,6 +357,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ // FIXME unit test leaves cm == null. this should change if (mCm != null) { @@ -358,6 +366,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void activateCellBroadcastSms(int activate, Message response) { // Unless CBS is implemented for GSM, this point should be unreachable. Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM."); @@ -365,6 +374,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void getCellBroadcastSmsConfig(Message response){ // Unless CBS is implemented for GSM, this point should be unreachable. Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM."); @@ -372,6 +382,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void setCellBroadcastConfig(int[] configValuesArray, Message response) { // Unless CBS is implemented for GSM, this point should be unreachable. Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM."); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 6ddb312..b04d4b9 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -16,6 +16,18 @@ package com.android.internal.telephony.gsm; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.CommandsInterface; +import com.android.internal.telephony.DataConnectionTracker; +import com.android.internal.telephony.EventLogTags; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.MccTable; +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.telephony.TelephonyProperties; + import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; @@ -47,17 +59,6 @@ import android.util.EventLog; import android.util.Log; import android.util.TimeUtils; -import com.android.internal.telephony.CommandException; -import com.android.internal.telephony.CommandsInterface; -import com.android.internal.telephony.DataConnectionTracker; -import com.android.internal.telephony.EventLogTags; -import com.android.internal.telephony.IccCard; -import com.android.internal.telephony.MccTable; -import com.android.internal.telephony.RILConstants; -import com.android.internal.telephony.ServiceStateTracker; -import com.android.internal.telephony.TelephonyIntents; -import com.android.internal.telephony.TelephonyProperties; - import java.util.Arrays; import java.util.Calendar; import java.util.Date; @@ -226,6 +227,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_LOCALE_CHANGED); phone.getContext().registerReceiver(mIntentReceiver, filter); + + // Gsm doesn't support OTASP so its not needed + phone.notifyOtaspChanged(OTASP_NOT_NEEDED); } public void dispose() { @@ -246,6 +250,11 @@ final class GsmServiceStateTracker extends ServiceStateTracker { if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized"); } + @Override + protected Phone getPhone() { + return phone; + } + /** * Registration point for transition into GPRS attached. * @param h handler to notify @@ -590,16 +599,21 @@ final class GsmServiceStateTracker extends ServiceStateTracker { if (mEmergencyOnly && cm.getRadioState().isOn()) { plmn = Resources.getSystem(). getText(com.android.internal.R.string.emergency_calls_only).toString(); + Log.d(LOG_TAG, "updateSpnDisplay: emergency only and radio is on plmn='" + plmn + "'"); } if (rule != curSpnRule || !TextUtils.equals(spn, curSpn) || !TextUtils.equals(plmn, curPlmn)) { - boolean showSpn = !mEmergencyOnly + boolean showSpn = !mEmergencyOnly && !TextUtils.isEmpty(spn) && (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN; - boolean showPlmn = + boolean showPlmn = !TextUtils.isEmpty(plmn) && (rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN; + Log.d(LOG_TAG, + String.format("updateSpnDisplay: changed sending intent" + " rule=" + rule + + " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'", + showPlmn, plmn, showSpn, spn)); Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn); @@ -1001,7 +1015,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { mNeedFixZone = false; if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1024,7 +1038,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } if (hasNetworkTypeChanged) { - phone.notifyDataConnection(null); + phone.notifyDataConnection(); } if (hasRoamingOn) { @@ -1481,7 +1495,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1551,6 +1565,15 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } } + private boolean getAutoTimeZone() { + try { + return Settings.System.getInt(phone.getContext().getContentResolver(), + Settings.System.AUTO_TIME_ZONE) > 0; + } catch (SettingNotFoundException snfe) { + return true; + } + } + private void saveNitzTimeZone(String zoneId) { mSavedTimeZone = zoneId; } @@ -1666,7 +1689,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } } - private void log(String s) { + @Override + protected void log(String s) { Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s); } } diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java index e55596b..5abba6e 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java +++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java @@ -106,6 +106,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager { public void dispose() { } + @Override protected void finalize() { try { super.finalize(); @@ -331,6 +332,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager { return mSuccess; } + @Override protected void log(String msg) { Log.d(LOG_TAG, "[SimSmsInterfaceManager] " + msg); } diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 9a3c476..e24613f 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -26,7 +26,6 @@ import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; -import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; @@ -34,6 +33,7 @@ import java.io.UnsupportedEncodingException; import static android.telephony.SmsMessage.ENCODING_7BIT; import static android.telephony.SmsMessage.ENCODING_8BIT; import static android.telephony.SmsMessage.ENCODING_16BIT; +import static android.telephony.SmsMessage.ENCODING_KSC5601; import static android.telephony.SmsMessage.ENCODING_UNKNOWN; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER; @@ -45,7 +45,7 @@ import static android.telephony.SmsMessage.MessageClass; * A Short Message Service message. * */ -public class SmsMessage extends SmsMessageBase{ +public class SmsMessage extends SmsMessageBase { static final String LOG_TAG = "GSM"; private MessageClass messageClass; @@ -311,7 +311,7 @@ public class SmsMessage extends SmsMessageBase{ // the receiver's SIM card. You can then send messages to yourself // (on a phone with this change) and they'll end up on the SIM card. bo.write(0x00); - } else { //assume UCS-2 + } else { // assume UCS-2 if ((0xff & userData[0]) > MAX_USER_DATA_BYTES) { // Message too long return null; @@ -377,7 +377,7 @@ public class SmsMessage extends SmsMessageBase{ * @param destinationAddress the address of the destination for the message * @param destinationPort the port to deliver the message to at the * destination - * @param data the dat for the message + * @param data the data for the message * @return a <code>SubmitPdu</code> containing the encoded SC * address, if applicable, and the encoded message. * Returns null on encode error. @@ -482,7 +482,7 @@ public class SmsMessage extends SmsMessageBase{ return bo; } - static class PduParser { + private static class PduParser { byte pdu[]; int cur; SmsHeader userDataHeader; @@ -490,10 +490,6 @@ public class SmsMessage extends SmsMessageBase{ int mUserDataSeptetPadding; int mUserDataSize; - PduParser(String s) { - this(IccUtils.hexStringToBytes(s)); - } - PduParser(byte[] pdu) { this.pdu = pdu; cur = 0; @@ -545,7 +541,7 @@ public class SmsMessage extends SmsMessageBase{ GsmSmsAddress ret; // "The Address-Length field is an integer representation of - // the number field, i.e. excludes any semi octet containing only + // the number field, i.e. excludes any semi-octet containing only // fill bits." // The TOA field is not included as part of this int addressLength = pdu[cur] & 0xff; @@ -573,7 +569,7 @@ public class SmsMessage extends SmsMessageBase{ int second = IccUtils.gsmBcdByteToInt(pdu[cur++]); // For the timezone, the most significant bit of the - // least signficant nibble is the sign byte + // least significant nibble is the sign byte // (meaning the max range of this field is 79 quarter-hours, // which is more than enough) @@ -632,7 +628,7 @@ public class SmsMessage extends SmsMessageBase{ /* * Here we just create the user data length to be the remainder of * the pdu minus the user data header, since userDataLength means - * the number of uncompressed sepets. + * the number of uncompressed septets. */ bufferLen = pdu.length - offset; } else { @@ -671,10 +667,10 @@ public class SmsMessage extends SmsMessageBase{ } /** - * Returns the number of padding bits at the begining of the user data + * Returns the number of padding bits at the beginning of the user data * array before the start of the septets. * - * @return the number of padding bits at the begining of the user data + * @return the number of padding bits at the beginning of the user data * array before the start of the septets */ int getUserDataSeptetPadding() { @@ -694,7 +690,7 @@ public class SmsMessage extends SmsMessageBase{ XXX Not sure what this one is supposed to be doing, and no one is using it. String getUserDataGSM8bit() { - // System.out.println("remainder of pud:" + + // System.out.println("remainder of pdu:" + // HexDump.dumpHexString(pdu, cur, pdu.length - cur)); int count = pdu[cur++] & 0xff; int size = pdu[cur++]; @@ -781,6 +777,27 @@ public class SmsMessage extends SmsMessageBase{ return ret; } + /** + * Interprets the user data payload as KSC-5601 characters, and + * decodes them into a String. + * + * @param byteCount the number of bytes in the user data payload + * @return a String with the decoded characters + */ + String getUserDataKSC5601(int byteCount) { + String ret; + + try { + ret = new String(pdu, cur, byteCount, "KSC5601"); + } catch (UnsupportedEncodingException ex) { + ret = ""; + Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex); + } + + cur += byteCount; + return ret; + } + boolean moreDataPresent() { return (pdu.length > cur); } @@ -827,11 +844,13 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public int getProtocolIdentifier() { return protocolIdentifier; } /** {@inheritDoc} */ + @Override public boolean isReplace() { return (protocolIdentifier & 0xc0) == 0x40 && (protocolIdentifier & 0x3f) > 0 @@ -839,12 +858,14 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public boolean isCphsMwiMessage() { return ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear() || ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet(); } /** {@inheritDoc} */ + @Override public boolean isMWIClearMessage() { if (isMwi && (mwiSense == false)) { return true; @@ -855,6 +876,7 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public boolean isMWISetMessage() { if (isMwi && (mwiSense == true)) { return true; @@ -865,6 +887,7 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public boolean isMwiDontStore() { if (isMwi && mwiDontStore) { return true; @@ -884,31 +907,34 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public int getStatus() { return status; } /** {@inheritDoc} */ + @Override public boolean isStatusReportMessage() { return isStatusReportMessage; } /** {@inheritDoc} */ + @Override public boolean isReplyPathPresent() { return replyPathPresent; } /** - * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] + * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format: * ME/TA converts each octet of TP data unit into two IRA character long - * hexad number (e.g. octet with integer value 42 is presented to TE as two + * hex number (e.g. octet with integer value 42 is presented to TE as two * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast, * something else... */ private void parsePdu(byte[] pdu) { mPdu = pdu; - // Log.d(LOG_TAG, "raw sms mesage:"); + // Log.d(LOG_TAG, "raw sms message:"); // Log.d(LOG_TAG, s); PduParser p = new PduParser(pdu); @@ -1107,6 +1133,16 @@ public class SmsMessage extends SmsMessageBase{ Log.w(LOG_TAG, "MWI for fax, email, or other " + (dataCodingScheme & 0xff)); } + } else if ((dataCodingScheme & 0xC0) == 0x80) { + // 3GPP TS 23.038 V7.0.0 (2006-03) section 4 + // 0x80..0xBF == Reserved coding groups + if (dataCodingScheme == 0x84) { + // This value used for KSC5601 by carriers in Korea. + encodingType = ENCODING_KSC5601; + } else { + Log.w(LOG_TAG, "5 - Unsupported SMS data coding scheme " + + (dataCodingScheme & 0xff)); + } } else { Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme " + (dataCodingScheme & 0xff)); @@ -1131,6 +1167,10 @@ public class SmsMessage extends SmsMessageBase{ case ENCODING_16BIT: messageBody = p.getUserDataUCS2(count); break; + + case ENCODING_KSC5601: + messageBody = p.getUserDataKSC5601(count); + break; } if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'"); @@ -1162,6 +1202,7 @@ public class SmsMessage extends SmsMessageBase{ /** * {@inheritDoc} */ + @Override public MessageClass getMessageClass() { return messageClass; } diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java index b642541..41f3b23 100755 --- a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java +++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java @@ -27,8 +27,6 @@ import com.android.internal.telephony.IccConstants; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.PhoneBase; -import org.apache.harmony.luni.lang.reflect.ListOfTypes; - import java.util.ArrayList; import java.util.HashMap; import java.util.Map; diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java index ed578c8..2e729fe 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java +++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java @@ -184,19 +184,12 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface { public void writeSmsToRuim(int status, String pdu, Message response) { } - public void setupDefaultPDP(String apn, String user, String password, - Message result) { - } - - public void deactivateDefaultPDP(int cid, Message result) { - } - public void setupDataCall(String radioTechnology, String profile, String apn, String user, String password, String authType, Message result) { } - public void deactivateDataCall(int cid, Message result) { + public void deactivateDataCall(int cid, int reason, Message result) { } public void setRadioPower(boolean on, Message result) { diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java index 154a334..c83f696 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java @@ -19,6 +19,7 @@ package com.android.internal.telephony.sip; import com.android.internal.telephony.Call; import com.android.internal.telephony.Connection; import com.android.internal.telephony.Phone; +import com.android.internal.telephony.UUSInfo; import android.net.sip.SipAudioCall; import android.os.SystemClock; @@ -171,4 +172,10 @@ abstract class SipConnectionBase extends Connection { // TODO: add PRESENTATION_URL return Connection.PRESENTATION_ALLOWED; } + + @Override + public UUSInfo getUUSInfo() { + // FIXME: what's this for SIP? + return null; + } } diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java index a92ac1c..461f01d 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java @@ -36,7 +36,6 @@ import com.android.internal.telephony.CallStateException; import com.android.internal.telephony.Connection; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneNotifier; -import com.android.internal.telephony.UUSInfo; import java.text.ParseException; import java.util.List; @@ -70,6 +69,14 @@ public class SipPhone extends SipPhoneBase { mSipManager = SipManager.newInstance(context); } + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SipPhone)) return false; + SipPhone that = (SipPhone) o; + return mProfile.getUriString().equals(that.mProfile.getUriString()); + } + public String getPhoneName() { return "SIP:" + getUriString(mProfile); } @@ -145,10 +152,6 @@ public class SipPhone extends SipPhoneBase { } } - public Connection dial(String dialString, UUSInfo uusinfo) throws CallStateException { - return dial(dialString); - } - public Connection dial(String dialString) throws CallStateException { synchronized (SipPhone.class) { return dialInternal(dialString); @@ -827,10 +830,6 @@ public class SipPhone extends SipPhoneBase { } } - @Override - public UUSInfo getUUSInfo() { - return null; - } } private static Call.State getCallStateFrom(SipAudioCall sipAudioCall) { diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java index 5499966..db9e35a 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java @@ -17,6 +17,7 @@ package com.android.internal.telephony.sip; import android.content.Context; +import android.net.LinkProperties; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; @@ -42,6 +43,7 @@ import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneSubInfo; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import java.util.ArrayList; import java.util.List; @@ -62,6 +64,12 @@ abstract class SipPhoneBase extends PhoneBase { public abstract Call getRingingCall(); + public Connection dial(String dialString, UUSInfo uusInfo) + throws CallStateException { + // ignore UUSInfo + return dial(dialString); + } + void migrateFrom(SipPhoneBase from) { migrate(mRingbackRegistrants, from.mRingbackRegistrants); migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants); @@ -93,12 +101,12 @@ abstract class SipPhoneBase extends PhoneBase { } protected void startRingbackTone() { - AsyncResult result = new AsyncResult(null, new Boolean(true), null); + AsyncResult result = new AsyncResult(null, Boolean.TRUE, null); mRingbackRegistrants.notifyRegistrants(result); } protected void stopRingbackTone() { - AsyncResult result = new AsyncResult(null, new Boolean(false), null); + AsyncResult result = new AsyncResult(null, Boolean.FALSE, null); mRingbackRegistrants.notifyRegistrants(result); } @@ -419,6 +427,18 @@ abstract class SipPhoneBase extends PhoneBase { Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP."); } + //@Override + public boolean needsOtaServiceProvisioning() { + // FIXME: what's this for SIP? + return false; + } + + //@Override + public LinkProperties getLinkProperties(String apnType) { + // FIXME: what's this for SIP? + return null; + } + void updatePhoneState() { State oldState = state; diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 9c72e5a..c2f88e5 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -16,7 +16,6 @@ package com.android.internal.telephony.test; - import android.os.AsyncResult; import android.os.HandlerThread; import android.os.Looper; @@ -27,7 +26,6 @@ import com.android.internal.telephony.BaseCommands; import com.android.internal.telephony.CommandException; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataCallState; -import com.android.internal.telephony.IccCard; import com.android.internal.telephony.Phone; import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.CallFailCause; @@ -335,7 +333,7 @@ public final class SimulatedCommands extends BaseCommands /** * (AsyncResult)response.obj).result will be an Integer representing - * the sum of enabled serivice classes (sum of SERVICE_CLASS_*) + * the sum of enabled service classes (sum of SERVICE_CLASS_*) * * @param facility one of CB_FACILTY_* * @param pin password or "" if not required @@ -441,7 +439,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result contains a List of DriverCall * The ar.result List is sorted by DriverCall.index */ @@ -468,7 +466,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result contains a List of DataCallState */ public void getDataCallList(Message result) { @@ -479,7 +477,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * CLIR_DEFAULT == on "use subscription default value" @@ -496,7 +494,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * CLIR_DEFAULT == on "use subscription default value" @@ -513,7 +511,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is String containing IMSI on success */ public void getIMSI(Message result) { @@ -524,7 +522,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is String containing IMEI on success */ public void getIMEI(Message result) { @@ -535,7 +533,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is String containing IMEISV on success */ public void getIMEISV(Message result) { @@ -547,7 +545,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * 3GPP 22.030 6.5.5 @@ -572,7 +570,7 @@ public final class SimulatedCommands extends BaseCommands * "Releases all held calls or sets User Determined User Busy (UDUB) * for a waiting call." * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void hangupWaitingOrBackground (Message result) { @@ -593,7 +591,7 @@ public final class SimulatedCommands extends BaseCommands * the other (held or waiting) call." * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void hangupForegroundResumeBackground (Message result) { @@ -614,7 +612,7 @@ public final class SimulatedCommands extends BaseCommands * the other (held or waiting) call." * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void switchWaitingOrHoldingAndActive (Message result) { @@ -634,7 +632,7 @@ public final class SimulatedCommands extends BaseCommands * "Adds a held call to the conversation" * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void conference (Message result) { @@ -654,7 +652,7 @@ public final class SimulatedCommands extends BaseCommands * "Connects the two calls and disconnects the subscriber from both calls" * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void explicitCallTransfer (Message result) { @@ -690,7 +688,7 @@ public final class SimulatedCommands extends BaseCommands /** * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void acceptCall (Message result) { @@ -708,7 +706,7 @@ public final class SimulatedCommands extends BaseCommands /** * also known as UDUB * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void rejectCall (Message result) { @@ -785,7 +783,7 @@ public final class SimulatedCommands extends BaseCommands * * @param result is callback message * ((AsyncResult)response.obj).result is an int[] with every - * element representing one avialable BM_*_BAND + * element representing one available BM_*_BAND */ public void queryAvailableBandMode (Message result) { int ret[] = new int [4]; @@ -894,7 +892,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void sendDtmf(char c, Message result) { @@ -903,7 +901,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void startDtmf(char c, Message result) { @@ -912,7 +910,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void stopDtmf(Message result) { @@ -921,7 +919,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { @@ -956,21 +954,12 @@ public final class SimulatedCommands extends BaseCommands unimplemented(response); } - public void setupDefaultPDP(String apn, String user, String password, Message result) { - unimplemented(result); - } - public void setupDataCall(String radioTechnology, String profile, String apn, String user, String password, String authType, Message result) { unimplemented(result); } - public void deactivateDataCall(int cid, Message result) {unimplemented(result);} - - /** - * @deprecated - */ - public void deactivateDefaultPDP(int cid, Message result) {unimplemented(result);} + public void deactivateDataCall(int cid, int reason, Message result) {unimplemented(result);} public void setPreferredNetworkType(int networkType , Message result) { mNetworkType = networkType; @@ -1046,7 +1035,7 @@ public final class SimulatedCommands extends BaseCommands } /** - * parameters equivilient to 27.007 AT+CRSM command + * parameters equivalent to 27.007 AT+CRSM command * response.obj will be an AsyncResult * response.obj.userObj will be a SimIoResult on success */ |
