am c5193c62: Merge "Add new landscape and portrait orientation features." into honeycomb-mr2
* commit 'c5193c6285d7094fb86dcb5cd56f44a3788af7c2':
Add new landscape and portrait orientation features.
diff --git a/Android.mk b/Android.mk
index 24c0dc4..36ae106 100644
--- a/Android.mk
+++ b/Android.mk
@@ -123,10 +123,10 @@
core/java/android/nfc/ILlcpServiceSocket.aidl \
core/java/android/nfc/ILlcpSocket.aidl \
core/java/android/nfc/INfcAdapter.aidl \
+ core/java/android/nfc/INfcAdapterExtras.aidl \
core/java/android/nfc/INfcTag.aidl \
core/java/android/nfc/IP2pInitiator.aidl \
core/java/android/nfc/IP2pTarget.aidl \
- core/java/android/nfc/INfcSecureElement.aidl \
core/java/android/os/IHardwareService.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/INetworkManagementService.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2eee813..023ce59 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -95,7 +95,7 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/PerfTest_intermediates/)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/RSTest_intermediates/)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware/IUsbManager.java)
-
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index f6d702f..ccc4fd7 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -109,7 +109,10 @@
run_command("NETWORK INTERFACES", 10, "su", "root", "netcfg", NULL);
dump_file("NETWORK ROUTES", "/proc/net/route");
+ dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
dump_file("ARP CACHE", "/proc/net/arp");
+ run_command("IPTABLES", 10, "su", "root", "iptables", "-L", NULL);
+ run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", NULL);
run_command("WIFI NETWORKS", 20,
"su", "root", "wpa_cli", "list_networks", NULL);
@@ -121,6 +124,13 @@
"su", "root", "wlutil", "counters", NULL);
#endif
+ char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
+ property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
+ if (strlen(ril_dumpstate_timeout) > 0) {
+ run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+ "su", "root", "vril-dump", NULL);
+ }
+
print_properties();
run_command("KERNEL LOG", 20, "dmesg", NULL);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ccd65de..c9351af 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -416,7 +416,7 @@
if (this.largeIcon != null) {
that.largeIcon = Bitmap.createBitmap(this.largeIcon);
}
- that.iconLevel = that.iconLevel;
+ that.iconLevel = this.iconLevel;
that.sound = this.sound; // android.net.Uri is immutable
that.audioStreamType = this.audioStreamType;
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 9855709..6f3a2e7 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -26,8 +26,8 @@
import android.server.BluetoothService;
import android.util.Log;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import java.util.Set;
@@ -57,7 +57,7 @@
* Todo(): Write tests for this class, when the Android Mock support is completed.
* @hide
*/
-public final class BluetoothDeviceProfileState extends HierarchicalStateMachine {
+public final class BluetoothDeviceProfileState extends StateMachine {
private static final String TAG = "BluetoothDeviceProfileState";
private static final boolean DBG = false;
@@ -235,16 +235,16 @@
}
}
- private class BondedDevice extends HierarchicalState {
+ private class BondedDevice extends State {
@Override
- protected void enter() {
+ public void enter() {
Log.i(TAG, "Entering ACL Connected state with: " + getCurrentMessage().what);
Message m = new Message();
m.copyFrom(getCurrentMessage());
sendMessageAtFrontOfQueue(m);
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("ACL Connected State -> Processing Message: " + message.what);
switch(message.what) {
case CONNECT_HFP_OUTGOING:
@@ -353,12 +353,12 @@
}
}
- private class OutgoingHandsfree extends HierarchicalState {
+ private class OutgoingHandsfree extends State {
private boolean mStatus = false;
private int mCommand;
@Override
- protected void enter() {
+ public void enter() {
Log.i(TAG, "Entering OutgoingHandsfree state with: " + getCurrentMessage().what);
mCommand = getCurrentMessage().what;
if (mCommand != CONNECT_HFP_OUTGOING &&
@@ -374,7 +374,7 @@
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("OutgoingHandsfree State -> Processing Message: " + message.what);
Message deferMsg = new Message();
int command = message.what;
@@ -466,12 +466,12 @@
}
}
- private class IncomingHandsfree extends HierarchicalState {
+ private class IncomingHandsfree extends State {
private boolean mStatus = false;
private int mCommand;
@Override
- protected void enter() {
+ public void enter() {
Log.i(TAG, "Entering IncomingHandsfree state with: " + getCurrentMessage().what);
mCommand = getCurrentMessage().what;
if (mCommand != CONNECT_HFP_INCOMING &&
@@ -487,7 +487,7 @@
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("IncomingHandsfree State -> Processing Message: " + message.what);
switch(message.what) {
case CONNECT_HFP_OUTGOING:
@@ -546,12 +546,12 @@
}
}
- private class OutgoingA2dp extends HierarchicalState {
+ private class OutgoingA2dp extends State {
private boolean mStatus = false;
private int mCommand;
@Override
- protected void enter() {
+ public void enter() {
Log.i(TAG, "Entering OutgoingA2dp state with: " + getCurrentMessage().what);
mCommand = getCurrentMessage().what;
if (mCommand != CONNECT_A2DP_OUTGOING &&
@@ -567,7 +567,7 @@
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("OutgoingA2dp State->Processing Message: " + message.what);
Message deferMsg = new Message();
switch(message.what) {
@@ -656,12 +656,12 @@
}
}
- private class IncomingA2dp extends HierarchicalState {
+ private class IncomingA2dp extends State {
private boolean mStatus = false;
private int mCommand;
@Override
- protected void enter() {
+ public void enter() {
Log.i(TAG, "Entering IncomingA2dp state with: " + getCurrentMessage().what);
mCommand = getCurrentMessage().what;
if (mCommand != CONNECT_A2DP_INCOMING &&
@@ -677,7 +677,7 @@
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("IncomingA2dp State->Processing Message: " + message.what);
Message deferMsg = new Message();
switch(message.what) {
@@ -735,12 +735,12 @@
}
- private class OutgoingHid extends HierarchicalState {
+ private class OutgoingHid extends State {
private boolean mStatus = false;
private int mCommand;
@Override
- protected void enter() {
+ public void enter() {
log("Entering OutgoingHid state with: " + getCurrentMessage().what);
mCommand = getCurrentMessage().what;
if (mCommand != CONNECT_HID_OUTGOING &&
@@ -752,7 +752,7 @@
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("OutgoingHid State->Processing Message: " + message.what);
Message deferMsg = new Message();
switch(message.what) {
@@ -816,12 +816,12 @@
}
}
- private class IncomingHid extends HierarchicalState {
+ private class IncomingHid extends State {
private boolean mStatus = false;
private int mCommand;
@Override
- protected void enter() {
+ public void enter() {
log("Entering IncomingHid state with: " + getCurrentMessage().what);
mCommand = getCurrentMessage().what;
if (mCommand != CONNECT_HID_INCOMING &&
@@ -833,7 +833,7 @@
}
@Override
- protected boolean processMessage(Message message) {
+ public boolean processMessage(Message message) {
log("IncomingHid State->Processing Message: " + message.what);
Message deferMsg = new Message();
switch(message.what) {
diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java
index 18060a0..98afdb8 100644
--- a/core/java/android/bluetooth/BluetoothProfileState.java
+++ b/core/java/android/bluetooth/BluetoothProfileState.java
@@ -22,8 +22,8 @@
import android.os.Message;
import android.util.Log;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
/**
* This state machine is used to serialize the connections
@@ -39,7 +39,7 @@
* @hide
*/
-public class BluetoothProfileState extends HierarchicalStateMachine {
+public class BluetoothProfileState extends StateMachine {
private static final boolean DBG = true;
private static final String TAG = "BluetoothProfileState";
@@ -101,15 +101,15 @@
context.registerReceiver(mBroadcastReceiver, filter);
}
- private class StableState extends HierarchicalState {
+ private class StableState extends State {
@Override
- protected void enter() {
+ public void enter() {
log("Entering Stable State");
mPendingDevice = null;
}
@Override
- protected boolean processMessage(Message msg) {
+ public boolean processMessage(Message msg) {
if (msg.what != TRANSITION_TO_STABLE) {
transitionTo(mPendingCommandState);
}
@@ -117,15 +117,15 @@
}
}
- private class PendingCommandState extends HierarchicalState {
+ private class PendingCommandState extends State {
@Override
- protected void enter() {
+ public void enter() {
log("Entering PendingCommandState State");
dispatchMessage(getCurrentMessage());
}
@Override
- protected boolean processMessage(Message msg) {
+ public boolean processMessage(Message msg) {
if (msg.what == TRANSITION_TO_STABLE) {
transitionTo(mStableState);
} else {
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index c08f14f..a7b0037 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -300,4 +300,8 @@
msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
}
+
+ public void setDependencyMet(boolean met) {
+ // not supported on this network
+ }
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b305e02..eaf9191 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -218,15 +218,35 @@
/** {@hide} */
public static final int TYPE_DUMMY = 8;
+
/**
* The Default Ethernet data connection. When active, all data traffic
* will use this connection by default.
*/
public static final int TYPE_ETHERNET = 9;
- /** {@hide} TODO: Need to adjust this for WiMAX. */
- public static final int MAX_RADIO_TYPE = TYPE_ETHERNET;
- /** {@hide} TODO: Need to adjust this for WiMAX. */
- public static final int MAX_NETWORK_TYPE = TYPE_ETHERNET;
+ /**
+ * Over the air Adminstration.
+ * {@hide}
+ */
+ public static final int TYPE_MOBILE_FOTA = 10;
+
+ /**
+ * IP Multimedia Subsystem
+ * {@hide}
+ */
+ public static final int TYPE_MOBILE_IMS = 11;
+
+ /**
+ * Carrier Branded Services
+ * {@hide}
+ */
+ public static final int TYPE_MOBILE_CBS = 12;
+
+ /** {@hide} */
+ public static final int MAX_RADIO_TYPE = TYPE_MOBILE_CBS;
+
+ /** {@hide} */
+ public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_CBS;
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
@@ -670,4 +690,16 @@
return null;
}
}
+
+ /**
+ * @param networkType The network who's dependence has changed
+ * @param met Boolean - true if network use is ok, false if not
+ * {@hide}
+ */
+ public void setDataDependency(int networkType, boolean met) {
+ try {
+ mService.setDataDependency(networkType, met);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
index 7396669..860da0a 100644
--- a/core/java/android/net/DhcpInfoInternal.java
+++ b/core/java/android/net/DhcpInfoInternal.java
@@ -22,6 +22,8 @@
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
/**
* A simple object for retrieving the results of a DHCP request.
@@ -31,7 +33,6 @@
public class DhcpInfoInternal {
private final static String TAG = "DhcpInfoInternal";
public String ipAddress;
- public String gateway;
public int prefixLength;
public String dns1;
@@ -40,7 +41,14 @@
public String serverAddress;
public int leaseDuration;
+ private Collection<RouteInfo> routes;
+
public DhcpInfoInternal() {
+ routes = new ArrayList<RouteInfo>();
+ }
+
+ public void addRoute(RouteInfo routeInfo) {
+ routes.add(routeInfo);
}
private int convertToInt(String addr) {
@@ -58,7 +66,12 @@
public DhcpInfo makeDhcpInfo() {
DhcpInfo info = new DhcpInfo();
info.ipAddress = convertToInt(ipAddress);
- info.gateway = convertToInt(gateway);
+ for (RouteInfo route : routes) {
+ if (route.isDefaultRoute()) {
+ info.gateway = convertToInt(route.getGateway().getHostAddress());
+ break;
+ }
+ }
try {
InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
@@ -81,8 +94,8 @@
public LinkProperties makeLinkProperties() {
LinkProperties p = new LinkProperties();
p.addLinkAddress(makeLinkAddress());
- if (TextUtils.isEmpty(gateway) == false) {
- p.addGateway(NetworkUtils.numericToInetAddress(gateway));
+ for (RouteInfo route : routes) {
+ p.addRoute(route);
}
if (TextUtils.isEmpty(dns1) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns1));
@@ -98,8 +111,10 @@
}
public String toString() {
+ String routeString = "";
+ for (RouteInfo route : routes) routeString += route.toString() + " | ";
return "addr: " + ipAddress + "/" + prefixLength +
- " gateway: " + gateway +
+ " routes: " + routeString +
" dns: " + dns1 + "," + dns2 +
" dhcpServer: " + serverAddress +
" leaseDuration: " + leaseDuration;
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index f5cf14b..eaf087f 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -17,8 +17,8 @@
package android.net;
import com.android.internal.util.Protocol;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -47,14 +47,14 @@
*
* @hide
*/
-public class DhcpStateMachine extends HierarchicalStateMachine {
+public class DhcpStateMachine extends StateMachine {
private static final String TAG = "DhcpStateMachine";
private static final boolean DBG = false;
/* A StateMachine that controls the DhcpStateMachine */
- private HierarchicalStateMachine mController;
+ private StateMachine mController;
private Context mContext;
private BroadcastReceiver mBroadcastReceiver;
@@ -95,13 +95,13 @@
public static final int DHCP_SUCCESS = 1;
public static final int DHCP_FAILURE = 2;
- private HierarchicalState mDefaultState = new DefaultState();
- private HierarchicalState mStoppedState = new StoppedState();
- private HierarchicalState mWaitBeforeStartState = new WaitBeforeStartState();
- private HierarchicalState mRunningState = new RunningState();
- private HierarchicalState mWaitBeforeRenewalState = new WaitBeforeRenewalState();
+ private State mDefaultState = new DefaultState();
+ private State mStoppedState = new StoppedState();
+ private State mWaitBeforeStartState = new WaitBeforeStartState();
+ private State mRunningState = new RunningState();
+ private State mWaitBeforeRenewalState = new WaitBeforeRenewalState();
- private DhcpStateMachine(Context context, HierarchicalStateMachine controller, String intf) {
+ private DhcpStateMachine(Context context, StateMachine controller, String intf) {
super(TAG);
mContext = context;
@@ -136,7 +136,7 @@
setInitialState(mStoppedState);
}
- public static DhcpStateMachine makeDhcpStateMachine(Context context, HierarchicalStateMachine controller,
+ public static DhcpStateMachine makeDhcpStateMachine(Context context, StateMachine controller,
String intf) {
DhcpStateMachine dsm = new DhcpStateMachine(context, controller, intf);
dsm.start();
@@ -156,7 +156,7 @@
mRegisteredForPreDhcpNotification = true;
}
- class DefaultState extends HierarchicalState {
+ class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
@@ -164,7 +164,7 @@
case CMD_RENEW_DHCP:
Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
break;
- case HSM_QUIT_CMD:
+ case SM_QUIT_CMD:
mContext.unregisterReceiver(mBroadcastReceiver);
//let parent kill the state machine
return NOT_HANDLED;
@@ -177,7 +177,7 @@
}
- class StoppedState extends HierarchicalState {
+ class StoppedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -210,7 +210,7 @@
}
}
- class WaitBeforeStartState extends HierarchicalState {
+ class WaitBeforeStartState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -242,7 +242,7 @@
}
}
- class RunningState extends HierarchicalState {
+ class RunningState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -281,7 +281,7 @@
}
}
- class WaitBeforeRenewalState extends HierarchicalState {
+ class WaitBeforeRenewalState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index d0c77cf..e39725a 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -191,6 +191,10 @@
return new LinkCapabilities(mLinkCapabilities);
}
+ public void setDependencyMet(boolean met) {
+ // not supported on this network
+ }
+
static private void log(String s) {
Slog.d(TAG, s);
}
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index df5fdd0..55850c9 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -330,4 +330,8 @@
public String getTcpBufferSizesPropName() {
return "net.tcp.buffersize.wifi";
}
+
+ public void setDependencyMet(boolean met) {
+ // not supported on this network
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 70ab4f1..8be492c 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -92,4 +92,6 @@
void setGlobalProxy(in ProxyProperties p);
ProxyProperties getProxy();
+
+ void setDataDependency(int networkType, boolean met);
}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 9c36b12..f6a114c 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -78,6 +78,14 @@
this.prefixLength == linkAddress.prefixLength;
}
+ @Override
+ /*
+ * generate hashcode based on significant fields
+ */
+ public int hashCode() {
+ return ((null == address) ? 0 : address.hashCode()) + prefixLength;
+ }
+
/**
* Returns the InetAddress for this address.
*/
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index b6e9751..19894a0 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -19,11 +19,9 @@
import android.net.ProxyProperties;
import android.os.Parcelable;
import android.os.Parcel;
-import android.util.Log;
+import android.text.TextUtils;
import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
@@ -56,7 +54,7 @@
String mIfaceName;
private Collection<LinkAddress> mLinkAddresses;
private Collection<InetAddress> mDnses;
- private Collection<InetAddress> mGateways;
+ private Collection<RouteInfo> mRoutes;
private ProxyProperties mHttpProxy;
public LinkProperties() {
@@ -69,8 +67,9 @@
mIfaceName = source.getInterfaceName();
mLinkAddresses = source.getLinkAddresses();
mDnses = source.getDnses();
- mGateways = source.getGateways();
- mHttpProxy = new ProxyProperties(source.getHttpProxy());
+ mRoutes = source.getRoutes();
+ mHttpProxy = (source.getHttpProxy() == null) ?
+ null : new ProxyProperties(source.getHttpProxy());
}
}
@@ -91,7 +90,7 @@
}
public void addLinkAddress(LinkAddress address) {
- mLinkAddresses.add(address);
+ if (address != null) mLinkAddresses.add(address);
}
public Collection<LinkAddress> getLinkAddresses() {
@@ -99,18 +98,18 @@
}
public void addDns(InetAddress dns) {
- mDnses.add(dns);
+ if (dns != null) mDnses.add(dns);
}
public Collection<InetAddress> getDnses() {
return Collections.unmodifiableCollection(mDnses);
}
- public void addGateway(InetAddress gateway) {
- mGateways.add(gateway);
+ public void addRoute(RouteInfo route) {
+ if (route != null) mRoutes.add(route);
}
- public Collection<InetAddress> getGateways() {
- return Collections.unmodifiableCollection(mGateways);
+ public Collection<RouteInfo> getRoutes() {
+ return Collections.unmodifiableCollection(mRoutes);
}
public void setHttpProxy(ProxyProperties proxy) {
@@ -124,7 +123,7 @@
mIfaceName = null;
mLinkAddresses = new ArrayList<LinkAddress>();
mDnses = new ArrayList<InetAddress>();
- mGateways = new ArrayList<InetAddress>();
+ mRoutes = new ArrayList<RouteInfo>();
mHttpProxy = null;
}
@@ -141,19 +140,80 @@
String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
String linkAddresses = "LinkAddresses: [";
- for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString();
+ for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
linkAddresses += "] ";
String dns = "DnsAddresses: [";
for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
dns += "] ";
- String gateways = "Gateways: [";
- for (InetAddress gw : mGateways) gateways += gw.getHostAddress() + ",";
- gateways += "] ";
+ String routes = "Routes: [";
+ for (RouteInfo route : mRoutes) routes += route.toString() + ",";
+ routes += "] ";
String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
- return ifaceName + linkAddresses + gateways + dns + proxy;
+ return ifaceName + linkAddresses + routes + dns + proxy;
+ }
+
+
+ @Override
+ /**
+ * Compares this {@code LinkProperties} instance against the target
+ * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
+ * all their fields are equal in values.
+ *
+ * For collection fields, such as mDnses, containsAll() is used to check
+ * if two collections contains the same elements, independent of order.
+ * There are two thoughts regarding containsAll()
+ * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
+ * 2. Worst case performance is O(n^2).
+ *
+ * @param obj the object to be tested for equality.
+ * @return {@code true} if both objects are equal, {@code false} otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+
+ if (!(obj instanceof LinkProperties)) return false;
+
+ boolean sameAddresses;
+ boolean sameDnses;
+ boolean sameRoutes;
+
+ LinkProperties target = (LinkProperties) obj;
+
+ Collection<InetAddress> targetAddresses = target.getAddresses();
+ Collection<InetAddress> sourceAddresses = getAddresses();
+ sameAddresses = (sourceAddresses.size() == targetAddresses.size()) ?
+ sourceAddresses.containsAll(targetAddresses) : false;
+
+ Collection<InetAddress> targetDnses = target.getDnses();
+ sameDnses = (mDnses.size() == targetDnses.size()) ?
+ mDnses.containsAll(targetDnses) : false;
+
+ Collection<RouteInfo> targetRoutes = target.getRoutes();
+ sameRoutes = (mRoutes.size() == targetRoutes.size()) ?
+ mRoutes.containsAll(targetRoutes) : false;
+
+ return
+ sameAddresses && sameDnses && sameRoutes
+ && TextUtils.equals(getInterfaceName(), target.getInterfaceName())
+ && (getHttpProxy() == null ? target.getHttpProxy() == null :
+ getHttpProxy().equals(target.getHttpProxy()));
+ }
+
+ @Override
+ /**
+ * generate hashcode based on significant fields
+ * Equal objects must produce the same hash code, while unequal objects
+ * may have the same hash codes.
+ */
+ public int hashCode() {
+ return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
+ + mLinkAddresses.size() * 31
+ + mDnses.size() * 37
+ + mRoutes.size() * 41
+ + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
}
/**
@@ -172,9 +232,9 @@
dest.writeByteArray(d.getAddress());
}
- dest.writeInt(mGateways.size());
- for(InetAddress gw : mGateways) {
- dest.writeByteArray(gw.getAddress());
+ dest.writeInt(mRoutes.size());
+ for(RouteInfo route : mRoutes) {
+ dest.writeParcelable(route, flags);
}
if (mHttpProxy != null) {
@@ -213,9 +273,7 @@
}
addressCount = in.readInt();
for (int i=0; i<addressCount; i++) {
- try {
- netProp.addGateway(InetAddress.getByAddress(in.createByteArray()));
- } catch (UnknownHostException e) { }
+ netProp.addRoute((RouteInfo)in.readParcelable(null));
}
if (in.readByte() == 1) {
netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index e04964e..770f152 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Messenger;
@@ -275,6 +276,21 @@
setDetailedState(DetailedState.CONNECTED, reason, apnName);
break;
}
+ } else {
+ // There was no state change. Check if LinkProperties has been updated.
+ if (TextUtils.equals(reason, Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+ mLinkProperties = intent.getParcelableExtra(Phone.DATA_LINK_PROPERTIES_KEY);
+ if (mLinkProperties == null) {
+ log("No link property in LINK_PROPERTIES change event.");
+ mLinkProperties = new LinkProperties();
+ }
+ // Just update reason field in this NetworkInfo
+ mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
+ mNetworkInfo.getExtraInfo());
+ Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED,
+ mNetworkInfo);
+ msg.sendToTarget();
+ }
}
} else if (intent.getAction().
equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
@@ -437,7 +453,8 @@
retValue = true;
break;
case Phone.APN_REQUEST_STARTED:
- // no need to do anything - we're already due some status update intents
+ // set IDLE here , avoid the following second FAILED not sent out
+ mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null);
retValue = true;
break;
case Phone.APN_REQUEST_FAILED:
@@ -492,6 +509,25 @@
}
}
+ /**
+ * carrier dependency is met/unmet
+ * @param met
+ */
+ public void setDependencyMet(boolean met) {
+ Bundle bundle = Bundle.forPair(DataConnectionTracker.APN_TYPE_KEY, mApnType);
+ try {
+ log("setDependencyMet: E met=" + met);
+ Message msg = Message.obtain();
+ msg.what = DataConnectionTracker.CMD_SET_DEPENDENCY_MET;
+ msg.arg1 = (met ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
+ msg.setData(bundle);
+ mDataConnectionTrackerAc.sendMessage(msg);
+ log("setDependencyMet: X met=" + met);
+ } catch (NullPointerException e) {
+ log("setDependencyMet: X mAc was null" + e);
+ }
+ }
+
@Override
public String toString() {
StringBuffer sb = new StringBuffer("Mobile data state: ");
@@ -546,6 +582,12 @@
return Phone.APN_TYPE_DUN;
case ConnectivityManager.TYPE_MOBILE_HIPRI:
return Phone.APN_TYPE_HIPRI;
+ case ConnectivityManager.TYPE_MOBILE_FOTA:
+ return Phone.APN_TYPE_FOTA;
+ case ConnectivityManager.TYPE_MOBILE_IMS:
+ return Phone.APN_TYPE_IMS;
+ case ConnectivityManager.TYPE_MOBILE_CBS:
+ return Phone.APN_TYPE_CBS;
default:
sloge("Error mapping networkType " + netType + " to apnType.");
return null;
diff --git a/core/java/android/net/NetworkConfig.java b/core/java/android/net/NetworkConfig.java
new file mode 100644
index 0000000..3cc0bc5
--- /dev/null
+++ b/core/java/android/net/NetworkConfig.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.util.Log;
+
+/**
+ * Describes the buildtime configuration of a network.
+ * Holds settings read from resources.
+ * @hide
+ */
+public class NetworkConfig {
+ /**
+ * Human readable string
+ */
+ public String name;
+
+ /**
+ * Type from ConnectivityManager
+ */
+ public int type;
+
+ /**
+ * the radio number from radio attributes config
+ */
+ public int radio;
+
+ /**
+ * higher number == higher priority when turning off connections
+ */
+ public int priority;
+
+ /**
+ * indicates the boot time dependencyMet setting
+ */
+ public boolean dependencyMet;
+
+ /**
+ * indicates the default restoral timer in seconds
+ * if the network is used as a special network feature
+ * -1 indicates no restoration of default
+ */
+ public int restoreTime;
+
+ /**
+ * input string from config.xml resource. Uses the form:
+ * [Connection name],[ConnectivityManager connection type],
+ * [associated radio-type],[priority],[dependencyMet]
+ */
+ public NetworkConfig(String init) {
+ String fragments[] = init.split(",");
+ name = fragments[0].trim().toLowerCase();
+ type = Integer.parseInt(fragments[1]);
+ radio = Integer.parseInt(fragments[2]);
+ priority = Integer.parseInt(fragments[3]);
+ restoreTime = Integer.parseInt(fragments[4]);
+ dependencyMet = Boolean.parseBoolean(fragments[5]);
+ }
+
+ /**
+ * Indicates if this network is supposed to be default-routable
+ */
+ public boolean isDefault() {
+ return (type == radio);
+ }
+}
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index eb97d77..f53063d 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -176,4 +176,9 @@
* Indicate tear down requested from connectivity
*/
public void setTeardownRequested(boolean isRequested);
+
+ /**
+ * An external dependency has been met/unmet
+ */
+ public void setDependencyMet(boolean met);
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 823d10f..8a678d6 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -38,32 +38,6 @@
/** Bring the named network interface down. */
public native static int disableInterface(String interfaceName);
- /**
- * Add a route to the routing table.
- *
- * @param interfaceName the interface to route through.
- * @param dst the network or host to route to. May be IPv4 or IPv6, e.g.
- * "0.0.0.0" or "2001:4860::".
- * @param prefixLength the prefix length of the route.
- * @param gw the gateway to use, e.g., "192.168.251.1". If null,
- * indicates a directly-connected route.
- */
- public native static int addRoute(String interfaceName, String dst,
- int prefixLength, String gw);
-
- /** Return the gateway address for the default route for the named interface. */
- public static InetAddress getDefaultRoute(String interfaceName) {
- int addr = getDefaultRouteNative(interfaceName);
- return intToInetAddress(addr);
- }
- private native static int getDefaultRouteNative(String interfaceName);
-
- /** Remove host routes that uses the named interface. */
- public native static int removeHostRoutes(String interfaceName);
-
- /** Remove the default route for the named interface. */
- public native static int removeDefaultRoute(String interfaceName);
-
/** Reset any sockets that are connected via the named interface. */
public native static int resetConnections(String interfaceName);
@@ -160,6 +134,15 @@
}
/**
+ * Convert a IPv4 netmask integer to a prefix length
+ * @param netmask as an integer in network byte order
+ * @return the network prefix length
+ */
+ public static int netmaskIntToPrefixLength(int netmask) {
+ return Integer.bitCount(netmask);
+ }
+
+ /**
* Create an InetAddress from a string where the string must be a standard
* representation of a V4 or V6 address. Avoids doing a DNS lookup on failure
* but it will throw an IllegalArgumentException in that case.
@@ -173,56 +156,69 @@
}
/**
- * Add a default route through the specified gateway.
- * @param interfaceName interface on which the route should be added
- * @param gw the IP address of the gateway to which the route is desired,
- * @return {@code true} on success, {@code false} on failure
+ * Get InetAddress masked with prefixLength. Will never return null.
+ * @param IP address which will be masked with specified prefixLength
+ * @param prefixLength the prefixLength used to mask the IP
*/
- public static boolean addDefaultRoute(String interfaceName, InetAddress gw) {
- String dstStr;
- String gwStr = gw.getHostAddress();
-
- if (gw instanceof Inet4Address) {
- dstStr = "0.0.0.0";
- } else if (gw instanceof Inet6Address) {
- dstStr = "::";
- } else {
- Log.w(TAG, "addDefaultRoute failure: address is neither IPv4 nor IPv6" +
- "(" + gwStr + ")");
- return false;
+ public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
+ if (address == null) {
+ throw new RuntimeException("getNetworkPart doesn't accept null address");
}
- return addRoute(interfaceName, dstStr, 0, gwStr) == 0;
+
+ byte[] array = address.getAddress();
+
+ if (prefixLength < 0 || prefixLength > array.length * 8) {
+ throw new RuntimeException("getNetworkPart - bad prefixLength");
+ }
+
+ int offset = prefixLength / 8;
+ int reminder = prefixLength % 8;
+ byte mask = (byte)(0xFF << (8 - reminder));
+
+ if (offset < array.length) array[offset] = (byte)(array[offset] & mask);
+
+ offset++;
+
+ for (; offset < array.length; offset++) {
+ array[offset] = 0;
+ }
+
+ InetAddress netPart = null;
+ try {
+ netPart = InetAddress.getByAddress(array);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException("getNetworkPart error - " + e.toString());
+ }
+ return netPart;
}
/**
- * Add a host route.
- * @param interfaceName interface on which the route should be added
- * @param dst the IP address of the host to which the route is desired,
- * this should not be null.
- * @param gw the IP address of the gateway to which the route is desired,
- * if null, indicates a directly-connected route.
- * @return {@code true} on success, {@code false} on failure
+ * Check if IP address type is consistent between two InetAddress.
+ * @return true if both are the same type. False otherwise.
*/
- public static boolean addHostRoute(String interfaceName, InetAddress dst,
- InetAddress gw) {
- if (dst == null) {
- Log.w(TAG, "addHostRoute: dst should not be null");
- return false;
- }
+ public static boolean addressTypeMatches(InetAddress left, InetAddress right) {
+ return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) ||
+ ((left instanceof Inet6Address) && (right instanceof Inet6Address)));
+ }
- int prefixLength;
- String dstStr = dst.getHostAddress();
- String gwStr = (gw != null) ? gw.getHostAddress() : null;
-
- if (dst instanceof Inet4Address) {
- prefixLength = 32;
- } else if (dst instanceof Inet6Address) {
- prefixLength = 128;
- } else {
- Log.w(TAG, "addHostRoute failure: address is neither IPv4 nor IPv6" +
- "(" + dst + ")");
- return false;
+ /**
+ * Convert a 32 char hex string into a Inet6Address.
+ * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be
+ * made into an Inet6Address
+ * @param addrHexString a 32 character hex string representing an IPv6 addr
+ * @return addr an InetAddress representation for the string
+ */
+ public static InetAddress hexToInet6Address(String addrHexString)
+ throws IllegalArgumentException {
+ try {
+ return numericToInetAddress(String.format("%s:%s:%s:%s:%s:%s:%s:%s",
+ addrHexString.substring(0,4), addrHexString.substring(4,8),
+ addrHexString.substring(8,12), addrHexString.substring(12,16),
+ addrHexString.substring(16,20), addrHexString.substring(20,24),
+ addrHexString.substring(24,28), addrHexString.substring(28,32)));
+ } catch (Exception e) {
+ Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e);
+ throw new IllegalArgumentException(e);
}
- return addRoute(interfaceName, dstStr, prefixLength, gwStr) == 0;
}
}
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index cbe4445..44dbec1 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -163,6 +163,16 @@
return 0;
}
+ @Override
+ /*
+ * generate hashcode based on significant fields
+ */
+ public int hashCode() {
+ return ((null == mHost) ? 0 : mHost.hashCode())
+ + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
+ + mPort;
+ }
+
/**
* Implement the Parcelable interface.
* @hide
diff --git a/core/java/android/net/RouteInfo.aidl b/core/java/android/net/RouteInfo.aidl
new file mode 100644
index 0000000..2296a57
--- /dev/null
+++ b/core/java/android/net/RouteInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable RouteInfo;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
new file mode 100644
index 0000000..8e5ddda
--- /dev/null
+++ b/core/java/android/net/RouteInfo.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.UnknownHostException;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+
+import java.util.Collection;
+
+/**
+ * A simple container for route information.
+ *
+ * @hide
+ */
+public class RouteInfo implements Parcelable {
+ /**
+ * The IP destination address for this route.
+ */
+ private final LinkAddress mDestination;
+
+ /**
+ * The gateway address for this route.
+ */
+ private final InetAddress mGateway;
+
+ private final boolean mIsDefault;
+
+ public RouteInfo(LinkAddress destination, InetAddress gateway) {
+ if (destination == null) {
+ if (gateway != null) {
+ if (gateway instanceof Inet4Address) {
+ destination = new LinkAddress(Inet4Address.ANY, 0);
+ } else {
+ destination = new LinkAddress(Inet6Address.ANY, 0);
+ }
+ } else {
+ // no destination, no gateway. invalid.
+ throw new RuntimeException("Invalid arguments passed in.");
+ }
+ }
+ if (gateway == null) {
+ if (destination.getAddress() instanceof Inet4Address) {
+ gateway = Inet4Address.ANY;
+ } else {
+ gateway = Inet6Address.ANY;
+ }
+ }
+ mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
+ destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
+ mGateway = gateway;
+ mIsDefault = isDefault();
+ }
+
+ public RouteInfo(InetAddress gateway) {
+ this(null, gateway);
+ }
+
+ public static RouteInfo makeHostRoute(InetAddress host) {
+ return makeHostRoute(host, null);
+ }
+
+ public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway) {
+ if (host == null) return null;
+
+ if (host instanceof Inet4Address) {
+ return new RouteInfo(new LinkAddress(host, 32), gateway);
+ } else {
+ return new RouteInfo(new LinkAddress(host, 128), gateway);
+ }
+ }
+
+ private boolean isDefault() {
+ boolean val = false;
+ if (mGateway != null) {
+ if (mGateway instanceof Inet4Address) {
+ val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
+ } else {
+ val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
+ }
+ }
+ return val;
+ }
+
+ public LinkAddress getDestination() {
+ return mDestination;
+ }
+
+ public InetAddress getGateway() {
+ return mGateway;
+ }
+
+ public boolean isDefaultRoute() {
+ return mIsDefault;
+ }
+
+ public String toString() {
+ String val = "";
+ if (mDestination != null) val = mDestination.toString();
+ if (mGateway != null) val += " -> " + mGateway.getHostAddress();
+ return val;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mDestination == null) {
+ dest.writeByte((byte) 0);
+ } else {
+ dest.writeByte((byte) 1);
+ dest.writeByteArray(mDestination.getAddress().getAddress());
+ dest.writeInt(mDestination.getNetworkPrefixLength());
+ }
+
+ if (mGateway == null) {
+ dest.writeByte((byte) 0);
+ } else {
+ dest.writeByte((byte) 1);
+ dest.writeByteArray(mGateway.getAddress());
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+
+ if (!(obj instanceof RouteInfo)) return false;
+
+ RouteInfo target = (RouteInfo) obj;
+
+ boolean sameDestination = ( mDestination == null) ?
+ target.getDestination() == null
+ : mDestination.equals(target.getDestination());
+
+ boolean sameAddress = (mGateway == null) ?
+ target.getGateway() == null
+ : mGateway.equals(target.getGateway());
+
+ return sameDestination && sameAddress
+ && mIsDefault == target.mIsDefault;
+ }
+
+ @Override
+ public int hashCode() {
+ return (mDestination == null ? 0 : mDestination.hashCode())
+ + (mGateway == null ? 0 :mGateway.hashCode())
+ + (mIsDefault ? 3 : 7);
+ }
+
+ public static final Creator<RouteInfo> CREATOR =
+ new Creator<RouteInfo>() {
+ public RouteInfo createFromParcel(Parcel in) {
+ InetAddress destAddr = null;
+ int prefix = 0;
+ InetAddress gateway = null;
+
+ if (in.readByte() == 1) {
+ byte[] addr = in.createByteArray();
+ prefix = in.readInt();
+
+ try {
+ destAddr = InetAddress.getByAddress(addr);
+ } catch (UnknownHostException e) {}
+ }
+
+ if (in.readByte() == 1) {
+ byte[] addr = in.createByteArray();
+
+ try {
+ gateway = InetAddress.getByAddress(addr);
+ } catch (UnknownHostException e) {}
+ }
+
+ LinkAddress dest = null;
+
+ if (destAddr != null) {
+ dest = new LinkAddress(destAddr, prefix);
+ }
+
+ return new RouteInfo(dest, gateway);
+ }
+
+ public RouteInfo[] newArray(int size) {
+ return new RouteInfo[size];
+ }
+ };
+
+ private boolean matches(InetAddress destination) {
+ if (destination == null) return false;
+
+ // if the destination is present and the route is default.
+ // return true
+ if (isDefault()) return true;
+
+ // match the route destination and destination with prefix length
+ InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
+ mDestination.getNetworkPrefixLength());
+
+ return mDestination.getAddress().equals(dstNet);
+ }
+
+ /**
+ * Find the route from a Collection of routes that best matches a given address.
+ * May return null if no routes are applicable.
+ * @param routes a Collection of RouteInfos to chose from
+ * @param dest the InetAddress your trying to get to
+ * @return the RouteInfo from the Collection that best fits the given address
+ */
+ public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
+ if ((routes == null) || (dest == null)) return null;
+
+ RouteInfo bestRoute = null;
+ // pick a longest prefix match under same address type
+ for (RouteInfo route : routes) {
+ if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
+ if ((bestRoute != null) &&
+ (bestRoute.mDestination.getNetworkPrefixLength() >=
+ route.mDestination.getNetworkPrefixLength())) {
+ continue;
+ }
+ if (route.matches(dest)) bestRoute = route;
+ }
+ }
+ return bestRoute;
+ }
+}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index d439a48..870127c 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -28,7 +28,7 @@
import android.nfc.INfcTag;
import android.nfc.IP2pTarget;
import android.nfc.IP2pInitiator;
-import android.nfc.INfcSecureElement;
+import android.nfc.INfcAdapterExtras;
/**
* @hide
@@ -41,13 +41,12 @@
INfcTag getNfcTagInterface();
IP2pTarget getP2pTargetInterface();
IP2pInitiator getP2pInitiatorInterface();
- INfcSecureElement getNfcSecureElementInterface();
+ INfcAdapterExtras getNfcAdapterExtrasInterface();
// NfcAdapter-class related methods
boolean isEnabled();
NdefMessage localGet();
void localSet(in NdefMessage message);
- void openTagConnection(in Tag tag);
void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent,
in IntentFilter[] filters, in TechListParcel techLists);
void disableForegroundDispatch(in ComponentName activity);
@@ -59,12 +58,8 @@
int createLlcpConnectionlessSocket(int sap);
int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength);
int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength);
- int deselectSecureElement();
boolean disable();
boolean enable();
String getProperties(String param);
- int[] getSecureElementList();
- int getSelectedSecureElement();
- int selectSecureElement(int seId);
int setProperties(String param, String value);
-}
\ No newline at end of file
+}
diff --git a/core/java/android/nfc/INfcSecureElement.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
similarity index 63%
rename from core/java/android/nfc/INfcSecureElement.aidl
rename to core/java/android/nfc/INfcAdapterExtras.aidl
index aa98dd2..ab5c1a6 100755
--- a/core/java/android/nfc/INfcSecureElement.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,13 +16,15 @@
package android.nfc;
+import android.os.Bundle;
+
/**
* {@hide}
*/
-interface INfcSecureElement {
- int openSecureElementConnection();
- int closeSecureElementConnection(int nativeHandle);
- byte[] exchangeAPDU(int nativeHandle, in byte[] data);
- int[] getSecureElementTechList(int nativeHandle);
- byte[] getSecureElementUid(int nativeHandle);
-}
\ No newline at end of file
+interface INfcAdapterExtras {
+ Bundle open(IBinder b);
+ Bundle close();
+ Bundle transceive(in byte[] data_in);
+ int getCardEmulationRoute();
+ void setCardEmulationRoute(int route);
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 8c56fda..4689804 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -157,31 +157,6 @@
public static final String EXTRA_ID = "android.nfc.extra.ID";
/**
- * Broadcast Action: a transaction with a secure element has been detected.
- * <p>
- * Always contains the extra field
- * {@link android.nfc.NfcAdapter#EXTRA_AID}
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TRANSACTION_DETECTED =
- "android.nfc.action.TRANSACTION_DETECTED";
-
- /**
- * Broadcast Action: an RF field ON has been detected.
- * @hide
- */
- public static final String ACTION_RF_FIELD_ON_DETECTED =
- "android.nfc.action.RF_FIELD_ON_DETECTED";
-
- /**
- * Broadcast Action: an RF Field OFF has been detected.
- * @hide
- */
- public static final String ACTION_RF_FIELD_OFF_DETECTED =
- "android.nfc.action.RF_FIELD_OFF_DETECTED";
-
- /**
* Broadcast Action: an adapter's state changed between enabled and disabled.
*
* The new value is stored in the extra EXTRA_NEW_BOOLEAN_STATE and just contains
@@ -201,15 +176,6 @@
public static final String EXTRA_NEW_BOOLEAN_STATE = "android.nfc.isEnabled";
/**
- * Mandatory byte array extra field in
- * {@link android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED}.
- * <p>
- * Contains the AID of the applet involved in the transaction.
- * @hide
- */
- public static final String EXTRA_AID = "android.nfc.extra.AID";
-
- /**
* LLCP link status: The LLCP link is activated.
* @hide
*/
@@ -691,39 +657,14 @@
}
/**
- * Create an Nfc Secure Element Connection
* @hide
*/
- public NfcSecureElement createNfcSecureElementConnection() {
+ public INfcAdapterExtras getNfcAdapterExtrasInterface() {
try {
- return new NfcSecureElement(sService.getNfcSecureElementInterface());
+ return sService.getNfcAdapterExtrasInterface();
} catch (RemoteException e) {
- Log.e(TAG, "createNfcSecureElementConnection failed", e);
+ attemptDeadServiceRecovery(e);
return null;
}
}
-
- /**
- * To change the Secure Element Card Emulation state (ON/OFF)
- * @hide
- */
- public void changeNfcSecureElementCardEmulationState(boolean state)
- {
- int seId = 11259375;
- if(state){
- /* Enable card emulation */
- try {
- sService.selectSecureElement(seId);
- } catch (RemoteException e) {
- Log.e(TAG, "Enable card emulation failed", e);
- }
- }else{
- /* Disable card emulation */
- try {
- sService.deselectSecureElement();
- } catch (RemoteException e) {
- Log.e(TAG, " card emulation failed", e);
- }
- }
- }
}
diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java
deleted file mode 100755
index 3b5f39e..0000000
--- a/core/java/android/nfc/NfcSecureElement.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.nfc.tech.TagTechnology;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-//import android.util.Log;
-
-/**
- * This class provides the primary API for managing all aspects Secure Element.
- * Get an instance of this class by calling
- * Context.getSystemService(Context.NFC_SERVICE).
- * @hide
- */
-public final class NfcSecureElement {
-
- private static final String TAG = "NfcSecureElement";
-
- private INfcSecureElement mService;
-
-
- /**
- * @hide
- */
- public NfcSecureElement(INfcSecureElement mSecureElementService) {
- mService = mSecureElementService;
- }
-
- public int openSecureElementConnection(String seType) throws IOException {
- if (seType.equals("SmartMX")) {
- try {
- int handle = mService.openSecureElementConnection();
- // Handle potential errors
- if (handle != 0) {
- return handle;
- } else {
- throw new IOException("SmartMX connection not allowed");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openSecureElementConnection(): ", e);
- return 0;
- }
-
- } else if (seType.equals("UICC")) {
- return 0;
- } else {
- throw new IOException("Wrong Secure Element type");
- }
- }
-
-
- public byte [] exchangeAPDU(int handle,byte [] data) throws IOException {
-
-
- // Perform exchange APDU
- try {
- byte[] response = mService.exchangeAPDU(handle, data);
- // Handle potential errors
- if (response == null) {
- throw new IOException("Exchange APDU failed");
- }
- return response;
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in exchangeAPDU(): ", e);
- return null;
- }
- }
-
- public void closeSecureElementConnection(int handle) throws IOException {
-
- try {
- int status = mService.closeSecureElementConnection(handle);
- // Handle potential errors
- if (ErrorCodes.isError(status)) {
- throw new IOException("Error during the conection close");
- };
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in closeSecureElement(): ", e);
- }
- }
-
-
- /**
- * Returns target type. constants.
- *
- * @return Secure Element technology type. The possible values are defined in
- * {@link TagTechnology}
- *
- */
- public int[] getSecureElementTechList(int handle) throws IOException {
- try {
- return mService.getSecureElementTechList(handle);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getType(): ", e);
- return null;
- }
- }
-
- /**
- * Returns Secure Element UID.
- *
- * @return Secure Element UID.
- */
- public byte[] getSecureElementUid(int handle) throws IOException {
-
- byte[] uid = null;
- try {
- uid = mService.getSecureElementUid(handle);
- // Handle potential errors
- if (uid == null) {
- throw new IOException("Get Secure Element UID failed");
- }
- return uid;
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getType(): ", e);
- return null;
- }
- }
-
-}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index f56f6a9..632daa1 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -19,19 +19,20 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedInputStream;
/**
* Tools for managing files. Not for public consumption.
* @hide
*/
-public class FileUtils
-{
+public class FileUtils {
public static final int S_IRWXU = 00700;
public static final int S_IRUSR = 00400;
public static final int S_IWUSR = 00200;
@@ -94,7 +95,7 @@
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
- * @param mount point for FAT volume
+ * @param mountPoint point for FAT volume
* @return volume ID or -1
*/
public static native int getFatVolumeId(String mountPoint);
@@ -226,4 +227,32 @@
input.close();
}
}
+
+ /**
+ * Computes the checksum of a file using the CRC32 checksum routine.
+ * The value of the checksum is returned.
+ *
+ * @param file the file to checksum, must not be null
+ * @return the checksum value or an exception is thrown.
+ */
+ public static long checksumCrc32(File file) throws FileNotFoundException, IOException {
+ CRC32 checkSummer = new CRC32();
+ CheckedInputStream cis = null;
+
+ try {
+ cis = new CheckedInputStream( new FileInputStream(file), checkSummer);
+ byte[] buf = new byte[128];
+ while(cis.read(buf) >= 0) {
+ // Just read for checksum to get calculated.
+ }
+ return checkSummer.getValue();
+ } finally {
+ if (cis != null) {
+ try {
+ cis.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 212c5fb..5a245f8 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,6 +19,7 @@
import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
+import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
/**
@@ -57,6 +58,22 @@
void setInterfaceConfig(String iface, in InterfaceConfiguration cfg);
/**
+ * Retrieves the network routes currently configured on the specified
+ * interface
+ */
+ RouteInfo[] getRoutes(String iface);
+
+ /**
+ * Add the specified route to the interface.
+ */
+ void addRoute(String iface, in RouteInfo route);
+
+ /**
+ * Remove the specified route from the interface.
+ */
+ void removeRoute(String iface, in RouteInfo route);
+
+ /**
* Shuts down the service
*/
void shutdown();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 58d9952..eb9eb03 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3706,6 +3706,29 @@
"inet_condition_debounce_down_delay";
/**
+ * URL to open browser on to allow user to manage a prepay account
+ * @hide
+ */
+ public static final String SETUP_PREPAID_DATA_SERVICE_URL =
+ "setup_prepaid_data_service_url";
+
+ /**
+ * URL to attempt a GET on to see if this is a prepay device
+ * @hide
+ */
+ public static final String SETUP_PREPAID_DETECTION_TARGET_URL =
+ "setup_prepaid_detection_target_url";
+
+ /**
+ * Host to check for a redirect to after an attempt to GET
+ * SETUP_PREPAID_DETECTION_TARGET_URL. (If we redirected there,
+ * this is a prepaid device with zero balance.)
+ * @hide
+ */
+ public static final String SETUP_PREPAID_DETECTION_REDIR_HOST =
+ "setup_prepaid_detection_redir_host";
+
+ /**
* @hide
*/
public static final String[] SETTINGS_TO_BACKUP = {
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 62f66b6..d2d2557 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1723,6 +1723,14 @@
public static final String TYPE = "type";
+ public static final String INACTIVE_TIMER = "inactivetimer";
+
+ // Only if enabled try Data Connection.
+ public static final String ENABLED = "enabled";
+
+ // Rules apply based on class.
+ public static final String CLASS = "class";
+
/**
* The protocol to be used to connect to this APN.
*
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index cdb0339..1440a81 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1204,10 +1204,11 @@
}
}
mSurfaceHolder.mSurfaceLock.lock();
- // Make surface invalid.
- //mSurfaceHolder.mSurface.copyFrom(mSurface);
- mSurfaceHolder.mSurface = new Surface();
- mSurfaceHolder.mSurfaceLock.unlock();
+ try {
+ mSurfaceHolder.mSurface = new Surface();
+ } finally {
+ mSurfaceHolder.mSurfaceLock.unlock();
+ }
}
}
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index 101dd91..3973344 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -44,16 +44,16 @@
* In this usage model there is no need for the destination to
* use the connect methods. The typical sequence of operations is:</p>
*<ol>
- * <li>Client calls AsyncChannel#connect</li>
- * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * <li>Client calls AsyncChannel#connectSync or Asynchronously:</li>
+ * <ol>For an asynchronous half connection client calls AsyncChannel#connect.</ol>
+ * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * </ol>
* <li><code>comm-loop:</code></li>
- * <li>Client calls AsyncChannel#sendMessage(msgX)</li>
- * <li>Server receives and processes msgX</li>
- * <li>Server optionally calls AsyncChannel#replyToMessage(msgY)
- * and if sent Client receives and processes msgY</li>
+ * <li>Client calls AsyncChannel#sendMessage</li>
+ * <li>Server processes messages and optionally replies using AsyncChannel#replyToMessage
* <li>Loop to <code>comm-loop</code> until done</li>
- * <li>When done Client calls {@link AsyncChannel#disconnect(int)}</li>
- * <li>Client receives CMD_CHANNEL_DISCONNECTED from AsyncChannel</li>
+ * <li>When done Client calls {@link AsyncChannel#disconnect}</li>
+ * <li>Client/Server receives CMD_CHANNEL_DISCONNECTED from AsyncChannel</li>
*</ol>
*<br/>
* <p>A second usage model is where the server/destination needs to know
@@ -62,21 +62,26 @@
* different state for each client. In this model the server will also
* use the connect methods. The typical sequence of operation is:</p>
*<ol>
- * <li>Client calls AsyncChannel#connect</li>
- * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
- * <li>Client calls AsyncChannel#sendMessage(CMD_CHANNEL_FULL_CONNECTION)</li>
+ * <li>Client calls AsyncChannel#fullyConnectSync or Asynchronously:<li>
+ * <ol>For an asynchronous full connection it calls AsyncChannel#connect</li>
+ * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * <li>Client calls AsyncChannel#sendMessage(CMD_CHANNEL_FULL_CONNECTION)</li>
+ * </ol>
* <li>Server receives CMD_CHANNEL_FULL_CONNECTION</li>
- * <li>Server calls AsyncChannel#connect</li>
- * <li>Server receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * <li>Server calls AsyncChannel#connected</li>
* <li>Server sends AsyncChannel#sendMessage(CMD_CHANNEL_FULLY_CONNECTED)</li>
* <li>Client receives CMD_CHANNEL_FULLY_CONNECTED</li>
* <li><code>comm-loop:</code></li>
* <li>Client/Server uses AsyncChannel#sendMessage/replyToMessage
* to communicate and perform work</li>
* <li>Loop to <code>comm-loop</code> until done</li>
- * <li>When done Client/Server calls {@link AsyncChannel#disconnect(int)}</li>
+ * <li>When done Client/Server calls {@link AsyncChannel#disconnect}</li>
* <li>Client/Server receives CMD_CHANNEL_DISCONNECTED from AsyncChannel</li>
*</ol>
+ *
+ * TODO: Consider simplifying where we have connect and fullyConnect with only one response
+ * message RSP_CHANNEL_CONNECT instead of two, CMD_CHANNEL_HALF_CONNECTED and
+ * CMD_CHANNEL_FULLY_CONNECTED. We'd also change CMD_CHANNEL_FULL_CONNECTION to REQ_CHANNEL_CONNECT.
*/
public class AsyncChannel {
/** Log tag */
@@ -85,6 +90,8 @@
/** Enable to turn on debugging */
private static final boolean DBG = false;
+ private static final int BASE = Protocol.BASE_SYSTEM_ASYNC_CHANNEL;
+
/**
* Command sent when the channel is half connected. Half connected
* means that the channel can be used to send commends to the destination
@@ -98,7 +105,7 @@
* msg.obj == the AsyncChannel
* msg.replyTo == dstMessenger if successful
*/
- public static final int CMD_CHANNEL_HALF_CONNECTED = -1;
+ public static final int CMD_CHANNEL_HALF_CONNECTED = BASE + 0;
/**
* Command typically sent when after receiving the CMD_CHANNEL_HALF_CONNECTED.
@@ -107,7 +114,7 @@
*
* msg.replyTo = srcMessenger.
*/
- public static final int CMD_CHANNEL_FULL_CONNECTION = -2;
+ public static final int CMD_CHANNEL_FULL_CONNECTION = BASE + 1;
/**
* Command typically sent after the destination receives a CMD_CHANNEL_FULL_CONNECTION.
@@ -115,31 +122,33 @@
*
* msg.arg1 == 0 : Accept connection
* : All other values signify the destination rejected the connection
- * and {@link AsyncChannel#disconnect(int)} would typically be called.
+ * and {@link AsyncChannel#disconnect} would typically be called.
*/
- public static final int CMD_CHANNEL_FULLY_CONNECTED = -3;
+ public static final int CMD_CHANNEL_FULLY_CONNECTED = BASE + 2;
/**
* Command sent when one side or the other wishes to disconnect. The sender
* may or may not be able to receive a reply depending upon the protocol and
- * the state of the connection. The receiver should call {@link AsyncChannel#disconnect(int)}
+ * the state of the connection. The receiver should call {@link AsyncChannel#disconnect}
* to close its side of the channel and it will receive a CMD_CHANNEL_DISCONNECTED
* when the channel is closed.
*
* msg.replyTo = messenger that is disconnecting
*/
- public static final int CMD_CHANNEL_DISCONNECT = -4;
+ public static final int CMD_CHANNEL_DISCONNECT = BASE + 3;
/**
* Command sent when the channel becomes disconnected. This is sent when the
* channel is forcibly disconnected by the system or as a reply to CMD_CHANNEL_DISCONNECT.
*
* msg.arg1 == 0 : STATUS_SUCCESSFUL
+ * 1 : STATUS_BINDING_UNSUCCESSFUL
+ * 2 : STATUS_SEND_UNSUCCESSFUL
* : All other values signify failure and the channel state is indeterminate
* msg.obj == the AsyncChannel
* msg.replyTo = messenger disconnecting or null if it was never connected.
*/
- public static final int CMD_CHANNEL_DISCONNECTED = -5;
+ public static final int CMD_CHANNEL_DISCONNECTED = BASE + 4;
/** Successful status always 0, !0 is an unsuccessful status */
public static final int STATUS_SUCCESSFUL = 0;
@@ -147,6 +156,12 @@
/** Error attempting to bind on a connect */
public static final int STATUS_BINDING_UNSUCCESSFUL = 1;
+ /** Error attempting to send a message */
+ public static final int STATUS_SEND_UNSUCCESSFUL = 2;
+
+ /** CMD_FULLY_CONNECTED refused because a connection already exists*/
+ public static final int STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED = 3;
+
/** Service connection */
private AsyncChannelConnection mConnection;
@@ -169,9 +184,7 @@
}
/**
- * Connect handler to named package/class.
- *
- * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete.
+ * Connect handler to named package/class synchronously.
*
* @param srcContext is the context of the source
* @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
@@ -179,8 +192,10 @@
* @param dstPackageName is the destination package name
* @param dstClassName is the fully qualified class name (i.e. contains
* package name)
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
*/
- private void connectSrcHandlerToPackage(
+ public int connectSrcHandlerToPackageSync(
Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) {
if (DBG) log("connect srcHandler to dst Package & class E");
@@ -202,11 +217,61 @@
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(dstPackageName, dstClassName);
boolean result = srcContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- if (!result) {
- replyHalfConnected(STATUS_BINDING_UNSUCCESSFUL);
- }
-
if (DBG) log("connect srcHandler to dst Package & class X result=" + result);
+ return result ? STATUS_SUCCESSFUL : STATUS_BINDING_UNSUCCESSFUL;
+ }
+
+ /**
+ * Connect a handler to Messenger synchronously.
+ *
+ * @param srcContext is the context of the source
+ * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
+ * messages
+ * @param dstMessenger is the hander to send messages to.
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
+ */
+ public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
+ if (DBG) log("halfConnectSync srcHandler to the dstMessenger E");
+
+ // We are connected
+ connected(srcContext, srcHandler, dstMessenger);
+
+ if (DBG) log("halfConnectSync srcHandler to the dstMessenger X");
+ return STATUS_SUCCESSFUL;
+ }
+
+ /**
+ * connect two local Handlers synchronously.
+ *
+ * @param srcContext is the context of the source
+ * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
+ * messages
+ * @param dstHandler is the hander to send messages to.
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
+ */
+ public int connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
+ return connectSync(srcContext, srcHandler, new Messenger(dstHandler));
+ }
+
+ /**
+ * Fully connect two local Handlers synchronously.
+ *
+ * @param srcContext is the context of the source
+ * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
+ * messages
+ * @param dstHandler is the hander to send messages to.
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
+ */
+ public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
+ int status = connectSync(srcContext, srcHandler, dstHandler);
+ if (status == STATUS_SUCCESSFUL) {
+ Message response = sendMessageSynchronously(CMD_CHANNEL_FULL_CONNECTION);
+ status = response.arg1;
+ }
+ return status;
}
/**
@@ -241,8 +306,11 @@
mDstClassName = dstClassName;
}
+ @Override
public void run() {
- connectSrcHandlerToPackage(mSrcCtx, mSrcHdlr, mDstPackageName, mDstClassName);
+ int result = connectSrcHandlerToPackageSync(mSrcCtx, mSrcHdlr, mDstPackageName,
+ mDstClassName);
+ replyHalfConnected(result);
}
}
@@ -281,15 +349,8 @@
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger E");
- // Initialize source fields
- mSrcContext = srcContext;
- mSrcHandler = srcHandler;
- mSrcMessenger = new Messenger(mSrcHandler);
-
- // Initialize destination fields
- mDstMessenger = dstMessenger;
-
- if (DBG) log("tell source we are half connected");
+ // We are connected
+ connected(srcContext, srcHandler, dstMessenger);
// Tell source we are half connected
replyHalfConnected(STATUS_SUCCESSFUL);
@@ -298,11 +359,31 @@
}
/**
- * Connect two local Handlers.
+ * Connect handler to messenger. This method is typically called
+ * when a server receives a CMD_CHANNEL_FULL_CONNECTION request
+ * and initializes the internal instance variables to allow communication
+ * with the dstMessenger.
*
- * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete.
- * msg.arg1 = status
- * msg.obj = the AsyncChannel
+ * @param srcContext
+ * @param srcHandler
+ * @param dstMessenger
+ */
+ public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
+ if (DBG) log("connected srcHandler to the dstMessenger E");
+
+ // Initialize source fields
+ mSrcContext = srcContext;
+ mSrcHandler = srcHandler;
+ mSrcMessenger = new Messenger(mSrcHandler);
+
+ // Initialize destination fields
+ mDstMessenger = dstMessenger;
+
+ if (DBG) log("connected srcHandler to the dstMessenger X");
+ }
+
+ /**
+ * Connect two local Handlers.
*
* @param srcContext is the context of the source
* @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
@@ -331,6 +412,7 @@
* To close the connection call when handler receives CMD_CHANNEL_DISCONNECTED
*/
public void disconnected() {
+ mSrcContext = null;
mSrcHandler = null;
mSrcMessenger = null;
mDstMessenger = null;
@@ -341,15 +423,11 @@
* Disconnect
*/
public void disconnect() {
- if (mConnection != null) {
+ if ((mConnection != null) && (mSrcContext != null)) {
mSrcContext.unbindService(mConnection);
}
if (mSrcHandler != null) {
- Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
- msg.arg1 = STATUS_SUCCESSFUL;
- msg.obj = this;
- msg.replyTo = mDstMessenger;
- mSrcHandler.sendMessage(msg);
+ replyDisconnected(STATUS_SUCCESSFUL);
}
}
@@ -363,7 +441,7 @@
try {
mDstMessenger.send(msg);
} catch (RemoteException e) {
- log("TODO: handle sendMessage RemoteException" + e);
+ replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}
@@ -444,6 +522,7 @@
*/
public void replyToMessage(Message srcMsg, Message dstMsg) {
try {
+ dstMsg.replyTo = mSrcMessenger;
srcMsg.replyTo.send(dstMsg);
} catch (RemoteException e) {
log("TODO: handle replyToMessage RemoteException" + e);
@@ -694,10 +773,14 @@
private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
SyncMessenger sm = SyncMessenger.obtain();
try {
- msg.replyTo = sm.mMessenger;
- dstMessenger.send(msg);
- synchronized (sm.mHandler.mLockObject) {
- sm.mHandler.mLockObject.wait();
+ if (dstMessenger != null && msg != null) {
+ msg.replyTo = sm.mMessenger;
+ synchronized (sm.mHandler.mLockObject) {
+ dstMessenger.send(msg);
+ sm.mHandler.mLockObject.wait();
+ }
+ } else {
+ sm.mHandler.mResultMsg = null;
}
} catch (InterruptedException e) {
sm.mHandler.mResultMsg = null;
@@ -712,6 +795,7 @@
/**
* Reply to the src handler that we're half connected.
+ * see: CMD_CHANNEL_HALF_CONNECTED for message contents
*
* @param status to be stored in msg.arg1
*/
@@ -724,23 +808,36 @@
}
/**
+ * Reply to the src handler that we are disconnected
+ * see: CMD_CHANNEL_DISCONNECTED for message contents
+ *
+ * @param status to be stored in msg.arg1
+ */
+ private void replyDisconnected(int status) {
+ Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
+ msg.arg1 = status;
+ msg.obj = this;
+ msg.replyTo = mDstMessenger;
+ mSrcHandler.sendMessage(msg);
+ }
+
+
+ /**
* ServiceConnection to receive call backs.
*/
class AsyncChannelConnection implements ServiceConnection {
AsyncChannelConnection() {
}
+ @Override
public void onServiceConnected(ComponentName className, IBinder service) {
mDstMessenger = new Messenger(service);
replyHalfConnected(STATUS_SUCCESSFUL);
}
+ @Override
public void onServiceDisconnected(ComponentName className) {
- Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
- msg.arg1 = STATUS_SUCCESSFUL;
- msg.obj = AsyncChannel.this;
- msg.replyTo = mDstMessenger;
- mSrcHandler.sendMessage(msg);
+ replyDisconnected(STATUS_SUCCESSFUL);
}
}
diff --git a/core/java/com/android/internal/util/HierarchicalState.java b/core/java/com/android/internal/util/IState.java
similarity index 61%
rename from core/java/com/android/internal/util/HierarchicalState.java
rename to core/java/com/android/internal/util/IState.java
index b37f46c..056f8e9 100644
--- a/core/java/com/android/internal/util/HierarchicalState.java
+++ b/core/java/com/android/internal/util/IState.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,21 +21,29 @@
/**
* {@hide}
*
- * The class for implementing states in a HierarchicalStateMachine
+ * The interface for implementing states in a {@link StateMachine}
*/
-public class HierarchicalState {
+public interface IState {
/**
- * Constructor
+ * Returned by processMessage to indicate the the message was processed.
*/
- protected HierarchicalState() {
- }
+ static final boolean HANDLED = true;
+
+ /**
+ * Returned by processMessage to indicate the the message was NOT processed.
+ */
+ static final boolean NOT_HANDLED = false;
/**
* Called when a state is entered.
*/
- protected void enter() {
- }
+ void enter();
+
+ /**
+ * Called when a state is exited.
+ */
+ void exit();
/**
* Called when a message is to be processed by the
@@ -49,28 +57,15 @@
* be processed until this routine returns.
*
* @param msg to process
- * @return true if processing has completed and false
- * if the parent state's processMessage should
- * be invoked.
+ * @return HANDLED if processing has completed and NOT_HANDLED
+ * if the message wasn't processed.
*/
- protected boolean processMessage(Message msg) {
- return false;
- }
+ boolean processMessage(Message msg);
/**
- * Called when a state is exited.
+ * Name of State for debugging purposes.
+ *
+ * @return name of state.
*/
- protected void exit() {
- }
-
- /**
- * @return name of state, but default returns the states
- * class name. An instance name would be better but requiring
- * it seems unnecessary.
- */
- public String getName() {
- String name = getClass().getName();
- int lastDollar = name.lastIndexOf('$');
- return name.substring(lastDollar + 1);
- }
+ String getName();
}
diff --git a/core/java/com/android/internal/util/ProcessedMessages.java b/core/java/com/android/internal/util/ProcessedMessages.java
deleted file mode 100644
index 244474e..0000000
--- a/core/java/com/android/internal/util/ProcessedMessages.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import android.os.Message;
-
-import java.util.Vector;
-
-/**
- * {@hide}
- *
- * A list of messages recently processed by the state machine.
- *
- * The class maintains a list of messages that have been most
- * recently processed. The list is finite and may be set in the
- * constructor or by calling setSize. The public interface also
- * includes size which returns the number of recent messages,
- * count which is the number of message processed since the
- * the last setSize, get which returns a processed message and
- * add which adds a processed messaged.
- */
-public class ProcessedMessages {
-
- public static final int DEFAULT_SIZE = 20;
-
- /**
- * The information maintained for a processed message.
- */
- public class Info {
- private int what;
- private HierarchicalState state;
- private HierarchicalState orgState;
-
- /**
- * Constructor
- * @param message
- * @param state that handled the message
- * @param orgState is the first state the received the message but
- * did not processes the message.
- */
- Info(Message message, HierarchicalState state, HierarchicalState orgState) {
- update(message, state, orgState);
- }
-
- /**
- * Update the information in the record.
- * @param state that handled the message
- * @param orgState is the first state the received the message but
- * did not processes the message.
- */
- public void update(Message message, HierarchicalState state, HierarchicalState orgState) {
- this.what = message.what;
- this.state = state;
- this.orgState = orgState;
- }
-
- /**
- * @return the command that was executing
- */
- public int getWhat() {
- return what;
- }
-
- /**
- * @return the state that handled this message
- */
- public HierarchicalState getState() {
- return state;
- }
-
- /**
- * @return the original state that received the message.
- */
- public HierarchicalState getOriginalState() {
- return orgState;
- }
-
- /**
- * @return as string
- */
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("what=");
- sb.append(what);
- sb.append(" state=");
- sb.append(cn(state));
- sb.append(" orgState=");
- sb.append(cn(orgState));
- return sb.toString();
- }
-
- /**
- * @return an objects class name
- */
- private String cn(Object n) {
- if (n == null) {
- return "null";
- } else {
- String name = n.getClass().getName();
- int lastDollar = name.lastIndexOf('$');
- return name.substring(lastDollar + 1);
- }
- }
- }
-
- private Vector<Info> mMessages = new Vector<Info>();
- private int mMaxSize = DEFAULT_SIZE;
- private int mOldestIndex = 0;
- private int mCount = 0;
-
- /**
- * Constructor
- */
- ProcessedMessages() {
- }
-
- ProcessedMessages(int maxSize) {
- setSize(maxSize);
- }
-
- /**
- * Set size of messages to maintain and clears all current messages.
- *
- * @param maxSize number of messages to maintain at anyone time.
- */
- void setSize(int maxSize) {
- mMaxSize = maxSize;
- mCount = 0;
- mMessages.clear();
- }
-
- /**
- * @return the number of recent messages.
- */
- int size() {
- return mMessages.size();
- }
-
- /**
- * @return the total number of messages processed since size was set.
- */
- int count() {
- return mCount;
- }
-
- /**
- * @return the information on a particular record. 0 is the oldest
- * record and size()-1 is the newest record. If the index is to
- * large null is returned.
- */
- Info get(int index) {
- int nextIndex = mOldestIndex + index;
- if (nextIndex >= mMaxSize) {
- nextIndex -= mMaxSize;
- }
- if (nextIndex >= size()) {
- return null;
- } else {
- return mMessages.get(nextIndex);
- }
- }
-
- /**
- * Add a processed message.
- *
- * @param message
- * @param state that handled the message
- * @param orgState is the first state the received the message but
- * did not processes the message.
- */
- void add(Message message, HierarchicalState state, HierarchicalState orgState) {
- mCount += 1;
- if (mMessages.size() < mMaxSize) {
- mMessages.add(new Info(message, state, orgState));
- } else {
- Info info = mMessages.get(mOldestIndex);
- mOldestIndex += 1;
- if (mOldestIndex >= mMaxSize) {
- mOldestIndex = 0;
- }
- info.update(message, state, orgState);
- }
- }
-}
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 2689f09..2e7ec58 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -29,9 +29,18 @@
* {@hide}
*/
public class Protocol {
- public static final int MAX_MESSAGE = 0x0000FFFF;
+ public static final int MAX_MESSAGE = 0x0000FFFF;
- public static final int BASE_WIFI = 0x00010000;
- public static final int BASE_DHCP = 0x00020000;
+ /** Base reserved for system */
+ public static final int BASE_SYSTEM_RESERVED = 0x00010000;
+ public static final int BASE_SYSTEM_ASYNC_CHANNEL = 0x00011000;
+
+ /** Non system protocols */
+ public static final int BASE_WIFI = 0x00020000;
+ public static final int BASE_DHCP = 0x00030000;
+ public static final int BASE_DATA_CONNECTION = 0x00040000;
+ public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
+ public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000;
+
//TODO: define all used protocols
}
diff --git a/core/java/com/android/internal/util/State.java b/core/java/com/android/internal/util/State.java
new file mode 100644
index 0000000..3eadff5
--- /dev/null
+++ b/core/java/com/android/internal/util/State.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.os.Message;
+
+/**
+ * {@hide}
+ *
+ * The class for implementing states in a StateMachine
+ */
+public class State implements IState {
+
+ /**
+ * Constructor
+ */
+ protected State() {
+ }
+
+ /* (non-Javadoc)
+ * @see com.android.internal.util.IState#enter()
+ */
+ @Override
+ public void enter() {
+ }
+
+ /* (non-Javadoc)
+ * @see com.android.internal.util.IState#exit()
+ */
+ @Override
+ public void exit() {
+ }
+
+ /* (non-Javadoc)
+ * @see com.android.internal.util.IState#processMessage(android.os.Message)
+ */
+ @Override
+ public boolean processMessage(Message msg) {
+ return false;
+ }
+
+ /**
+ * Name of State for debugging purposes.
+ *
+ * This default implementation returns the class name, returning
+ * the instance name would better in cases where a State class
+ * is used for multiple states. But normally there is one class per
+ * state and the class name is sufficient and easy to get. You may
+ * want to provide a setName or some other mechanism for setting
+ * another name if the class name is not appropriate.
+ *
+ * @see com.android.internal.util.IState#processMessage(android.os.Message)
+ */
+ @Override
+ public String getName() {
+ String name = getClass().getName();
+ int lastDollar = name.lastIndexOf('$');
+ return name.substring(lastDollar + 1);
+ }
+}
diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/StateMachine.java
similarity index 76%
rename from core/java/com/android/internal/util/HierarchicalStateMachine.java
rename to core/java/com/android/internal/util/StateMachine.java
index f43f459..cbe72dd 100644
--- a/core/java/com/android/internal/util/HierarchicalStateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -24,14 +24,15 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Vector;
/**
* {@hide}
*
- * <p>A hierarchical state machine is a state machine which processes messages
+ * <p>The state machine defined here is a hierarchical state machine which processes messages
* and can have states arranged hierarchically.</p>
*
- * <p>A state is a <code>HierarchicalState</code> object and must implement
+ * <p>A state is a <code>State</code> object and must implement
* <code>processMessage</code> and optionally <code>enter/exit/getName</code>.
* The enter/exit methods are equivalent to the construction and destruction
* in Object Oriented programming and are used to perform initialization and
@@ -75,7 +76,7 @@
* will exit the current state and its parent and then exit from the controlling thread
* and no further messages will be processed.</p>
*
- * <p>In addition to <code>processMessage</code> each <code>HierarchicalState</code> has
+ * <p>In addition to <code>processMessage</code> each <code>State</code> has
* an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p>
*
* <p>Since the states are arranged in a hierarchy transitioning to a new state
@@ -121,11 +122,11 @@
* mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So
* when the next message is received mS4.processMessage will be invoked.</p>
*
- * <p>Now for some concrete examples, here is the canonical HelloWorld as an HSM.
+ * <p>Now for some concrete examples, here is the canonical HelloWorld as a state machine.
* It responds with "Hello World" being printed to the log for every message.</p>
<code>
-class HelloWorld extends HierarchicalStateMachine {
- Hsm1(String name) {
+class HelloWorld extends StateMachine {
+ HelloWorld(String name) {
super(name);
addState(mState1);
setInitialState(mState1);
@@ -137,7 +138,7 @@
return hw;
}
- class State1 extends HierarchicalState {
+ class State1 extends State {
@Override public boolean processMessage(Message message) {
Log.d(TAG, "Hello World");
return HANDLED;
@@ -220,9 +221,9 @@
}
}
</code>
- * <p>The implementation is below and also in HierarchicalStateMachineTest:</p>
+ * <p>The implementation is below and also in StateMachineTest:</p>
<code>
-class Hsm1 extends HierarchicalStateMachine {
+class Hsm1 extends StateMachine {
private static final String TAG = "hsm1";
public static final int CMD_1 = 1;
@@ -254,7 +255,7 @@
Log.d(TAG, "ctor X");
}
- class P1 extends HierarchicalState {
+ class P1 extends State {
@Override public void enter() {
Log.d(TAG, "mP1.enter");
}
@@ -281,7 +282,7 @@
}
}
- class S1 extends HierarchicalState {
+ class S1 extends State {
@Override public void enter() {
Log.d(TAG, "mS1.enter");
}
@@ -301,7 +302,7 @@
}
}
- class S2 extends HierarchicalState {
+ class S2 extends State {
@Override public void enter() {
Log.d(TAG, "mS2.enter");
}
@@ -329,7 +330,7 @@
}
}
- class P2 extends HierarchicalState {
+ class P2 extends State {
@Override public void enter() {
Log.d(TAG, "mP2.enter");
sendMessage(obtainMessage(CMD_5));
@@ -408,16 +409,16 @@
D/hsm1 ( 1999): halting
</code>
*/
-public class HierarchicalStateMachine {
+public class StateMachine {
- private static final String TAG = "HierarchicalStateMachine";
+ private static final String TAG = "StateMachine";
private String mName;
/** Message.what value when quitting */
- public static final int HSM_QUIT_CMD = -1;
+ public static final int SM_QUIT_CMD = -1;
/** Message.what value when initializing */
- public static final int HSM_INIT_CMD = -1;
+ public static final int SM_INIT_CMD = -1;
/**
* Convenience constant that maybe returned by processMessage
@@ -433,7 +434,181 @@
*/
public static final boolean NOT_HANDLED = false;
- private static class HsmHandler extends Handler {
+ /**
+ * {@hide}
+ *
+ * The information maintained for a processed message.
+ */
+ public static class ProcessedMessageInfo {
+ private int what;
+ private State state;
+ private State orgState;
+
+ /**
+ * Constructor
+ * @param message
+ * @param state that handled the message
+ * @param orgState is the first state the received the message but
+ * did not processes the message.
+ */
+ ProcessedMessageInfo(Message message, State state, State orgState) {
+ update(message, state, orgState);
+ }
+
+ /**
+ * Update the information in the record.
+ * @param state that handled the message
+ * @param orgState is the first state the received the message but
+ * did not processes the message.
+ */
+ public void update(Message message, State state, State orgState) {
+ this.what = message.what;
+ this.state = state;
+ this.orgState = orgState;
+ }
+
+ /**
+ * @return the command that was executing
+ */
+ public int getWhat() {
+ return what;
+ }
+
+ /**
+ * @return the state that handled this message
+ */
+ public State getState() {
+ return state;
+ }
+
+ /**
+ * @return the original state that received the message.
+ */
+ public State getOriginalState() {
+ return orgState;
+ }
+
+ /**
+ * @return as string
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("what=");
+ sb.append(what);
+ sb.append(" state=");
+ sb.append(cn(state));
+ sb.append(" orgState=");
+ sb.append(cn(orgState));
+ return sb.toString();
+ }
+
+ /**
+ * @return an objects class name
+ */
+ private String cn(Object n) {
+ if (n == null) {
+ return "null";
+ } else {
+ String name = n.getClass().getName();
+ int lastDollar = name.lastIndexOf('$');
+ return name.substring(lastDollar + 1);
+ }
+ }
+ }
+
+ /**
+ * A list of messages recently processed by the state machine.
+ *
+ * The class maintains a list of messages that have been most
+ * recently processed. The list is finite and may be set in the
+ * constructor or by calling setSize. The public interface also
+ * includes size which returns the number of recent messages,
+ * count which is the number of message processed since the
+ * the last setSize, get which returns a processed message and
+ * add which adds a processed messaged.
+ */
+ private static class ProcessedMessages {
+
+ private static final int DEFAULT_SIZE = 20;
+
+ private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>();
+ private int mMaxSize = DEFAULT_SIZE;
+ private int mOldestIndex = 0;
+ private int mCount = 0;
+
+ /**
+ * Constructor
+ */
+ ProcessedMessages() {
+ }
+
+ /**
+ * Set size of messages to maintain and clears all current messages.
+ *
+ * @param maxSize number of messages to maintain at anyone time.
+ */
+ void setSize(int maxSize) {
+ mMaxSize = maxSize;
+ mCount = 0;
+ mMessages.clear();
+ }
+
+ /**
+ * @return the number of recent messages.
+ */
+ int size() {
+ return mMessages.size();
+ }
+
+ /**
+ * @return the total number of messages processed since size was set.
+ */
+ int count() {
+ return mCount;
+ }
+
+ /**
+ * @return the information on a particular record. 0 is the oldest
+ * record and size()-1 is the newest record. If the index is to
+ * large null is returned.
+ */
+ ProcessedMessageInfo get(int index) {
+ int nextIndex = mOldestIndex + index;
+ if (nextIndex >= mMaxSize) {
+ nextIndex -= mMaxSize;
+ }
+ if (nextIndex >= size()) {
+ return null;
+ } else {
+ return mMessages.get(nextIndex);
+ }
+ }
+
+ /**
+ * Add a processed message.
+ *
+ * @param message
+ * @param state that handled the message
+ * @param orgState is the first state the received the message but
+ * did not processes the message.
+ */
+ void add(Message message, State state, State orgState) {
+ mCount += 1;
+ if (mMessages.size() < mMaxSize) {
+ mMessages.add(new ProcessedMessageInfo(message, state, orgState));
+ } else {
+ ProcessedMessageInfo pmi = mMessages.get(mOldestIndex);
+ mOldestIndex += 1;
+ if (mOldestIndex >= mMaxSize) {
+ mOldestIndex = 0;
+ }
+ pmi.update(message, state, orgState);
+ }
+ }
+ }
+
+ private static class SmHandler extends Handler {
/** The debug flag */
private boolean mDbg = false;
@@ -441,9 +616,6 @@
/** The quit object */
private static final Object mQuitObj = new Object();
- /** The initialization message */
- private static final Message mInitMsg = null;
-
/** The current message */
private Message mMsg;
@@ -471,8 +643,8 @@
/** State used when state machine is quitting */
private QuittingState mQuittingState = new QuittingState();
- /** Reference to the HierarchicalStateMachine */
- private HierarchicalStateMachine mHsm;
+ /** Reference to the StateMachine */
+ private StateMachine mSm;
/**
* Information about a state.
@@ -480,7 +652,7 @@
*/
private class StateInfo {
/** The state */
- HierarchicalState state;
+ State state;
/** The parent of this state, null if there is no parent */
StateInfo parentStateInfo;
@@ -500,14 +672,14 @@
}
/** The map of all of the states in the state machine */
- private HashMap<HierarchicalState, StateInfo> mStateInfo =
- new HashMap<HierarchicalState, StateInfo>();
+ private HashMap<State, StateInfo> mStateInfo =
+ new HashMap<State, StateInfo>();
/** The initial state that will process the first message */
- private HierarchicalState mInitialState;
+ private State mInitialState;
/** The destination state when transitionTo has been invoked */
- private HierarchicalState mDestState;
+ private State mDestState;
/** The list of deferred messages */
private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
@@ -515,10 +687,10 @@
/**
* State entered when transitionToHaltingState is called.
*/
- private class HaltingState extends HierarchicalState {
+ private class HaltingState extends State {
@Override
public boolean processMessage(Message msg) {
- mHsm.haltedProcessMessage(msg);
+ mSm.haltedProcessMessage(msg);
return true;
}
}
@@ -526,7 +698,7 @@
/**
* State entered when a valid quit message is handled.
*/
- private class QuittingState extends HierarchicalState {
+ private class QuittingState extends State {
@Override
public boolean processMessage(Message msg) {
return NOT_HANDLED;
@@ -573,7 +745,7 @@
* the appropriate states. We loop on this to allow
* enter and exit methods to use transitionTo.
*/
- HierarchicalState destState = null;
+ State destState = null;
while (mDestState != null) {
if (mDbg) Log.d(TAG, "handleMessage: new destination call exit");
@@ -613,10 +785,11 @@
/**
* We are quitting so ignore all messages.
*/
- mHsm.quitting();
- if (mHsm.mHsmThread != null) {
- // If we made the thread then quit looper
+ mSm.quitting();
+ if (mSm.mSmThread != null) {
+ // If we made the thread then quit looper which stops the thread.
getLooper().quit();
+ mSm.mSmThread = null;
}
} else if (destState == mHaltingState) {
/**
@@ -624,7 +797,7 @@
* state. All subsequent messages will be processed in
* in the halting state which invokes haltedProcessMessage(msg);
*/
- mHsm.halting();
+ mSm.halting();
}
}
}
@@ -660,7 +833,7 @@
* starting at the first entry.
*/
mIsConstructionCompleted = true;
- mMsg = obtainMessage(HSM_INIT_CMD);
+ mMsg = obtainMessage(SM_INIT_CMD);
invokeEnterMethods(0);
/**
@@ -690,7 +863,7 @@
/**
* No parents left so it's not handled
*/
- mHsm.unhandledMessage(msg);
+ mSm.unhandledMessage(msg);
if (isQuit(msg)) {
transitionTo(mQuittingState);
}
@@ -705,7 +878,7 @@
* Record that we processed the message
*/
if (curStateInfo != null) {
- HierarchicalState orgState = mStateStack[mStateStackTopIndex].state;
+ State orgState = mStateStack[mStateStackTopIndex].state;
mProcessedMessages.add(msg, curStateInfo.state, orgState);
} else {
mProcessedMessages.add(msg, null, null);
@@ -719,7 +892,7 @@
private final void invokeExitMethods(StateInfo commonStateInfo) {
while ((mStateStackTopIndex >= 0) &&
(mStateStack[mStateStackTopIndex] != commonStateInfo)) {
- HierarchicalState curState = mStateStack[mStateStackTopIndex].state;
+ State curState = mStateStack[mStateStackTopIndex].state;
if (mDbg) Log.d(TAG, "invokeExitMethods: " + curState.getName());
curState.exit();
mStateStack[mStateStackTopIndex].active = false;
@@ -761,7 +934,7 @@
* reversing the order of the items on the temporary stack as
* they are moved.
*
- * @return index into mStateState where entering needs to start
+ * @return index into mStateStack where entering needs to start
*/
private final int moveTempStateStackToStateStack() {
int startingIndex = mStateStackTopIndex + 1;
@@ -794,7 +967,7 @@
* @return StateInfo of the common ancestor for the destState and
* current state or null if there is no common parent.
*/
- private final StateInfo setupTempStateStackWithStatesToEnter(HierarchicalState destState) {
+ private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
/**
* Search up the parent list of the destination state for an active
* state. Use a do while() loop as the destState must always be entered
@@ -846,7 +1019,7 @@
/**
* @return current state
*/
- private final HierarchicalState getCurrentState() {
+ private final IState getCurrentState() {
return mStateStack[mStateStackTopIndex].state;
}
@@ -859,7 +1032,7 @@
* @param parent the parent of state
* @return stateInfo for this state
*/
- private final StateInfo addState(HierarchicalState state, HierarchicalState parent) {
+ private final StateInfo addState(State state, State parent) {
if (mDbg) {
Log.d(TAG, "addStateInternal: E state=" + state.getName()
+ ",parent=" + ((parent == null) ? "" : parent.getName()));
@@ -894,29 +1067,29 @@
* Constructor
*
* @param looper for dispatching messages
- * @param hsm the hierarchical state machine
+ * @param sm the hierarchical state machine
*/
- private HsmHandler(Looper looper, HierarchicalStateMachine hsm) {
+ private SmHandler(Looper looper, StateMachine sm) {
super(looper);
- mHsm = hsm;
+ mSm = sm;
addState(mHaltingState, null);
addState(mQuittingState, null);
}
- /** @see HierarchicalStateMachine#setInitialState(HierarchicalState) */
- private final void setInitialState(HierarchicalState initialState) {
+ /** @see StateMachine#setInitialState(State) */
+ private final void setInitialState(State initialState) {
if (mDbg) Log.d(TAG, "setInitialState: initialState" + initialState.getName());
mInitialState = initialState;
}
- /** @see HierarchicalStateMachine#transitionTo(HierarchicalState) */
- private final void transitionTo(HierarchicalState destState) {
- if (mDbg) Log.d(TAG, "StateMachine.transitionTo EX destState" + destState.getName());
- mDestState = destState;
+ /** @see StateMachine#transitionTo(IState) */
+ private final void transitionTo(IState destState) {
+ mDestState = (State) destState;
+ if (mDbg) Log.d(TAG, "StateMachine.transitionTo EX destState" + mDestState.getName());
}
- /** @see HierarchicalStateMachine#deferMessage(Message) */
+ /** @see StateMachine#deferMessage(Message) */
private final void deferMessage(Message msg) {
if (mDbg) Log.d(TAG, "deferMessage: msg=" + msg.what);
@@ -927,51 +1100,51 @@
mDeferredMessages.add(newMsg);
}
- /** @see HierarchicalStateMachine#deferMessage(Message) */
+ /** @see StateMachine#deferMessage(Message) */
private final void quit() {
if (mDbg) Log.d(TAG, "quit:");
- sendMessage(obtainMessage(HSM_QUIT_CMD, mQuitObj));
+ sendMessage(obtainMessage(SM_QUIT_CMD, mQuitObj));
}
- /** @see HierarchicalStateMachine#isQuit(Message) */
+ /** @see StateMachine#isQuit(Message) */
private final boolean isQuit(Message msg) {
- return (msg.what == HSM_QUIT_CMD) && (msg.obj == mQuitObj);
+ return (msg.what == SM_QUIT_CMD) && (msg.obj == mQuitObj);
}
- /** @see HierarchicalStateMachine#isDbg() */
+ /** @see StateMachine#isDbg() */
private final boolean isDbg() {
return mDbg;
}
- /** @see HierarchicalStateMachine#setDbg(boolean) */
+ /** @see StateMachine#setDbg(boolean) */
private final void setDbg(boolean dbg) {
mDbg = dbg;
}
- /** @see HierarchicalStateMachine#setProcessedMessagesSize(int) */
+ /** @see StateMachine#setProcessedMessagesSize(int) */
private final void setProcessedMessagesSize(int maxSize) {
mProcessedMessages.setSize(maxSize);
}
- /** @see HierarchicalStateMachine#getProcessedMessagesSize() */
+ /** @see StateMachine#getProcessedMessagesSize() */
private final int getProcessedMessagesSize() {
return mProcessedMessages.size();
}
- /** @see HierarchicalStateMachine#getProcessedMessagesCount() */
+ /** @see StateMachine#getProcessedMessagesCount() */
private final int getProcessedMessagesCount() {
return mProcessedMessages.count();
}
- /** @see HierarchicalStateMachine#getProcessedMessage(int) */
- private final ProcessedMessages.Info getProcessedMessage(int index) {
+ /** @see StateMachine#getProcessedMessageInfo(int) */
+ private final ProcessedMessageInfo getProcessedMessageInfo(int index) {
return mProcessedMessages.get(index);
}
}
- private HsmHandler mHsmHandler;
- private HandlerThread mHsmThread;
+ private SmHandler mSmHandler;
+ private HandlerThread mSmThread;
/**
* Initialize.
@@ -981,28 +1154,28 @@
*/
private void initStateMachine(String name, Looper looper) {
mName = name;
- mHsmHandler = new HsmHandler(looper, this);
+ mSmHandler = new SmHandler(looper, this);
}
/**
- * Constructor creates an HSM with its own thread.
+ * Constructor creates a StateMachine with its own thread.
*
* @param name of the state machine
*/
- protected HierarchicalStateMachine(String name) {
- mHsmThread = new HandlerThread(name);
- mHsmThread.start();
- Looper looper = mHsmThread.getLooper();
+ protected StateMachine(String name) {
+ mSmThread = new HandlerThread(name);
+ mSmThread.start();
+ Looper looper = mSmThread.getLooper();
initStateMachine(name, looper);
}
/**
- * Constructor creates an HSMStateMachine using the looper.
+ * Constructor creates an StateMachine using the looper.
*
* @param name of the state machine
*/
- protected HierarchicalStateMachine(String name, Looper looper) {
+ protected StateMachine(String name, Looper looper) {
initStateMachine(name, looper);
}
@@ -1011,30 +1184,30 @@
* @param state the state to add
* @param parent the parent of state
*/
- protected final void addState(HierarchicalState state, HierarchicalState parent) {
- mHsmHandler.addState(state, parent);
+ protected final void addState(State state, State parent) {
+ mSmHandler.addState(state, parent);
}
/**
* @return current message
*/
protected final Message getCurrentMessage() {
- return mHsmHandler.getCurrentMessage();
+ return mSmHandler.getCurrentMessage();
}
/**
* @return current state
*/
- protected final HierarchicalState getCurrentState() {
- return mHsmHandler.getCurrentState();
+ protected final IState getCurrentState() {
+ return mSmHandler.getCurrentState();
}
/**
* Add a new state to the state machine, parent will be null
* @param state to add
*/
- protected final void addState(HierarchicalState state) {
- mHsmHandler.addState(state, null);
+ protected final void addState(State state) {
+ mSmHandler.addState(state, null);
}
/**
@@ -1043,8 +1216,8 @@
*
* @param initialState is the state which will receive the first message.
*/
- protected final void setInitialState(HierarchicalState initialState) {
- mHsmHandler.setInitialState(initialState);
+ protected final void setInitialState(State initialState) {
+ mSmHandler.setInitialState(initialState);
}
/**
@@ -1055,8 +1228,8 @@
*
* @param destState will be the state that receives the next message.
*/
- protected final void transitionTo(HierarchicalState destState) {
- mHsmHandler.transitionTo(destState);
+ protected final void transitionTo(IState destState) {
+ mSmHandler.transitionTo(destState);
}
/**
@@ -1067,7 +1240,7 @@
* will be called.
*/
protected final void transitionToHaltingState() {
- mHsmHandler.transitionTo(mHsmHandler.mHaltingState);
+ mSmHandler.transitionTo(mSmHandler.mHaltingState);
}
/**
@@ -1080,7 +1253,7 @@
* @param msg is deferred until the next transition.
*/
protected final void deferMessage(Message msg) {
- mHsmHandler.deferMessage(msg);
+ mSmHandler.deferMessage(msg);
}
@@ -1090,9 +1263,7 @@
* @param msg that couldn't be handled.
*/
protected void unhandledMessage(Message msg) {
- if (false) {
- Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
- }
+ if (mSmHandler.mDbg) Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
}
/**
@@ -1103,16 +1274,18 @@
}
/**
- * Called after the message that called transitionToHalting
- * is called and should be overridden by StateMachine's that
- * call transitionToHalting.
+ * This will be called once after handling a message that called
+ * transitionToHalting. All subsequent messages will invoke
+ * {@link StateMachine#haltedProcessMessage(Message)}
*/
protected void halting() {
}
/**
- * Called after the quitting message was NOT handled and
- * just before the quit actually occurs.
+ * This will be called once after a quit message that was NOT handled by
+ * the derived StateMachine. The StateMachine will stop and any subsequent messages will be
+ * ignored. In addition, if this StateMachine created the thread, the thread will
+ * be stopped after this method returns.
*/
protected void quitting() {
}
@@ -1130,35 +1303,35 @@
* @param maxSize number of messages to maintain at anyone time.
*/
public final void setProcessedMessagesSize(int maxSize) {
- mHsmHandler.setProcessedMessagesSize(maxSize);
+ mSmHandler.setProcessedMessagesSize(maxSize);
}
/**
* @return number of messages processed
*/
public final int getProcessedMessagesSize() {
- return mHsmHandler.getProcessedMessagesSize();
+ return mSmHandler.getProcessedMessagesSize();
}
/**
* @return the total number of messages processed
*/
public final int getProcessedMessagesCount() {
- return mHsmHandler.getProcessedMessagesCount();
+ return mSmHandler.getProcessedMessagesCount();
}
/**
- * @return a processed message
+ * @return a processed message information
*/
- public final ProcessedMessages.Info getProcessedMessage(int index) {
- return mHsmHandler.getProcessedMessage(index);
+ public final ProcessedMessageInfo getProcessedMessageInfo(int index) {
+ return mSmHandler.getProcessedMessageInfo(index);
}
/**
* @return Handler
*/
public final Handler getHandler() {
- return mHsmHandler;
+ return mSmHandler;
}
/**
@@ -1168,7 +1341,7 @@
*/
public final Message obtainMessage()
{
- return Message.obtain(mHsmHandler);
+ return Message.obtain(mSmHandler);
}
/**
@@ -1178,7 +1351,7 @@
* @return message
*/
public final Message obtainMessage(int what) {
- return Message.obtain(mHsmHandler, what);
+ return Message.obtain(mSmHandler, what);
}
/**
@@ -1191,7 +1364,7 @@
*/
public final Message obtainMessage(int what, Object obj)
{
- return Message.obtain(mHsmHandler, what, obj);
+ return Message.obtain(mSmHandler, what, obj);
}
/**
@@ -1205,7 +1378,7 @@
*/
public final Message obtainMessage(int what, int arg1, int arg2)
{
- return Message.obtain(mHsmHandler, what, arg1, arg2);
+ return Message.obtain(mSmHandler, what, arg1, arg2);
}
/**
@@ -1220,107 +1393,107 @@
*/
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
{
- return Message.obtain(mHsmHandler, what, arg1, arg2, obj);
+ return Message.obtain(mSmHandler, what, arg1, arg2, obj);
}
/**
* Enqueue a message to this state machine.
*/
public final void sendMessage(int what) {
- mHsmHandler.sendMessage(obtainMessage(what));
+ mSmHandler.sendMessage(obtainMessage(what));
}
/**
* Enqueue a message to this state machine.
*/
public final void sendMessage(int what, Object obj) {
- mHsmHandler.sendMessage(obtainMessage(what,obj));
+ mSmHandler.sendMessage(obtainMessage(what,obj));
}
/**
* Enqueue a message to this state machine.
*/
public final void sendMessage(Message msg) {
- mHsmHandler.sendMessage(msg);
+ mSmHandler.sendMessage(msg);
}
/**
* Enqueue a message to this state machine after a delay.
*/
public final void sendMessageDelayed(int what, long delayMillis) {
- mHsmHandler.sendMessageDelayed(obtainMessage(what), delayMillis);
+ mSmHandler.sendMessageDelayed(obtainMessage(what), delayMillis);
}
/**
* Enqueue a message to this state machine after a delay.
*/
public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
- mHsmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
+ mSmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
}
/**
* Enqueue a message to this state machine after a delay.
*/
public final void sendMessageDelayed(Message msg, long delayMillis) {
- mHsmHandler.sendMessageDelayed(msg, delayMillis);
+ mSmHandler.sendMessageDelayed(msg, delayMillis);
}
/**
* Enqueue a message to the front of the queue for this state machine.
- * Protected, may only be called by instances of HierarchicalStateMachine.
+ * Protected, may only be called by instances of StateMachine.
*/
protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
- mHsmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
+ mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
}
/**
* Enqueue a message to the front of the queue for this state machine.
- * Protected, may only be called by instances of HierarchicalStateMachine.
+ * Protected, may only be called by instances of StateMachine.
*/
protected final void sendMessageAtFrontOfQueue(int what) {
- mHsmHandler.sendMessageAtFrontOfQueue(obtainMessage(what));
+ mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what));
}
/**
* Enqueue a message to the front of the queue for this state machine.
- * Protected, may only be called by instances of HierarchicalStateMachine.
+ * Protected, may only be called by instances of StateMachine.
*/
protected final void sendMessageAtFrontOfQueue(Message msg) {
- mHsmHandler.sendMessageAtFrontOfQueue(msg);
+ mSmHandler.sendMessageAtFrontOfQueue(msg);
}
/**
* Removes a message from the message queue.
- * Protected, may only be called by instances of HierarchicalStateMachine.
+ * Protected, may only be called by instances of StateMachine.
*/
protected final void removeMessages(int what) {
- mHsmHandler.removeMessages(what);
+ mSmHandler.removeMessages(what);
}
/**
* Conditionally quit the looper and stop execution.
*
- * This sends the HSM_QUIT_MSG to the state machine and
+ * This sends the SM_QUIT_MSG to the state machine and
* if not handled by any state's processMessage then the
* state machine will be stopped and no further messages
* will be processed.
*/
public final void quit() {
- mHsmHandler.quit();
+ mSmHandler.quit();
}
/**
* @return ture if msg is quit
*/
protected final boolean isQuit(Message msg) {
- return mHsmHandler.isQuit(msg);
+ return mSmHandler.isQuit(msg);
}
/**
* @return if debugging is enabled
*/
public boolean isDbg() {
- return mHsmHandler.isDbg();
+ return mSmHandler.isDbg();
}
/**
@@ -1329,7 +1502,7 @@
* @param dbg is true to enable debugging.
*/
public void setDbg(boolean dbg) {
- mHsmHandler.setDbg(dbg);
+ mSmHandler.setDbg(dbg);
}
/**
@@ -1337,6 +1510,6 @@
*/
public void start() {
/** Send the complete construction message */
- mHsmHandler.completeConstruction();
+ mSmHandler.completeConstruction();
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 0dc0422..c3f6329 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -33,7 +33,9 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import android.view.View;
import android.widget.Button;
+import android.widget.TextView;
import java.io.File;
import java.io.FileNotFoundException;
@@ -775,6 +777,16 @@
setBoolean(LOCKOUT_PERMANENT_KEY, locked);
}
+ public boolean isEmergencyCallCapable() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_voice_capable);
+ }
+
+ public boolean isPukUnlockScreenEnable() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enable_puk_unlock_screen);
+ }
+
/**
* @return A formatted string of the next alarm (for showing on the lock screen),
* or null if there is no next alarm.
@@ -827,11 +839,22 @@
}
/**
- * Sets the text on the emergency button to indicate what action will be taken.
+ * Sets the emergency button visibility based on isEmergencyCallCapable().
+ *
+ * If the emergency button is visible, sets the text on the emergency button
+ * to indicate what action will be taken.
+ *
* If there's currently a call in progress, the button will take them to the call
* @param button the button to update
*/
public void updateEmergencyCallButtonState(Button button) {
+ if (isEmergencyCallCapable()) {
+ button.setVisibility(View.VISIBLE);
+ } else {
+ button.setVisibility(View.GONE);
+ return;
+ }
+
int newState = TelephonyManager.getDefault().getCallState();
int textId;
if (newState == TelephonyManager.CALL_STATE_OFFHOOK) {
@@ -848,6 +871,18 @@
}
/**
+ * Sets the visibility of emergency call prompt based on emergency capable
+ * @param emergencyText the emergency call text to be updated
+ */
+ public void updateEmergencyCallText(TextView emergencyText) {
+ if (isEmergencyCallCapable()) {
+ emergencyText.setVisibility(View.VISIBLE);
+ } else {
+ emergencyText.setVisibility(View.GONE);
+ }
+ }
+
+ /**
* Resumes a call in progress. Typically launched from the EmergencyCall button
* on various lockscreens.
*
diff --git a/core/java/com/google/android/mms/pdu/PduParser.java b/core/java/com/google/android/mms/pdu/PduParser.java
old mode 100644
new mode 100755
index 8edfe52..3f185aa
--- a/core/java/com/google/android/mms/pdu/PduParser.java
+++ b/core/java/com/google/android/mms/pdu/PduParser.java
@@ -29,6 +29,8 @@
import java.util.Arrays;
import java.util.HashMap;
+import android.content.res.Resources;
+
public class PduParser {
/**
* The next are WAP values defined in WSP specification.
@@ -1557,43 +1559,55 @@
* Attachment = <Octet 129>
* Inline = <Octet 130>
*/
- int len = parseValueLength(pduDataStream);
- pduDataStream.mark(1);
- int thisStartPos = pduDataStream.available();
- int thisEndPos = 0;
- int value = pduDataStream.read();
- if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
- part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
- } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
- part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
- } else if (value == PduPart.P_DISPOSITION_INLINE) {
- part.setContentDisposition(PduPart.DISPOSITION_INLINE);
- } else {
- pduDataStream.reset();
- /* Token-text */
- part.setContentDisposition(parseWapString(pduDataStream, TYPE_TEXT_STRING));
- }
+ /*
+ * some carrier mmsc servers do not support content_disposition
+ * field correctly
+ */
+ boolean contentDisposition = Resources.getSystem().getBoolean(com
+ .android.internal.R.bool.config_mms_content_disposition_support);
- /* get filename parameter and skip other parameters */
- thisEndPos = pduDataStream.available();
- if (thisStartPos - thisEndPos < len) {
- value = pduDataStream.read();
- if (value == PduPart.P_FILENAME) { //filename is text-string
- part.setFilename(parseWapString(pduDataStream, TYPE_TEXT_STRING));
+ if (contentDisposition) {
+ int len = parseValueLength(pduDataStream);
+ pduDataStream.mark(1);
+ int thisStartPos = pduDataStream.available();
+ int thisEndPos = 0;
+ int value = pduDataStream.read();
+
+ if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
+ part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
+ } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
+ part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
+ } else if (value == PduPart.P_DISPOSITION_INLINE) {
+ part.setContentDisposition(PduPart.DISPOSITION_INLINE);
+ } else {
+ pduDataStream.reset();
+ /* Token-text */
+ part.setContentDisposition(parseWapString(pduDataStream
+ , TYPE_TEXT_STRING));
}
- /* skip other parameters */
+ /* get filename parameter and skip other parameters */
thisEndPos = pduDataStream.available();
if (thisStartPos - thisEndPos < len) {
- int last = len - (thisStartPos - thisEndPos);
- byte[] temp = new byte[last];
- pduDataStream.read(temp, 0, last);
- }
- }
+ value = pduDataStream.read();
+ if (value == PduPart.P_FILENAME) { //filename is text-string
+ part.setFilename(parseWapString(pduDataStream
+ , TYPE_TEXT_STRING));
+ }
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
+ /* skip other parameters */
+ thisEndPos = pduDataStream.available();
+ if (thisStartPos - thisEndPos < len) {
+ int last = len - (thisStartPos - thisEndPos);
+ byte[] temp = new byte[last];
+ pduDataStream.read(temp, 0, last);
+ }
+ }
+
+ tempPos = pduDataStream.available();
+ lastLen = length - (startPos - tempPos);
+ }
break;
default:
if (LOCAL_LOGV) {
diff --git a/core/java/com/google/android/mms/util/PduCache.java b/core/java/com/google/android/mms/util/PduCache.java
index 7c3fad7..866ca1e 100644
--- a/core/java/com/google/android/mms/util/PduCache.java
+++ b/core/java/com/google/android/mms/util/PduCache.java
@@ -235,7 +235,7 @@
}
private void removeFromMessageBoxes(Uri key, PduCacheEntry entry) {
- HashSet<Uri> msgBox = mThreads.get(entry.getMessageBox());
+ HashSet<Uri> msgBox = mThreads.get(Long.valueOf(entry.getMessageBox()));
if (msgBox != null) {
msgBox.remove(key);
}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 4becad7..68d1b3a 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,10 +26,6 @@
extern "C" {
int ifc_enable(const char *ifname);
int ifc_disable(const char *ifname);
-int ifc_add_route(const char *ifname, const char *destStr, uint32_t prefixLen, const char *gwStr);
-int ifc_remove_host_routes(const char *ifname);
-int ifc_get_default_route(const char *ifname);
-int ifc_remove_default_route(const char *ifname);
int ifc_reset_connections(const char *ifname);
int dhcp_do_request(const char *ifname,
@@ -68,7 +64,6 @@
jclass dhcpInfoInternalClass;
jmethodID constructorId;
jfieldID ipaddress;
- jfieldID gateway;
jfieldID prefixLength;
jfieldID dns1;
jfieldID dns2;
@@ -96,56 +91,6 @@
return (jint)result;
}
-static jint android_net_utils_addRoute(JNIEnv* env, jobject clazz, jstring ifname,
- jstring dst, jint prefixLength, jstring gw)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- const char *dstStr = env->GetStringUTFChars(dst, NULL);
- const char *gwStr = NULL;
- if (gw != NULL) {
- gwStr = env->GetStringUTFChars(gw, NULL);
- }
- result = ::ifc_add_route(nameStr, dstStr, prefixLength, gwStr);
- env->ReleaseStringUTFChars(ifname, nameStr);
- env->ReleaseStringUTFChars(dst, dstStr);
- if (gw != NULL) {
- env->ReleaseStringUTFChars(gw, gwStr);
- }
- return (jint)result;
-}
-
-static jint android_net_utils_removeHostRoutes(JNIEnv* env, jobject clazz, jstring ifname)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- result = ::ifc_remove_host_routes(nameStr);
- env->ReleaseStringUTFChars(ifname, nameStr);
- return (jint)result;
-}
-
-static jint android_net_utils_getDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- result = ::ifc_get_default_route(nameStr);
- env->ReleaseStringUTFChars(ifname, nameStr);
- return (jint)result;
-}
-
-static jint android_net_utils_removeDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- result = ::ifc_remove_default_route(nameStr);
- env->ReleaseStringUTFChars(ifname, nameStr);
- return (jint)result;
-}
-
static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname)
{
int result;
@@ -182,7 +127,30 @@
env->ReleaseStringUTFChars(ifname, nameStr);
if (result == 0 && dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) {
env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
- env->SetObjectField(info, dhcpInfoInternalFieldIds.gateway, env->NewStringUTF(gateway));
+
+ // set the gateway
+ jclass cls = env->FindClass("java/net/InetAddress");
+ jmethodID method = env->GetStaticMethodID(cls, "getByName",
+ "(Ljava/lang/String;)Ljava/net/InetAddress;");
+ jvalue args[1];
+ args[0].l = env->NewStringUTF(gateway);
+ jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);
+
+ if (!env->ExceptionOccurred()) {
+ cls = env->FindClass("android/net/RouteInfo");
+ method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V");
+ args[0].l = inetAddressObject;
+ jobject routeInfoObject = env->NewObjectA(cls, method, args);
+
+ cls = env->FindClass("android/net/DhcpInfoInternal");
+ method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V");
+ args[0].l = routeInfoObject;
+ env->CallVoidMethodA(info, method, args);
+ } else {
+ // if we have an exception (host not found perhaps), just don't add the route
+ env->ExceptionClear();
+ }
+
env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
@@ -239,12 +207,6 @@
{ "enableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_enableInterface },
{ "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface },
- { "addRoute", "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)I",
- (void *)android_net_utils_addRoute },
- { "removeHostRoutes", "(Ljava/lang/String;)I", (void *)android_net_utils_removeHostRoutes },
- { "getDefaultRouteNative", "(Ljava/lang/String;)I",
- (void *)android_net_utils_getDefaultRoute },
- { "removeDefaultRoute", "(Ljava/lang/String;)I", (void *)android_net_utils_removeDefaultRoute },
{ "resetConnections", "(Ljava/lang/String;)I", (void *)android_net_utils_resetConnections },
{ "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcp },
{ "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcpRenew },
@@ -262,7 +224,6 @@
if (dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) {
dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "<init>", "()V");
dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
- dhcpInfoInternalFieldIds.gateway = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "gateway", "Ljava/lang/String;");
dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "prefixLength", "I");
dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index df272a7..eb1c437 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -680,6 +680,15 @@
static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
{
+ // XXX temporary sanity check to debug crashes.
+ int uid = (int)(token>>32);
+ if (uid > 0 && uid < 999) {
+ // In Android currently there are no uids in this range.
+ char buf[128];
+ sprintf(buf, "Restoring bad calling ident: 0x%Lx", token);
+ jniThrowException(env, "java/lang/IllegalStateException", buf);
+ return;
+ }
IPCThreadState::self()->restoreCallingIdentity(token);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 441a3bfe..4d40b57 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -91,10 +91,15 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
+ <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
+ <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
+ <protected-broadcast android:name="com.android.nfc_extras.action.AID_SELECTED" />
+
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
<protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" />
<protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
+
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
<!-- ====================================== -->
@@ -490,6 +495,12 @@
android:label="@string/permlab_hardware_test"
android:description="@string/permdesc_hardware_test" />
+ <!-- Allows access to configure network interfaces, configure/use IPSec, etc.
+ @hide -->
+ <permission android:name="android.permission.NET_ADMIN"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature" />
+
<!-- =========================================== -->
<!-- Permissions associated with telephony state -->
<!-- =========================================== -->
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
new file mode 100644
index 0000000..d58fb23
--- /dev/null
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/background_dark"
+ >
+
+ <LinearLayout android:id="@+id/topDisplayGroup"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- header text ('Enter Puk Code') -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+ <!-- Carrier info -->
+ <TextView android:id="@+id/carrier"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="9dip"
+ android:gravity="center"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginRight="10dip"
+ android:layout_marginLeft="10dip">
+ <TextView android:id="@+id/enter_puk"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:text="@android:string/keyguard_password_enter_puk_prompt"
+ android:textSize="30sp"
+ android:layout_marginBottom="10dip"/>
+ <TextView android:id="@+id/enter_pin"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:text="@android:string/keyguard_password_enter_pin_prompt"
+ android:textSize="30sp"
+ android:layout_marginTop="10dip"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:paddingRight="0dip"
+ android:layout_marginRight="10dip"
+ android:layout_marginLeft="10dip">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginRight="6dip"
+ android:layout_marginLeft="6dip"
+ android:gravity="center_vertical"
+ android:background="@android:drawable/edit_text">
+
+ <!-- displays dots as user enters puk -->
+ <TextView android:id="@+id/pukDisplay"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="1"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ />
+
+ <ImageButton android:id="@+id/pukDel"
+ android:src="@android:drawable/ic_input_delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="-3dip"
+ android:layout_marginBottom="-3dip"
+ />
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginRight="6dip"
+ android:layout_marginLeft="6dip"
+ android:gravity="center_vertical"
+ android:background="@android:drawable/edit_text">
+
+ <!-- displays dots as user enters new pin -->
+ <TextView android:id="@+id/pinDisplay"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="1"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ />
+
+ <ImageButton android:id="@+id/pinDel"
+ android:src="@android:drawable/ic_input_delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="-3dip"
+ android:layout_marginBottom="-3dip"
+ />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip">
+
+ <Button android:id="@+id/ok"
+ android:text="@android:string/ok"
+ android:layout_alignParentBottom="true"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:layout_marginBottom="8dip"
+ android:layout_marginRight="8dip"
+ android:textSize="18sp"
+ />
+
+ <Button android:id="@+id/emergencyCall"
+ android:text="@android:string/lockscreen_emergency_call"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:textSize="18sp"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ />
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
new file mode 100644
index 0000000..5e392ef
--- /dev/null
+++ b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@android:color/background_dark"
+ android:gravity="center_horizontal">
+
+ <LinearLayout android:id="@+id/topDisplayGroup"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- header text ('Enter Puk Code') -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+ <!-- Carrier info -->
+ <TextView android:id="@+id/carrier"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="9dip"
+ android:gravity="center"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginRight="10dip"
+ android:layout_marginLeft="10dip">
+ <TextView android:id="@+id/enter_puk"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:text="@android:string/keyguard_password_enter_puk_prompt"
+ android:textSize="30sp"
+ android:layout_marginBottom="10dip"/>
+ <TextView android:id="@+id/enter_pin"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:text="@android:string/keyguard_password_enter_pin_prompt"
+ android:textSize="30sp"
+ android:layout_marginTop="10dip"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:paddingRight="0dip"
+ android:layout_marginRight="10dip"
+ android:layout_marginLeft="10dip">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginRight="6dip"
+ android:layout_marginLeft="6dip"
+ android:gravity="center_vertical"
+ android:background="@android:drawable/edit_text">
+
+ <!-- displays dots as user enters puk -->
+ <TextView android:id="@+id/pukDisplay"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="1"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ />
+
+ <ImageButton android:id="@+id/pukDel"
+ android:src="@android:drawable/ic_input_delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="-3dip"
+ android:layout_marginBottom="-3dip"
+ />
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginRight="6dip"
+ android:layout_marginLeft="6dip"
+ android:gravity="center_vertical"
+ android:background="@android:drawable/edit_text">
+
+ <!-- displays dots as user enters new pin -->
+ <TextView android:id="@+id/pinDisplay"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="1"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ />
+
+ <ImageButton android:id="@+id/pinDel"
+ android:src="@android:drawable/ic_input_delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="-3dip"
+ android:layout_marginBottom="-3dip"
+ />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <include
+ android:id="@+id/keyPad"
+ layout="@android:layout/twelve_key_entry"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/topDisplayGroup"
+ android:layout_marginTop="10dip"
+ />
+
+ <!-- spacer below keypad -->
+ <View
+ android:id="@+id/spacerBottom"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="6dip"
+ android:layout_above="@id/emergencyCall"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <!-- The emergency button should take the rest of the space and be centered vertically -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <!-- emergency call button -->
+ <Button
+ android:id="@+id/emergencyCall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableLeft="@android:drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ android:text="@android:string/lockscreen_emergency_call"
+ />
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
old mode 100644
new mode 100755
index 5c8b9a1..60f11ce
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -49,6 +49,11 @@
manager will disable alpha trasformation in animations where not
strictly needed. -->
<bool name="config_sf_limitedAlpha">false</bool>
+
+ <!-- Default value used to block data calls if ims is not
+ connected. If you use the ims apn DCT will block
+ any other apn from connecting until ims apn is connected-->
+ <bool name="ImsConnectedDefaultValue">false</bool>
<!-- Flag indicating whether the surface flinger is inefficient
at performing a blur. Used by parts of the UI to turn off
@@ -94,13 +99,20 @@
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
<!-- An Array of "[Connection name],[ConnectivityManager connection type],
- [associated radio-type],[priority] -->
+ [associated radio-type],[priority],[restoral-timer(ms)],[dependencyMet] -->
+ <!-- the 5th element "resore-time" indicates the number of milliseconds to delay
+ before automatically restore the default connection. Set -1 if the connection
+ does not require auto-restore. -->
+ <!-- the 6th element indicates boot-time dependency-met value. -->
<string-array translatable="false" name="networkAttributes">
- <item>"wifi,1,1,1"</item>
- <item>"mobile,0,0,0"</item>
- <item>"mobile_mms,2,0,2"</item>
- <item>"mobile_supl,3,0,2"</item>
- <item>"mobile_hipri,5,0,3"</item>
+ <item>"wifi,1,1,1,-1,true"</item>
+ <item>"mobile,0,0,0,-1,true"</item>
+ <item>"mobile_mms,2,0,2,60000,true"</item>
+ <item>"mobile_supl,3,0,2,60000,true"</item>
+ <item>"mobile_hipri,5,0,3,60000,true"</item>
+ <item>"mobile_fota,10,0,2,60000,true"</item>
+ <item>"mobile_ims,11,0,2,60000,true"</item>
+ <item>"mobile_cbs,12,0,2,60000,true"</item>
</string-array>
<!-- This string array should be overridden by the device to present a list of radio
@@ -357,6 +369,10 @@
<!-- Diable lockscreen rotation by default -->
<bool name="config_enableLockScreenRotation">false</bool>
+ <!-- Diable puk unlockscreen by default.
+ If unlock screen is disabled, the puk should be unlocked through Emergency Dialer -->
+ <bool name="config_enable_puk_unlock_screen">false</bool>
+
<!-- Control the behavior when the user long presses the power button.
0 - Nothing
1 - Recent apps dialog
@@ -531,4 +547,27 @@
<!-- The VoiceMail default value is displayed to my own number if it is true -->
<bool name="config_telephony_use_own_number_for_voicemail">false</bool>
+
+ <!-- If this value is true, Sms encoded as octet is decoded by utf8 decoder.
+ If false, decoded by Latin decoder. -->
+ <bool name="config_sms_utf8_support">false</bool>
+
+ <!-- If this value is true, The mms content-disposition field is supported correctly.
+ If false, Content-disposition fragments are ignored -->
+ <bool name="config_mms_content_disposition_support">true</bool>
+
+ <!-- If this value is true, the carrier supports sms delivery reports.
+ If false, sms delivery reports are not supported and the preference
+ option to enable/disable delivery reports is removed in the Messaging app. -->
+ <bool name="config_sms_delivery_reports_support">true</bool>
+
+ <!-- If this value is true, the carrier supports mms delivery reports.
+ If false, mms delivery reports are not supported and the preference
+ option to enable/disable delivery reports is removed in the Messaging app. -->
+ <bool name="config_mms_delivery_reports_support">true</bool>
+
+ <!-- If this value is true, the carrier supports mms read reports.
+ If false, mms read reports are not supported and the preference
+ option to enable/disable read reports is removed in the Messaging app. -->
+ <bool name="config_mms_read_reports_support">true</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b92bf88..0161e1c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -87,6 +87,8 @@
<string name="mismatchPin">The PINs you entered do not match.</string>
<!-- Displayed when a SIM PIN password is too long or too short. -->
<string name="invalidPin">Type a PIN that is 4 to 8 numbers.</string>
+ <!-- Displayed when a SIM PUK password is too short. -->
+ <string name="invalidPuk">Type a PUK that is 8 numbers or longer.</string>
<!-- Displayed to prompt the user to type the PUK password to unlock
the SIM card. -->
<string name="needPuk">Your SIM card is PUK-locked. Type the PUK code to unlock it.</string>
@@ -1644,6 +1646,15 @@
Displayed in one line in a large font. -->
<string name="keyguard_password_enter_pin_code">Enter PIN code</string>
+ <!-- Instructions telling the user to enter their SIM PUK to unlock the keyguard.
+ Displayed in one line in a large font. -->
+ <string name="keyguard_password_enter_puk_code">Enter PUK and new PIN code</string>
+
+ <!-- Prompt to enter SIM PUK in Edit Text Box in unlock screen -->
+ <string name="keyguard_password_enter_puk_prompt">PUK code</string>
+ <!-- Prompt to enter New SIM PIN in Edit Text Box in unlock screen -->
+ <string name="keyguard_password_enter_pin_prompt">New Pin Code</string>
+
<!-- Displayed as hint in passwordEntry EditText on PasswordUnlockScreen [CHAR LIMIT=30]-->
<string name="keyguard_password_entry_touch_hint"><font size="17">Touch to enter password</font></string>
@@ -1715,6 +1726,8 @@
<string name="lockscreen_missing_sim_message" product="default">No SIM card in phone.</string>
<!-- Shown in the lock screen to ask the user to insert a SIM card. -->
<string name="lockscreen_missing_sim_instructions">Please insert a SIM card.</string>
+ <!-- Shown in the lock screen to ask the user to insert a SIM card when sim is missing or not readable. -->
+ <string name="lockscreen_missing_sim_instructions_long">The SIM card is missing or not readable. Please insert a SIM card.</string>
<!-- Shown in the lock screen when there is emergency calls only mode. -->
<string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string>
@@ -2442,6 +2455,20 @@
<!-- See SMS_DIALOG. This is a button choice to disallow sending the SMSes.. -->
<string name="sms_control_no">Cancel</string>
+ <!-- SIM swap and device reboot Dialog --> <skip />
+ <!-- See SIM_REMOVED_DIALOG. This is the title of that dialog. -->
+ <string name="sim_removed_title">SIM card removed</string>
+ <!-- See SIM_REMOVED_DIALOG. This is the message of that dialog. -->
+ <string name="sim_removed_message">The mobile network will be unavailable until you replace the SIM card.</string>
+ <!-- See SIM_REMOVED_DIALOG. This is the button of that dialog. -->
+ <string name="sim_done_button">Done</string>
+ <!-- See SIM_ADDED_DIALOG. This is the title of that dialog. -->
+ <string name="sim_added_title">SIM card added</string>
+ <!-- See SIM_ADDED_DIALOG. This is the message of that dialog. -->
+ <string name="sim_added_message">You must restart your device to access the mobile network.</string>
+ <!-- See SIM_ADDED_DIALOG. This is the button of that dialog. -->
+ <string name="sim_restart_button">Restart</string>
+
<!-- Date/Time picker dialogs strings -->
<!-- The title of the time picker dialog. [CHAR LIMIT=NONE] -->
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index d22356d..27363e8 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -30,6 +30,7 @@
import android.net.wifi.WifiConfiguration.ProxySettings;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.RouteInfo;
import android.util.Log;
import java.io.InputStream;
@@ -301,7 +302,7 @@
if (!InetAddress.isNumeric(gwAddr)) {
throw new SAXException();
}
- mLinkProperties.addGateway(InetAddress.getByName(gwAddr));
+ mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr)));
} catch (UnknownHostException e) {
throw new SAXException();
}
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
new file mode 100644
index 0000000..e3b6b5f
--- /dev/null
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.LinkProperties;
+import android.net.RouteInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+import java.net.InetAddress;
+
+public class LinkPropertiesTest extends TestCase {
+ private static String ADDRV4 = "75.208.6.1";
+ private static String ADDRV6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
+ private static String DNS1 = "75.208.7.1";
+ private static String DNS2 = "69.78.7.1";
+ private static String GATEWAY1 = "75.208.8.1";
+ private static String GATEWAY2 = "69.78.8.1";
+ private static String NAME = "qmi0";
+
+ @SmallTest
+ public void testEqualsNull() {
+ LinkProperties source = new LinkProperties();
+ LinkProperties target = new LinkProperties();
+
+ assertFalse(source == target);
+ assertTrue(source.equals(target));
+ assertTrue(source.hashCode() == target.hashCode());
+ }
+
+ @SmallTest
+ public void testEqualsSameOrder() {
+ try {
+ LinkProperties source = new LinkProperties();
+ source.setInterfaceName(NAME);
+ // set 2 link addresses
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ // set 2 dnses
+ source.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ source.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ // set 2 gateways
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+
+ LinkProperties target = new LinkProperties();
+
+ // All fields are same
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+
+ assertTrue(source.equals(target));
+ assertTrue(source.hashCode() == target.hashCode());
+
+ target.clear();
+ // change Interface Name
+ target.setInterfaceName("qmi1");
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ assertFalse(source.equals(target));
+
+ target.clear();
+ target.setInterfaceName(NAME);
+ // change link addresses
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ assertFalse(source.equals(target));
+
+ target.clear();
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ // change dnses
+ target.addDns(NetworkUtils.numericToInetAddress("75.208.7.2"));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ assertFalse(source.equals(target));
+
+ target.clear();
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ // change gateway
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ assertFalse(source.equals(target));
+
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ //fail();
+ }
+ }
+
+ @SmallTest
+ public void testEqualsDifferentOrder() {
+ try {
+ LinkProperties source = new LinkProperties();
+ source.setInterfaceName(NAME);
+ // set 2 link addresses
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ // set 2 dnses
+ source.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ source.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ // set 2 gateways
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+
+ LinkProperties target = new LinkProperties();
+ // Exchange order
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+
+ assertTrue(source.equals(target));
+ assertTrue(source.hashCode() == target.hashCode());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @SmallTest
+ public void testEqualsDuplicated() {
+ try {
+ LinkProperties source = new LinkProperties();
+ // set 3 link addresses, eg, [A, A, B]
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ source.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+
+ LinkProperties target = new LinkProperties();
+ // set 3 link addresses, eg, [A, B, B]
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV4), 32));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress(ADDRV6), 128));
+
+ assertTrue(source.equals(target));
+ assertTrue(source.hashCode() == target.hashCode());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java b/core/tests/coretests/src/com/android/internal/util/StateMachineTest.java
similarity index 84%
rename from core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java
rename to core/tests/coretests/src/com/android/internal/util/StateMachineTest.java
index 36666c4..ab6b2b6 100644
--- a/core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/StateMachineTest.java
@@ -22,9 +22,9 @@
import android.os.Message;
import android.os.SystemClock;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
-import com.android.internal.util.ProcessedMessages;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.internal.util.StateMachine.ProcessedMessageInfo;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
@@ -33,9 +33,9 @@
import junit.framework.TestCase;
/**
- * Test for HierarchicalStateMachine.
+ * Test for StateMachine.
*/
-public class HierarchicalStateMachineTest extends TestCase {
+public class StateMachineTest extends TestCase {
private static final int TEST_CMD_1 = 1;
private static final int TEST_CMD_2 = 2;
private static final int TEST_CMD_3 = 3;
@@ -45,12 +45,12 @@
private static final boolean DBG = true;
private static final boolean WAIT_FOR_DEBUGGER = false;
- private static final String TAG = "HierarchicalStateMachineTest";
+ private static final String TAG = "StateMachineTest";
/**
* Tests that we can quit the state machine.
*/
- class StateMachineQuitTest extends HierarchicalStateMachine {
+ class StateMachineQuitTest extends StateMachine {
private int mQuitCount = 0;
StateMachineQuitTest(String name) {
@@ -65,8 +65,9 @@
setInitialState(mS1);
}
- class S1 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class S1 extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (isQuit(message)) {
mQuitCount += 1;
if (mQuitCount > 2) {
@@ -125,22 +126,22 @@
assertTrue(smQuitTest.getProcessedMessagesCount() == 9);
- ProcessedMessages.Info pmi;
+ ProcessedMessageInfo pmi;
// The first two message didn't quit and were handled by mS1
- pmi = smQuitTest.getProcessedMessage(6);
- assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
+ pmi = smQuitTest.getProcessedMessageInfo(6);
+ assertEquals(StateMachine.SM_QUIT_CMD, pmi.getWhat());
assertEquals(smQuitTest.mS1, pmi.getState());
assertEquals(smQuitTest.mS1, pmi.getOriginalState());
- pmi = smQuitTest.getProcessedMessage(7);
- assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
+ pmi = smQuitTest.getProcessedMessageInfo(7);
+ assertEquals(StateMachine.SM_QUIT_CMD, pmi.getWhat());
assertEquals(smQuitTest.mS1, pmi.getState());
assertEquals(smQuitTest.mS1, pmi.getOriginalState());
// The last message was never handled so the states are null
- pmi = smQuitTest.getProcessedMessage(8);
- assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
+ pmi = smQuitTest.getProcessedMessageInfo(8);
+ assertEquals(StateMachine.SM_QUIT_CMD, pmi.getWhat());
assertEquals(null, pmi.getState());
assertEquals(null, pmi.getOriginalState());
@@ -150,7 +151,7 @@
/**
* Test enter/exit can use transitionTo
*/
- class StateMachineEnterExitTransitionToTest extends HierarchicalStateMachine {
+ class StateMachineEnterExitTransitionToTest extends StateMachine {
StateMachineEnterExitTransitionToTest(String name) {
super(name);
mThisSm = this;
@@ -166,34 +167,38 @@
setInitialState(mS1);
}
- class S1 extends HierarchicalState {
- @Override protected void enter() {
+ class S1 extends State {
+ @Override
+ public void enter() {
// Test that message is HSM_INIT_CMD
- assertEquals(HSM_INIT_CMD, getCurrentMessage().what);
+ assertEquals(SM_INIT_CMD, getCurrentMessage().what);
// Test that a transition in enter and the initial state works
mS1EnterCount += 1;
transitionTo(mS2);
Log.d(TAG, "S1.enter");
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
// Test that message is HSM_INIT_CMD
- assertEquals(HSM_INIT_CMD, getCurrentMessage().what);
+ assertEquals(SM_INIT_CMD, getCurrentMessage().what);
mS1ExitCount += 1;
Log.d(TAG, "S1.exit");
}
}
- class S2 extends HierarchicalState {
- @Override protected void enter() {
+ class S2 extends State {
+ @Override
+ public void enter() {
// Test that message is HSM_INIT_CMD
- assertEquals(HSM_INIT_CMD, getCurrentMessage().what);
+ assertEquals(SM_INIT_CMD, getCurrentMessage().what);
mS2EnterCount += 1;
Log.d(TAG, "S2.enter");
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
// Test that message is TEST_CMD_1
assertEquals(TEST_CMD_1, getCurrentMessage().what);
@@ -202,7 +207,8 @@
transitionTo(mS4);
Log.d(TAG, "S2.exit");
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public boolean processMessage(Message message) {
// Start a transition to S3 but it will be
// changed to a transition to S4 in exit
transitionTo(mS3);
@@ -211,28 +217,32 @@
}
}
- class S3 extends HierarchicalState {
- @Override protected void enter() {
+ class S3 extends State {
+ @Override
+ public void enter() {
// Test that we can do halting in an enter/exit
transitionToHaltingState();
mS3EnterCount += 1;
Log.d(TAG, "S3.enter");
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
mS3ExitCount += 1;
Log.d(TAG, "S3.exit");
}
}
- class S4 extends HierarchicalState {
- @Override protected void enter() {
+ class S4 extends State {
+ @Override
+ public void enter() {
// Test that we can do halting in an enter/exit
transitionToHaltingState();
mS4EnterCount += 1;
Log.d(TAG, "S4.enter");
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
mS4ExitCount += 1;
Log.d(TAG, "S4.exit");
}
@@ -285,10 +295,10 @@
assertTrue(smEnterExitTranstionToTest.getProcessedMessagesCount() == 1);
- ProcessedMessages.Info pmi;
+ ProcessedMessageInfo pmi;
// Message should be handled by mS2.
- pmi = smEnterExitTranstionToTest.getProcessedMessage(0);
+ pmi = smEnterExitTranstionToTest.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(smEnterExitTranstionToTest.mS2, pmi.getState());
assertEquals(smEnterExitTranstionToTest.mS2, pmi.getOriginalState());
@@ -310,7 +320,7 @@
/**
* Tests that ProcessedMessage works as a circular buffer.
*/
- class StateMachine0 extends HierarchicalStateMachine {
+ class StateMachine0 extends StateMachine {
StateMachine0(String name) {
super(name);
mThisSm = this;
@@ -324,8 +334,9 @@
setInitialState(mS1);
}
- class S1 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class S1 extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_6) {
transitionToHaltingState();
}
@@ -369,18 +380,18 @@
assertTrue(sm0.getProcessedMessagesCount() == 6);
assertTrue(sm0.getProcessedMessagesSize() == 3);
- ProcessedMessages.Info pmi;
- pmi = sm0.getProcessedMessage(0);
+ ProcessedMessageInfo pmi;
+ pmi = sm0.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_4, pmi.getWhat());
assertEquals(sm0.mS1, pmi.getState());
assertEquals(sm0.mS1, pmi.getOriginalState());
- pmi = sm0.getProcessedMessage(1);
+ pmi = sm0.getProcessedMessageInfo(1);
assertEquals(TEST_CMD_5, pmi.getWhat());
assertEquals(sm0.mS1, pmi.getState());
assertEquals(sm0.mS1, pmi.getOriginalState());
- pmi = sm0.getProcessedMessage(2);
+ pmi = sm0.getProcessedMessageInfo(2);
assertEquals(TEST_CMD_6, pmi.getWhat());
assertEquals(sm0.mS1, pmi.getState());
assertEquals(sm0.mS1, pmi.getOriginalState());
@@ -394,7 +405,7 @@
* in state mS1. With the first message it transitions to
* itself which causes it to be exited and reentered.
*/
- class StateMachine1 extends HierarchicalStateMachine {
+ class StateMachine1 extends StateMachine {
StateMachine1(String name) {
super(name);
mThisSm = this;
@@ -408,12 +419,17 @@
if (DBG) Log.d(TAG, "StateMachine1: ctor X");
}
- class S1 extends HierarchicalState {
- @Override protected void enter() {
+ class S1 extends State {
+ @Override
+ public void enter() {
mEnterCount++;
}
-
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mExitCount++;
+ }
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_1) {
assertEquals(1, mEnterCount);
assertEquals(0, mExitCount);
@@ -425,10 +441,6 @@
}
return HANDLED;
}
-
- @Override protected void exit() {
- mExitCount++;
- }
}
@Override
@@ -469,13 +481,13 @@
assertTrue(sm1.getProcessedMessagesSize() == 2);
- ProcessedMessages.Info pmi;
- pmi = sm1.getProcessedMessage(0);
+ ProcessedMessageInfo pmi;
+ pmi = sm1.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(sm1.mS1, pmi.getState());
assertEquals(sm1.mS1, pmi.getOriginalState());
- pmi = sm1.getProcessedMessage(1);
+ pmi = sm1.getProcessedMessageInfo(1);
assertEquals(TEST_CMD_2, pmi.getWhat());
assertEquals(sm1.mS1, pmi.getState());
assertEquals(sm1.mS1, pmi.getOriginalState());
@@ -493,7 +505,7 @@
* mS2 then receives both of the deferred messages first TEST_CMD_1 and
* then TEST_CMD_2.
*/
- class StateMachine2 extends HierarchicalStateMachine {
+ class StateMachine2 extends StateMachine {
StateMachine2(String name) {
super(name);
mThisSm = this;
@@ -508,26 +520,28 @@
if (DBG) Log.d(TAG, "StateMachine2: ctor X");
}
- class S1 extends HierarchicalState {
- @Override protected void enter() {
+ class S1 extends State {
+ @Override
+ public void enter() {
mDidEnter = true;
}
-
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mDidExit = true;
+ }
+ @Override
+ public boolean processMessage(Message message) {
deferMessage(message);
if (message.what == TEST_CMD_2) {
transitionTo(mS2);
}
return HANDLED;
}
-
- @Override protected void exit() {
- mDidExit = true;
- }
}
- class S2 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class S2 extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_2) {
transitionToHaltingState();
}
@@ -571,20 +585,20 @@
assertTrue(sm2.getProcessedMessagesSize() == 4);
- ProcessedMessages.Info pmi;
- pmi = sm2.getProcessedMessage(0);
+ ProcessedMessageInfo pmi;
+ pmi = sm2.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(sm2.mS1, pmi.getState());
- pmi = sm2.getProcessedMessage(1);
+ pmi = sm2.getProcessedMessageInfo(1);
assertEquals(TEST_CMD_2, pmi.getWhat());
assertEquals(sm2.mS1, pmi.getState());
- pmi = sm2.getProcessedMessage(2);
+ pmi = sm2.getProcessedMessageInfo(2);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(sm2.mS2, pmi.getState());
- pmi = sm2.getProcessedMessage(3);
+ pmi = sm2.getProcessedMessageInfo(3);
assertEquals(TEST_CMD_2, pmi.getWhat());
assertEquals(sm2.mS2, pmi.getState());
@@ -598,7 +612,7 @@
* Test that unhandled messages in a child are handled by the parent.
* When TEST_CMD_2 is received.
*/
- class StateMachine3 extends HierarchicalStateMachine {
+ class StateMachine3 extends StateMachine {
StateMachine3(String name) {
super(name);
mThisSm = this;
@@ -615,8 +629,9 @@
if (DBG) Log.d(TAG, "StateMachine3: ctor X");
}
- class ParentState extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class ParentState extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_2) {
transitionToHaltingState();
}
@@ -624,8 +639,9 @@
}
}
- class ChildState extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class ChildState extends State {
+ @Override
+ public boolean processMessage(Message message) {
return NOT_HANDLED;
}
}
@@ -663,13 +679,13 @@
assertTrue(sm3.getProcessedMessagesSize() == 2);
- ProcessedMessages.Info pmi;
- pmi = sm3.getProcessedMessage(0);
+ ProcessedMessageInfo pmi;
+ pmi = sm3.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(sm3.mParentState, pmi.getState());
assertEquals(sm3.mChildState, pmi.getOriginalState());
- pmi = sm3.getProcessedMessage(1);
+ pmi = sm3.getProcessedMessageInfo(1);
assertEquals(TEST_CMD_2, pmi.getWhat());
assertEquals(sm3.mParentState, pmi.getState());
assertEquals(sm3.mChildState, pmi.getOriginalState());
@@ -682,7 +698,7 @@
* with transition from child 1 to child 2 and child 2
* lets the parent handle the messages.
*/
- class StateMachine4 extends HierarchicalStateMachine {
+ class StateMachine4 extends StateMachine {
StateMachine4(String name) {
super(name);
mThisSm = this;
@@ -700,8 +716,9 @@
if (DBG) Log.d(TAG, "StateMachine4: ctor X");
}
- class ParentState extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class ParentState extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_2) {
transitionToHaltingState();
}
@@ -709,15 +726,17 @@
}
}
- class ChildState1 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class ChildState1 extends State {
+ @Override
+ public boolean processMessage(Message message) {
transitionTo(mChildState2);
return HANDLED;
}
}
- class ChildState2 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class ChildState2 extends State {
+ @Override
+ public boolean processMessage(Message message) {
return NOT_HANDLED;
}
}
@@ -757,13 +776,13 @@
assertTrue(sm4.getProcessedMessagesSize() == 2);
- ProcessedMessages.Info pmi;
- pmi = sm4.getProcessedMessage(0);
+ ProcessedMessageInfo pmi;
+ pmi = sm4.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(sm4.mChildState1, pmi.getState());
assertEquals(sm4.mChildState1, pmi.getOriginalState());
- pmi = sm4.getProcessedMessage(1);
+ pmi = sm4.getProcessedMessageInfo(1);
assertEquals(TEST_CMD_2, pmi.getWhat());
assertEquals(sm4.mParentState, pmi.getState());
assertEquals(sm4.mChildState2, pmi.getOriginalState());
@@ -775,7 +794,7 @@
* Test transition from one child to another of a "complex"
* hierarchy with two parents and multiple children.
*/
- class StateMachine5 extends HierarchicalStateMachine {
+ class StateMachine5 extends StateMachine {
StateMachine5(String name) {
super(name);
mThisSm = this;
@@ -797,23 +816,32 @@
if (DBG) Log.d(TAG, "StateMachine5: ctor X");
}
- class ParentState1 extends HierarchicalState {
- @Override protected void enter() {
+ class ParentState1 extends State {
+ @Override
+ public void enter() {
mParentState1EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
- return HANDLED;
- }
- @Override protected void exit() {
+ @Override
+ public void exit() {
mParentState1ExitCount += 1;
}
+ @Override
+ public boolean processMessage(Message message) {
+ return HANDLED;
+ }
}
- class ChildState1 extends HierarchicalState {
- @Override protected void enter() {
+ class ChildState1 extends State {
+ @Override
+ public void enter() {
mChildState1EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mChildState1ExitCount += 1;
+ }
+ @Override
+ public boolean processMessage(Message message) {
assertEquals(1, mParentState1EnterCount);
assertEquals(0, mParentState1ExitCount);
assertEquals(1, mChildState1EnterCount);
@@ -832,16 +860,19 @@
transitionTo(mChildState2);
return HANDLED;
}
- @Override protected void exit() {
- mChildState1ExitCount += 1;
- }
}
- class ChildState2 extends HierarchicalState {
- @Override protected void enter() {
+ class ChildState2 extends State {
+ @Override
+ public void enter() {
mChildState2EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mChildState2ExitCount += 1;
+ }
+ @Override
+ public boolean processMessage(Message message) {
assertEquals(1, mParentState1EnterCount);
assertEquals(0, mParentState1ExitCount);
assertEquals(1, mChildState1EnterCount);
@@ -860,16 +891,19 @@
transitionTo(mChildState5);
return HANDLED;
}
- @Override protected void exit() {
- mChildState2ExitCount += 1;
- }
}
- class ParentState2 extends HierarchicalState {
- @Override protected void enter() {
+ class ParentState2 extends State {
+ @Override
+ public void enter() {
mParentState2EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mParentState2ExitCount += 1;
+ }
+ @Override
+ public boolean processMessage(Message message) {
assertEquals(1, mParentState1EnterCount);
assertEquals(1, mParentState1ExitCount);
assertEquals(1, mChildState1EnterCount);
@@ -888,16 +922,19 @@
transitionToHaltingState();
return HANDLED;
}
- @Override protected void exit() {
- mParentState2ExitCount += 1;
- }
}
- class ChildState3 extends HierarchicalState {
- @Override protected void enter() {
+ class ChildState3 extends State {
+ @Override
+ public void enter() {
mChildState3EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mChildState3ExitCount += 1;
+ }
+ @Override
+ public boolean processMessage(Message message) {
assertEquals(1, mParentState1EnterCount);
assertEquals(1, mParentState1ExitCount);
assertEquals(1, mChildState1EnterCount);
@@ -916,16 +953,19 @@
transitionTo(mChildState4);
return HANDLED;
}
- @Override protected void exit() {
- mChildState3ExitCount += 1;
- }
}
- class ChildState4 extends HierarchicalState {
- @Override protected void enter() {
+ class ChildState4 extends State {
+ @Override
+ public void enter() {
mChildState4EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mChildState4ExitCount += 1;
+ }
+ @Override
+ public boolean processMessage(Message message) {
assertEquals(1, mParentState1EnterCount);
assertEquals(1, mParentState1ExitCount);
assertEquals(1, mChildState1EnterCount);
@@ -944,16 +984,19 @@
transitionTo(mParentState2);
return HANDLED;
}
- @Override protected void exit() {
- mChildState4ExitCount += 1;
- }
}
- class ChildState5 extends HierarchicalState {
- @Override protected void enter() {
+ class ChildState5 extends State {
+ @Override
+ public void enter() {
mChildState5EnterCount += 1;
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ mChildState5ExitCount += 1;
+ }
+ @Override
+ public boolean processMessage(Message message) {
assertEquals(1, mParentState1EnterCount);
assertEquals(1, mParentState1ExitCount);
assertEquals(1, mChildState1EnterCount);
@@ -972,9 +1015,6 @@
transitionTo(mChildState3);
return HANDLED;
}
- @Override protected void exit() {
- mChildState5ExitCount += 1;
- }
}
@Override
@@ -1050,33 +1090,33 @@
assertEquals(1, sm5.mChildState5EnterCount);
assertEquals(1, sm5.mChildState5ExitCount);
- ProcessedMessages.Info pmi;
- pmi = sm5.getProcessedMessage(0);
+ ProcessedMessageInfo pmi;
+ pmi = sm5.getProcessedMessageInfo(0);
assertEquals(TEST_CMD_1, pmi.getWhat());
assertEquals(sm5.mChildState1, pmi.getState());
assertEquals(sm5.mChildState1, pmi.getOriginalState());
- pmi = sm5.getProcessedMessage(1);
+ pmi = sm5.getProcessedMessageInfo(1);
assertEquals(TEST_CMD_2, pmi.getWhat());
assertEquals(sm5.mChildState2, pmi.getState());
assertEquals(sm5.mChildState2, pmi.getOriginalState());
- pmi = sm5.getProcessedMessage(2);
+ pmi = sm5.getProcessedMessageInfo(2);
assertEquals(TEST_CMD_3, pmi.getWhat());
assertEquals(sm5.mChildState5, pmi.getState());
assertEquals(sm5.mChildState5, pmi.getOriginalState());
- pmi = sm5.getProcessedMessage(3);
+ pmi = sm5.getProcessedMessageInfo(3);
assertEquals(TEST_CMD_4, pmi.getWhat());
assertEquals(sm5.mChildState3, pmi.getState());
assertEquals(sm5.mChildState3, pmi.getOriginalState());
- pmi = sm5.getProcessedMessage(4);
+ pmi = sm5.getProcessedMessageInfo(4);
assertEquals(TEST_CMD_5, pmi.getWhat());
assertEquals(sm5.mChildState4, pmi.getState());
assertEquals(sm5.mChildState4, pmi.getOriginalState());
- pmi = sm5.getProcessedMessage(5);
+ pmi = sm5.getProcessedMessageInfo(5);
assertEquals(TEST_CMD_6, pmi.getWhat());
assertEquals(sm5.mParentState2, pmi.getState());
assertEquals(sm5.mParentState2, pmi.getOriginalState());
@@ -1089,7 +1129,7 @@
* after construction and before any other messages arrive and that
* sendMessageDelayed works.
*/
- class StateMachine6 extends HierarchicalStateMachine {
+ class StateMachine6 extends StateMachine {
StateMachine6(String name) {
super(name);
mThisSm = this;
@@ -1103,13 +1143,13 @@
if (DBG) Log.d(TAG, "StateMachine6: ctor X");
}
- class S1 extends HierarchicalState {
-
- @Override protected void enter() {
+ class S1 extends State {
+ @Override
+ public void enter() {
sendMessage(TEST_CMD_1);
}
-
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_1) {
mArrivalTimeMsg1 = SystemClock.elapsedRealtime();
} else if (message.what == TEST_CMD_2) {
@@ -1118,9 +1158,6 @@
}
return HANDLED;
}
-
- @Override protected void exit() {
- }
}
@Override
@@ -1178,7 +1215,7 @@
* Test that enter is invoked immediately after exit. This validates
* that enter can be used to send a watch dog message for its state.
*/
- class StateMachine7 extends HierarchicalStateMachine {
+ class StateMachine7 extends StateMachine {
private final int SM7_DELAY_TIME = 250;
StateMachine7(String name) {
@@ -1195,24 +1232,26 @@
if (DBG) Log.d(TAG, "StateMachine7: ctor X");
}
- class S1 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class S1 extends State {
+ @Override
+ public void exit() {
+ sendMessage(TEST_CMD_2);
+ }
+ @Override
+ public boolean processMessage(Message message) {
transitionTo(mS2);
return HANDLED;
}
- @Override protected void exit() {
- sendMessage(TEST_CMD_2);
- }
}
- class S2 extends HierarchicalState {
-
- @Override protected void enter() {
+ class S2 extends State {
+ @Override
+ public void enter() {
// Send a delayed message as a watch dog
sendMessageDelayed(TEST_CMD_3, SM7_DELAY_TIME);
}
-
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_2) {
mMsgCount += 1;
mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
@@ -1226,9 +1265,6 @@
}
return HANDLED;
}
-
- @Override protected void exit() {
- }
}
@Override
@@ -1286,7 +1322,7 @@
/**
* Test unhandledMessage.
*/
- class StateMachineUnhandledMessage extends HierarchicalStateMachine {
+ class StateMachineUnhandledMessage extends StateMachine {
StateMachineUnhandledMessage(String name) {
super(name);
mThisSm = this;
@@ -1298,13 +1334,14 @@
// Set the initial state
setInitialState(mS1);
}
-
- @Override protected void unhandledMessage(Message message) {
+ @Override
+ public void unhandledMessage(Message message) {
mUnhandledMessageCount += 1;
}
- class S1 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class S1 extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_2) {
transitionToHaltingState();
}
@@ -1359,7 +1396,7 @@
* will be used to notify testStateMachineSharedThread that the test is
* complete.
*/
- class StateMachineSharedThread extends HierarchicalStateMachine {
+ class StateMachineSharedThread extends StateMachine {
StateMachineSharedThread(String name, Looper looper, int maxCount) {
super(name, looper);
mMaxCount = maxCount;
@@ -1372,8 +1409,9 @@
setInitialState(mS1);
}
- class S1 extends HierarchicalState {
- @Override protected boolean processMessage(Message message) {
+ class S1 extends State {
+ @Override
+ public boolean processMessage(Message message) {
if (message.what == TEST_CMD_4) {
transitionToHaltingState();
}
@@ -1434,7 +1472,7 @@
for (StateMachineSharedThread sm : sms) {
assertTrue(sm.getProcessedMessagesCount() == 4);
for (int i = 0; i < sm.getProcessedMessagesCount(); i++) {
- ProcessedMessages.Info pmi = sm.getProcessedMessage(i);
+ ProcessedMessageInfo pmi = sm.getProcessedMessageInfo(i);
assertEquals(i+1, pmi.getWhat());
assertEquals(sm.mS1, pmi.getState());
assertEquals(sm.mS1, pmi.getOriginalState());
@@ -1464,37 +1502,37 @@
}
assertEquals(7, sm.getProcessedMessagesCount());
- ProcessedMessages.Info pmi = sm.getProcessedMessage(0);
+ ProcessedMessageInfo pmi = sm.getProcessedMessageInfo(0);
assertEquals(Hsm1.CMD_1, pmi.getWhat());
assertEquals(sm.mS1, pmi.getState());
assertEquals(sm.mS1, pmi.getOriginalState());
- pmi = sm.getProcessedMessage(1);
+ pmi = sm.getProcessedMessageInfo(1);
assertEquals(Hsm1.CMD_2, pmi.getWhat());
assertEquals(sm.mP1, pmi.getState());
assertEquals(sm.mS1, pmi.getOriginalState());
- pmi = sm.getProcessedMessage(2);
+ pmi = sm.getProcessedMessageInfo(2);
assertEquals(Hsm1.CMD_2, pmi.getWhat());
assertEquals(sm.mS2, pmi.getState());
assertEquals(sm.mS2, pmi.getOriginalState());
- pmi = sm.getProcessedMessage(3);
+ pmi = sm.getProcessedMessageInfo(3);
assertEquals(Hsm1.CMD_3, pmi.getWhat());
assertEquals(sm.mS2, pmi.getState());
assertEquals(sm.mS2, pmi.getOriginalState());
- pmi = sm.getProcessedMessage(4);
+ pmi = sm.getProcessedMessageInfo(4);
assertEquals(Hsm1.CMD_3, pmi.getWhat());
assertEquals(sm.mP2, pmi.getState());
assertEquals(sm.mP2, pmi.getOriginalState());
- pmi = sm.getProcessedMessage(5);
+ pmi = sm.getProcessedMessageInfo(5);
assertEquals(Hsm1.CMD_4, pmi.getWhat());
assertEquals(sm.mP2, pmi.getState());
assertEquals(sm.mP2, pmi.getOriginalState());
- pmi = sm.getProcessedMessage(6);
+ pmi = sm.getProcessedMessageInfo(6);
assertEquals(Hsm1.CMD_5, pmi.getWhat());
assertEquals(sm.mP2, pmi.getState());
assertEquals(sm.mP2, pmi.getOriginalState());
@@ -1503,7 +1541,7 @@
}
}
-class Hsm1 extends HierarchicalStateMachine {
+class Hsm1 extends StateMachine {
private static final String TAG = "hsm1";
public static final int CMD_1 = 1;
@@ -1535,11 +1573,17 @@
Log.d(TAG, "ctor X");
}
- class P1 extends HierarchicalState {
- @Override protected void enter() {
+ class P1 extends State {
+ @Override
+ public void enter() {
Log.d(TAG, "P1.enter");
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ Log.d(TAG, "P1.exit");
+ }
+ @Override
+ public boolean processMessage(Message message) {
boolean retVal;
Log.d(TAG, "P1.processMessage what=" + message.what);
switch(message.what) {
@@ -1557,16 +1601,19 @@
}
return retVal;
}
- @Override protected void exit() {
- Log.d(TAG, "P1.exit");
- }
}
- class S1 extends HierarchicalState {
- @Override protected void enter() {
+ class S1 extends State {
+ @Override
+ public void enter() {
Log.d(TAG, "S1.enter");
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ Log.d(TAG, "S1.exit");
+ }
+ @Override
+ public boolean processMessage(Message message) {
Log.d(TAG, "S1.processMessage what=" + message.what);
if (message.what == CMD_1) {
// Transition to ourself to show that enter/exit is called
@@ -1577,16 +1624,19 @@
return NOT_HANDLED;
}
}
- @Override protected void exit() {
- Log.d(TAG, "S1.exit");
- }
}
- class S2 extends HierarchicalState {
- @Override protected void enter() {
+ class S2 extends State {
+ @Override
+ public void enter() {
Log.d(TAG, "S2.enter");
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ Log.d(TAG, "S2.exit");
+ }
+ @Override
+ public boolean processMessage(Message message) {
boolean retVal;
Log.d(TAG, "S2.processMessage what=" + message.what);
switch(message.what) {
@@ -1605,17 +1655,20 @@
}
return retVal;
}
- @Override protected void exit() {
- Log.d(TAG, "S2.exit");
- }
}
- class P2 extends HierarchicalState {
- @Override protected void enter() {
+ class P2 extends State {
+ @Override
+ public void enter() {
Log.d(TAG, "P2.enter");
sendMessage(CMD_5);
}
- @Override protected boolean processMessage(Message message) {
+ @Override
+ public void exit() {
+ Log.d(TAG, "P2.exit");
+ }
+ @Override
+ public boolean processMessage(Message message) {
Log.d(TAG, "P2.processMessage what=" + message.what);
switch(message.what) {
case(CMD_3):
@@ -1628,9 +1681,6 @@
}
return HANDLED;
}
- @Override protected void exit() {
- Log.d(TAG, "P2.exit");
- }
}
@Override
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 1870a4a..5ed7966 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -66,6 +66,10 @@
<group gid="mtp" />
</permission>
+ <permission name="android.permission.NET_ADMIN" >
+ <group gid="net_admin" />
+ </permission>
+
<!-- The group that /cache belongs to, linked to the permission
set on the applications that can access /cache -->
<permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index 498c7b8..2caf211 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -220,40 +220,58 @@
return ERROR_ALREADY_CONNECTED;
}
- struct hostent *ent = gethostbyname(server);
- if (ent == NULL) {
+ if (port < 0 || port > (int) USHRT_MAX) {
+ return UNKNOWN_ERROR;
+ }
+
+ char service[sizeof("65536")];
+ sprintf(service, "%d", port);
+ struct addrinfo hints, *ai;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
+ hints.ai_socktype = SOCK_STREAM;
+
+ int ret = getaddrinfo(server, service, &hints, &ai);
+ if (ret) {
return ERROR_UNKNOWN_HOST;
}
CHECK_EQ(mSocket, -1);
- mSocket = socket(AF_INET, SOCK_STREAM, 0);
-
- if (mSocket < 0) {
- return UNKNOWN_ERROR;
- }
-
- setReceiveTimeout(30); // Time out reads after 30 secs by default
mState = CONNECTING;
+ status_t res = -1;
+ struct addrinfo *tmp;
+ for (tmp = ai; tmp; tmp = tmp->ai_next) {
+ mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
+ if (mSocket < 0) {
+ continue;
+ }
- int s = mSocket;
+ setReceiveTimeout(30); // Time out reads after 30 secs by default.
- mLock.unlock();
+ int s = mSocket;
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
- memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+ mLock.unlock();
- status_t res = MyConnect(s, (const struct sockaddr *)&addr, sizeof(addr));
+ res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen);
- mLock.lock();
+ mLock.lock();
- if (mState != CONNECTING) {
- return UNKNOWN_ERROR;
+ if (mState != CONNECTING) {
+ close(s);
+ freeaddrinfo(ai);
+ return UNKNOWN_ERROR;
+ }
+
+ if (res == OK) {
+ break;
+ }
+
+ close(s);
}
+ freeaddrinfo(ai);
+
if (res != OK) {
close(mSocket);
mSocket = -1;
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
index 7802efd..81c6167 100644
--- a/media/tests/omxjpegdecoder/Android.mk
+++ b/media/tests/omxjpegdecoder/Android.mk
@@ -22,11 +22,6 @@
SkOmxPixelRef.cpp \
StreamSource.cpp
-
-# add external/skia/src/images/SkImageDecoder_libjpeg.cpp
-LOCAL_SRC_FILES += \
- ../../../../../external/skia/src/images/SkImageDecoder_libjpeg.cpp
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libskia \
diff --git a/nfc-extras/Android.mk b/nfc-extras/Android.mk
new file mode 100644
index 0000000..131d898
--- /dev/null
+++ b/nfc-extras/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_MODULE:= com.android.nfc_extras
+
+include $(BUILD_JAVA_LIBRARY)
+
+# put the classes.jar, with full class files instead of classes.dex inside, into the dist directory
+$(call dist-for-goals, droidcore, $(full_classes_jar):com.android.nfc_extras.jar)
diff --git a/nfc-extras/com.android.nfc_extras.xml b/nfc-extras/com.android.nfc_extras.xml
new file mode 100644
index 0000000..370145d
--- /dev/null
+++ b/nfc-extras/com.android.nfc_extras.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<permissions>
+ <library name="com.android.nfc_extras"
+ file="/system/framework/com.android.nfc_extras.jar" />
+</permissions>
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
new file mode 100644
index 0000000..cf38bd1
--- /dev/null
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.nfc_extras;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.nfc.INfcAdapterExtras;
+import android.nfc.NfcAdapter;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Provides additional methods on an {@link NfcAdapter} for Card Emulation
+ * and management of {@link NfcExecutionEnvironment}'s.
+ *
+ * There is a 1-1 relationship between an {@link NfcAdapterExtras} object and
+ * a {@link NfcAdapter} object.
+ */
+public final class NfcAdapterExtras {
+ private static final String TAG = "NfcAdapterExtras";
+
+ /**
+ * Broadcast Action: an RF field ON has been detected.
+ *
+ * <p class="note">This is an unreliable signal, and will be removed.
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
+ * to receive.
+ */
+ public static final String ACTION_RF_FIELD_ON_DETECTED =
+ "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
+
+ /**
+ * Broadcast Action: an RF field OFF has been detected.
+ *
+ * <p class="note">This is an unreliable signal, and will be removed.
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
+ * to receive.
+ */
+ public static final String ACTION_RF_FIELD_OFF_DETECTED =
+ "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
+
+ // protected by NfcAdapterExtras.class, and final after first construction
+ private static INfcAdapterExtras sService;
+ private static boolean sIsInitialized = false;
+ private static NfcAdapterExtras sSingleton;
+ private static NfcExecutionEnvironment sEmbeddedEe;
+ private static CardEmulationRoute sRouteOff;
+ private static CardEmulationRoute sRouteOnWhenScreenOn;
+
+ /**
+ * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @param adapter a {@link NfcAdapter}, must not be null
+ * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
+ */
+ public static NfcAdapterExtras get(NfcAdapter adapter) {
+ synchronized(NfcAdapterExtras.class) {
+ if (!sIsInitialized) {
+ sIsInitialized = true;
+ sService = adapter.getNfcAdapterExtrasInterface();
+ sEmbeddedEe = new NfcExecutionEnvironment(sService);
+ sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
+ sRouteOnWhenScreenOn = new CardEmulationRoute(
+ CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
+ sSingleton = new NfcAdapterExtras();
+ }
+ return sSingleton;
+ }
+ }
+
+ private NfcAdapterExtras() {}
+
+ /**
+ * Immutable data class that describes a card emulation route.
+ */
+ public final static class CardEmulationRoute {
+ /**
+ * Card Emulation is turned off on this NfcAdapter.
+ * <p>This is the default routing state after boot.
+ */
+ public static final int ROUTE_OFF = 1;
+
+ /**
+ * Card Emulation is routed to {@link #nfcEe} only when the screen is on,
+ * otherwise it is turned off.
+ */
+ public static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
+
+ /**
+ * A route such as {@link #ROUTE_OFF} or {@link #ROUTE_ON_WHEN_SCREEN_ON}.
+ */
+ public final int route;
+
+ /**
+ * The {@link NFcExecutionEnvironment} that is Card Emulation is routed to.
+ * <p>null if {@link #route} is {@link #ROUTE_OFF}, otherwise not null.
+ */
+ public final NfcExecutionEnvironment nfcEe;
+
+ public CardEmulationRoute(int route, NfcExecutionEnvironment nfcEe) {
+ if (route == ROUTE_OFF && nfcEe != null) {
+ throw new IllegalArgumentException("must not specifiy a NFC-EE with ROUTE_OFF");
+ } else if (route != ROUTE_OFF && nfcEe == null) {
+ throw new IllegalArgumentException("must specifiy a NFC-EE for this route");
+ }
+ this.route = route;
+ this.nfcEe = nfcEe;
+ }
+ }
+
+ /**
+ * Get the routing state of this NFC EE.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @return
+ */
+ public CardEmulationRoute getCardEmulationRoute() {
+ try {
+ int route = sService.getCardEmulationRoute();
+ return route == CardEmulationRoute.ROUTE_OFF ?
+ sRouteOff :
+ sRouteOnWhenScreenOn;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return sRouteOff;
+ }
+ }
+
+ /**
+ * Set the routing state of this NFC EE.
+ *
+ * <p>This routing state is not persisted across reboot.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @param route a {@link #CardEmulationRoute}
+ */
+ public void setCardEmulationRoute(CardEmulationRoute route) {
+ try {
+ sService.setCardEmulationRoute(route.route);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+
+ /**
+ * Get the {@link NfcExecutionEnvironment} that is embedded with the
+ * {@link NFcAdapter}.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE
+ */
+ public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
+ return sEmbeddedEe;
+ }
+}
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
new file mode 100644
index 0000000..3efe492
--- /dev/null
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.nfc_extras;
+
+import java.io.IOException;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.nfc.INfcAdapterExtras;
+import android.nfc.NfcAdapter;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+public class NfcExecutionEnvironment {
+ private final INfcAdapterExtras mService;
+
+ /**
+ * Broadcast Action: An ISO-DEP AID was selected.
+ *
+ * <p>This happens as the result of a 'SELECT AID' command from an
+ * external NFC reader/writer.
+ *
+ * <p>Always contains the extra field {@link #EXTRA_AID}
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
+ * to receive.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_AID_SELECTED =
+ "com.android.nfc_extras.action.AID_SELECTED";
+
+ /**
+ * Mandatory byte array extra field in {@link #ACTION_AID_SELECTED}.
+ *
+ * <p>Contains the AID selected.
+ * @hide
+ */
+ public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
+
+ NfcExecutionEnvironment(INfcAdapterExtras service) {
+ mService = service;
+ }
+
+ /**
+ * Open the NFC Execution Environment on its contact interface.
+ *
+ * <p>Only one process may open the secure element at a time. If it is
+ * already open, an {@link IOException} is thrown.
+ *
+ * <p>All other NFC functionality is disabled while the NFC-EE is open
+ * on its contact interface, so make sure to call {@link #close} once complete.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @throws IOException if the NFC-EE is already open, or some other error occurs
+ */
+ public void open() throws IOException {
+ try {
+ Bundle b = mService.open(new Binder());
+ throwBundle(b);
+ } catch (RemoteException e) {
+ return;
+ }
+ }
+
+ /**
+ * Close the NFC Execution Environment on its contact interface.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @throws IOException if the NFC-EE is already open, or some other error occurs
+ */
+ public void close() throws IOException {
+ try {
+ throwBundle(mService.close());
+ } catch (RemoteException e) {
+ return;
+ }
+ }
+
+ /**
+ * Send raw commands to the NFC-EE and receive the response.
+ *
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+ *
+ * @throws IOException if the NFC-EE is not open, or some other error occurs
+ */
+ public byte[] transceive(byte[] in) throws IOException {
+ Bundle b;
+ try {
+ b = mService.transceive(in);
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ throwBundle(b);
+ return b.getByteArray("out");
+ }
+
+ private static void throwBundle(Bundle b) throws IOException {
+ if (b.getInt("e") == -1) {
+ throw new IOException(b.getString("m"));
+ }
+ }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 2ed968b..964fe9c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -17,6 +17,8 @@
package com.android.providers.settings;
import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
@@ -1300,8 +1302,13 @@
}
// Set the preferred network mode to 0 = Global, CDMA default
- int type = SystemProperties.getInt("ro.telephony.default_network",
- RILConstants.PREFERRED_NETWORK_MODE);
+ int type;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ type = Phone.NT_MODE_GLOBAL;
+ } else {
+ type = SystemProperties.getInt("ro.telephony.default_network",
+ RILConstants.PREFERRED_NETWORK_MODE);
+ }
loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);
// Enable or disable Cell Broadcast SMS
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..ade3716
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 0273a4c..826ac92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -246,6 +246,16 @@
R.drawable.stat_sys_data_fully_out_3g,
R.drawable.stat_sys_data_fully_inandout_3g }
};
+ private static final int[][] sDataNetType_4g = {
+ { R.drawable.stat_sys_data_connected_4g,
+ R.drawable.stat_sys_data_in_4g,
+ R.drawable.stat_sys_data_out_4g,
+ R.drawable.stat_sys_data_inandout_4g },
+ { R.drawable.stat_sys_data_fully_connected_4g,
+ R.drawable.stat_sys_data_fully_in_4g,
+ R.drawable.stat_sys_data_fully_out_4g,
+ R.drawable.stat_sys_data_fully_inandout_4g }
+ };
private static final int[][] sDataNetType_e = {
{ R.drawable.stat_sys_data_connected_e,
R.drawable.stat_sys_data_in_e,
@@ -670,9 +680,12 @@
case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
mDataIconList = sDataNetType_3g[mInetCondition];
break;
- // TODO - add support for NETWORK_TYPE_LTE and NETWORK_TYPE_EHRPD
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mDataIconList = sDataNetType_4g[mInetCondition];
+ break;
default:
mDataIconList = sDataNetType_g[mInetCondition];
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index a693e60..3175a99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -427,10 +427,14 @@
case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
mDataTypeIconId = R.drawable.stat_sys_signal_3g;
break;
- // TODO - add support for NETWORK_TYPE_LTE and NETWORK_TYPE_EHRPD
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
+ mDataTypeIconId = R.drawable.stat_sys_signal_4g;
+ break;
default:
mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
mDataTypeIconId = R.drawable.stat_sys_signal_gprs;
@@ -442,12 +446,14 @@
}
boolean isCdmaEri() {
- final int iconIndex = mServiceState.getCdmaEriIconIndex();
- if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
- final int iconMode = mServiceState.getCdmaEriIconMode();
- if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
- || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
- return true;
+ if (mServiceState != null) {
+ final int iconIndex = mServiceState.getCdmaEriIconIndex();
+ if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
+ final int iconMode = mServiceState.getCdmaEriIconMode();
+ if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
+ || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
+ return true;
+ }
}
}
return false;
@@ -850,7 +856,7 @@
pw.print(" mDataActivity=");
pw.println(mDataActivity);
pw.print(" mServiceState=");
- pw.println(mServiceState.toString());
+ pw.println(mServiceState);
pw.print(" mNetworkName=");
pw.println(mNetworkName);
pw.print(" mNetworkNameDefault=");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 29d35e3..9093b3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -124,5 +124,18 @@
R.drawable.stat_sys_data_fully_inandout_1x }
};
+ // LTE and eHRPD
+ static final int[][] DATA_4G = {
+ { R.drawable.stat_sys_data_connected_4g,
+ R.drawable.stat_sys_data_in_4g,
+ R.drawable.stat_sys_data_out_4g,
+ R.drawable.stat_sys_data_inandout_4g },
+ { R.drawable.stat_sys_data_fully_connected_4g,
+ R.drawable.stat_sys_data_fully_in_4g,
+ R.drawable.stat_sys_data_fully_out_4g,
+ R.drawable.stat_sys_data_fully_inandout_4g }
+ };
+
+
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 5ed67a9..72209f6 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -480,11 +480,11 @@
}
/**
- * Report that the user succesfully entered the sim pin so we
+ * Report that the user succesfully entered the sim pin or puk so we
* have the information earlier than waiting for the intent
* broadcast from the telephony code.
*/
- public void reportSimPinUnlocked() {
+ public void reportSimUnlocked() {
mSimState = IccCard.State.READY;
}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 2fda3aa..874acd0 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -116,6 +116,11 @@
SimPin,
/**
+ * Unlock by entering a sim puk.
+ */
+ SimPuk,
+
+ /**
* Unlock by entering an account's login and password.
*/
Account,
@@ -222,8 +227,10 @@
public void goToUnlockScreen() {
final IccCard.State simState = mUpdateMonitor.getSimState();
if (stuckOnLockScreenBecauseSimMissing()
- || (simState == IccCard.State.PUK_REQUIRED)){
- // stuck on lock screen when sim missing or puk'd
+ || (simState == IccCard.State.PUK_REQUIRED
+ && !mLockPatternUtils.isPukUnlockScreenEnable())){
+ // stuck on lock screen when sim missing or
+ // puk'd but puk unlock screen is disabled
return;
}
if (!isSecure()) {
@@ -522,8 +529,10 @@
secure = mLockPatternUtils.isLockPatternEnabled();
break;
case SimPin:
- secure = mUpdateMonitor.getSimState() == IccCard.State.PIN_REQUIRED
- || mUpdateMonitor.getSimState() == IccCard.State.PUK_REQUIRED;
+ secure = mUpdateMonitor.getSimState() == IccCard.State.PIN_REQUIRED;
+ break;
+ case SimPuk:
+ secure = mUpdateMonitor.getSimState() == IccCard.State.PUK_REQUIRED;
break;
case Account:
secure = true;
@@ -592,6 +601,10 @@
View createUnlockScreenFor(UnlockMode unlockMode) {
View unlockView = null;
+
+ if (DEBUG) Log.d(TAG,
+ "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
+
if (unlockMode == UnlockMode.Pattern) {
PatternUnlockScreen view = new PatternUnlockScreen(
mContext,
@@ -600,10 +613,15 @@
mUpdateMonitor,
mKeyguardScreenCallback,
mUpdateMonitor.getFailedAttempts());
- if (DEBUG) Log.d(TAG,
- "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
view.setEnableFallback(mEnableFallback);
unlockView = view;
+ } else if (unlockMode == UnlockMode.SimPuk) {
+ unlockView = new SimPukUnlockScreen(
+ mContext,
+ mConfiguration,
+ mUpdateMonitor,
+ mKeyguardScreenCallback,
+ mLockPatternUtils);
} else if (unlockMode == UnlockMode.SimPin) {
unlockView = new SimUnlockScreen(
mContext,
@@ -654,7 +672,9 @@
*/
private Mode getInitialMode() {
final IccCard.State simState = mUpdateMonitor.getSimState();
- if (stuckOnLockScreenBecauseSimMissing() || (simState == IccCard.State.PUK_REQUIRED)) {
+ if (stuckOnLockScreenBecauseSimMissing() ||
+ (simState == IccCard.State.PUK_REQUIRED &&
+ !mLockPatternUtils.isPukUnlockScreenEnable())) {
return Mode.LockScreen;
} else {
// Show LockScreen first for any screen other than Pattern unlock.
@@ -676,8 +696,10 @@
private UnlockMode getUnlockMode() {
final IccCard.State simState = mUpdateMonitor.getSimState();
UnlockMode currentMode;
- if (simState == IccCard.State.PIN_REQUIRED || simState == IccCard.State.PUK_REQUIRED) {
+ if (simState == IccCard.State.PIN_REQUIRED) {
currentMode = UnlockMode.SimPin;
+ } else if (simState == IccCard.State.PUK_REQUIRED) {
+ currentMode = UnlockMode.SimPuk;
} else {
final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
switch (mode) {
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index a9d5ce4..88f4f23 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -232,7 +232,7 @@
/** {@inheritDoc} */
public void onGrabbedStateChange(View v, int grabbedState) {
- if (DBG) Log.v(TAG, "*** LockScreen accel is "
+ if (DBG) Log.v(TAG, "*** LockScreen accel is "
+ (mEnergyWave.isHardwareAccelerated() ? "on":"off"));
// Don't poke the wake lock when returning to a state where the handle is
// not grabbed since that can happen when the system (instead of the user)
@@ -534,11 +534,11 @@
case SimMissing:
// text
mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short);
- mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions);
+ mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions_long);
// layout
mScreenLocked.setVisibility(View.VISIBLE);
- mEmergencyCallText.setVisibility(View.VISIBLE);
+ mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
enableUnlock(); // do not need to show the e-call button; user may unlock
break;
@@ -552,8 +552,8 @@
// layout
mScreenLocked.setVisibility(View.VISIBLE);
- mEmergencyCallText.setVisibility(View.VISIBLE);
- mEmergencyCallButton.setVisibility(View.VISIBLE);
+ mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
disableUnlock();
break;
@@ -579,10 +579,15 @@
mScreenLocked.setText(R.string.lockscreen_sim_puk_locked_instructions);
// layout
- mScreenLocked.setVisibility(View.VISIBLE);
- mEmergencyCallText.setVisibility(View.VISIBLE);
- mEmergencyCallButton.setVisibility(View.VISIBLE);
- disableUnlock();
+ mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ if (mLockPatternUtils.isPukUnlockScreenEnable()) {
+ mScreenLocked.setVisibility(View.INVISIBLE);
+ enableUnlock();
+ } else {
+ mScreenLocked.setVisibility(View.VISIBLE);
+ disableUnlock();
+ }
break;
}
}
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
new file mode 100644
index 0000000..544bb3d
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy.impl;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.text.Editable;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * Displays a dialer like interface to unlock the SIM PUK.
+ */
+public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen,
+ View.OnClickListener, KeyguardUpdateMonitor.InfoCallback {
+
+ private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+
+ private final KeyguardUpdateMonitor mUpdateMonitor;
+ private final KeyguardScreenCallback mCallback;
+
+ private TextView mHeaderText;
+ private TextView mPukText;
+ private TextView mPinText;
+
+ private TextView mFocusedEntry;
+
+ private TextView mOkButton;
+ private Button mEmergencyCallButton;
+
+ private View mDelPukButton;
+ private View mDelPinButton;
+
+ private ProgressDialog mSimUnlockProgressDialog = null;
+
+ private LockPatternUtils mLockPatternUtils;
+
+ private int mCreationOrientation;
+
+ private int mKeyboardHidden;
+
+ private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+ public SimPukUnlockScreen(Context context, Configuration configuration,
+ KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
+ LockPatternUtils lockpatternutils) {
+ super(context);
+ mUpdateMonitor = updateMonitor;
+ mCallback = callback;;
+
+ mCreationOrientation = configuration.orientation;
+ mKeyboardHidden = configuration.hardKeyboardHidden;
+ mLockPatternUtils = lockpatternutils;
+
+ LayoutInflater inflater = LayoutInflater.from(context);
+ if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
+ inflater.inflate(
+ R.layout.keyguard_screen_sim_puk_landscape, this, true);
+ } else {
+ inflater.inflate(
+ R.layout.keyguard_screen_sim_puk_portrait, this, true);
+ new TouchInput();
+ }
+
+ mHeaderText = (TextView) findViewById(R.id.headerText);
+ mPukText = (TextView) findViewById(R.id.pukDisplay);
+ mPukText.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ requestFocus(mPukText);
+ mCallback.pokeWakelock();
+ }
+ });
+ mPinText = (TextView) findViewById(R.id.pinDisplay);
+ mPinText.setOnClickListener(this);
+
+ mDelPukButton = findViewById(R.id.pukDel);
+ mDelPukButton.setOnClickListener(this);
+ mDelPinButton = findViewById(R.id.pinDel);
+ mDelPinButton.setOnClickListener(this);
+
+
+ mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+ mOkButton = (TextView) findViewById(R.id.ok);
+
+ mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
+ mPukText.setFocusable(false);
+ mPinText.setFocusable(false);
+ mOkButton.setOnClickListener(this);
+
+ requestFocus(mPukText);
+
+ if (mLockPatternUtils.isEmergencyCallCapable()) {
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ mEmergencyCallButton.setOnClickListener(this);
+ } else {
+ mEmergencyCallButton.setVisibility(View.GONE);
+ }
+
+ setFocusableInTouchMode(true);
+ }
+
+ private void requestFocus(TextView entry) {
+ mFocusedEntry = entry;
+ mFocusedEntry.setText("");
+ }
+
+ /** {@inheritDoc} */
+ public boolean needsInput() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public void onPause() {
+
+ }
+
+ /** {@inheritDoc} */
+ public void onResume() {
+ // start fresh
+ mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
+ requestFocus(mPukText);
+ mPinText.setText("");
+
+ if (mLockPatternUtils.isEmergencyCallCapable()) {
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void cleanUp() {
+ // dismiss the dialog.
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.dismiss();
+ mSimUnlockProgressDialog = null;
+ }
+ mUpdateMonitor.removeCallback(this);
+ }
+
+
+ /**
+ * Since the IPC can block, we want to run the request in a separate thread
+ * with a callback.
+ */
+ private abstract class CheckSimPuk extends Thread {
+
+ private final String mPin, mPuk;
+
+ protected CheckSimPuk(String puk, String pin) {
+ mPuk = puk;
+ mPin = pin;
+ }
+
+ abstract void onSimLockChangedResponse(boolean success);
+
+ @Override
+ public void run() {
+ try {
+ final boolean result = ITelephony.Stub.asInterface(ServiceManager
+ .checkService("phone")).supplyPuk(mPuk, mPin);
+
+ post(new Runnable() {
+ public void run() {
+ onSimLockChangedResponse(result);
+ }
+ });
+ } catch (RemoteException e) {
+ post(new Runnable() {
+ public void run() {
+ onSimLockChangedResponse(false);
+ }
+ });
+ }
+ }
+ }
+
+ public void onClick(View v) {
+ if (v == mDelPukButton) {
+ final Editable digits = mPukText.getEditableText();
+ final int len = digits.length();
+ if (len > 0) {
+ digits.delete(len-1, len);
+ }
+ mCallback.pokeWakelock();
+ } else if (v == mDelPinButton) {
+ final Editable digits = mPinText.getEditableText();
+ final int len = digits.length();
+ if (len > 0) {
+ digits.delete(len-1, len);
+ }
+ mCallback.pokeWakelock();
+ } else if (v == mPinText) {
+ requestFocus(mPinText);
+ mCallback.pokeWakelock();
+ } else if (v == mEmergencyCallButton) {
+ mCallback.takeEmergencyCallAction();
+ } else if (v == mOkButton) {
+ checkPuk();
+ }
+ }
+
+ private Dialog getSimUnlockProgressDialog() {
+ if (mSimUnlockProgressDialog == null) {
+ mSimUnlockProgressDialog = new ProgressDialog(mContext);
+ mSimUnlockProgressDialog.setMessage(
+ mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
+ mSimUnlockProgressDialog.setIndeterminate(true);
+ mSimUnlockProgressDialog.setCancelable(false);
+ mSimUnlockProgressDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_sf_slowBlur)) {
+ mSimUnlockProgressDialog.getWindow().setFlags(
+ WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
+ WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+ }
+ }
+ return mSimUnlockProgressDialog;
+ }
+
+ private void checkPuk() {
+ // make sure that the puk is at least 8 digits long.
+ if (mPukText.getText().length() < 8) {
+ // otherwise, display a message to the user, and don't submit.
+ mHeaderText.setText(R.string.invalidPuk);
+ mPukText.setText("");
+ mCallback.pokeWakelock();
+ return;
+ }
+
+ if (mPinText.getText().length() < 4
+ || mPinText.getText().length() > 8) {
+ // otherwise, display a message to the user, and don't submit.
+ mHeaderText.setText(R.string.invalidPin);
+ mPinText.setText("");
+ mCallback.pokeWakelock();
+ return;
+ }
+
+ getSimUnlockProgressDialog().show();
+
+ new CheckSimPuk(mPukText.getText().toString(),
+ mPinText.getText().toString()) {
+ void onSimLockChangedResponse(boolean success) {
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
+ if (success) {
+ // before closing the keyguard, report back that
+ // the sim is unlocked so it knows right away
+ mUpdateMonitor.reportSimUnlocked();
+ mCallback.goToUnlockScreen();
+ } else {
+ mHeaderText.setText(R.string.badPuk);
+ mPukText.setText("");
+ mPinText.setText("");
+ }
+ mCallback.pokeWakelock();
+ }
+ }.start();
+ }
+
+
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ mCallback.goToLockScreen();
+ return true;
+ }
+ final char match = event.getMatch(DIGITS);
+ if (match != 0) {
+ reportDigit(match - '0');
+ return true;
+ }
+ if (keyCode == KeyEvent.KEYCODE_DEL) {
+ mFocusedEntry.onKeyDown(keyCode, event);
+ final Editable digits = mFocusedEntry.getEditableText();
+ final int len = digits.length();
+ if (len > 0) {
+ digits.delete(len-1, len);
+ }
+ mCallback.pokeWakelock();
+ return true;
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_ENTER) {
+ checkPuk();
+ return true;
+ }
+
+ return false;
+ }
+
+ private void reportDigit(int digit) {
+ mFocusedEntry.append(Integer.toString(digit));
+ }
+
+ void updateConfiguration() {
+ Configuration newConfig = getResources().getConfiguration();
+ if (newConfig.orientation != mCreationOrientation) {
+ mCallback.recreateMe(newConfig);
+ } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
+ mKeyboardHidden = newConfig.hardKeyboardHidden;
+ final boolean isKeyboardOpen =
+ (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO);
+ if (mUpdateMonitor.isKeyguardBypassEnabled() && isKeyboardOpen) {
+ mCallback.goToUnlockScreen();
+ }
+ }
+
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ updateConfiguration();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateConfiguration();
+ }
+
+ /**
+ * Helper class to handle input from touch dialer. Only relevant when
+ * the keyboard is shut.
+ */
+ private class TouchInput implements View.OnClickListener {
+ private TextView mZero;
+ private TextView mOne;
+ private TextView mTwo;
+ private TextView mThree;
+ private TextView mFour;
+ private TextView mFive;
+ private TextView mSix;
+ private TextView mSeven;
+ private TextView mEight;
+ private TextView mNine;
+ private TextView mCancelButton;
+
+ private TouchInput() {
+ mZero = (TextView) findViewById(R.id.zero);
+ mOne = (TextView) findViewById(R.id.one);
+ mTwo = (TextView) findViewById(R.id.two);
+ mThree = (TextView) findViewById(R.id.three);
+ mFour = (TextView) findViewById(R.id.four);
+ mFive = (TextView) findViewById(R.id.five);
+ mSix = (TextView) findViewById(R.id.six);
+ mSeven = (TextView) findViewById(R.id.seven);
+ mEight = (TextView) findViewById(R.id.eight);
+ mNine = (TextView) findViewById(R.id.nine);
+ mCancelButton = (TextView) findViewById(R.id.cancel);
+
+ mZero.setText("0");
+ mOne.setText("1");
+ mTwo.setText("2");
+ mThree.setText("3");
+ mFour.setText("4");
+ mFive.setText("5");
+ mSix.setText("6");
+ mSeven.setText("7");
+ mEight.setText("8");
+ mNine.setText("9");
+
+ mZero.setOnClickListener(this);
+ mOne.setOnClickListener(this);
+ mTwo.setOnClickListener(this);
+ mThree.setOnClickListener(this);
+ mFour.setOnClickListener(this);
+ mFive.setOnClickListener(this);
+ mSix.setOnClickListener(this);
+ mSeven.setOnClickListener(this);
+ mEight.setOnClickListener(this);
+ mNine.setOnClickListener(this);
+ mCancelButton.setOnClickListener(this);
+ }
+
+
+ public void onClick(View v) {
+ if (v == mCancelButton) {
+ mCallback.goToLockScreen();
+ return;
+ }
+
+ final int digit = checkDigit(v);
+ if (digit >= 0) {
+ mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
+ reportDigit(digit);
+ }
+ }
+
+ private int checkDigit(View v) {
+ int digit = -1;
+ if (v == mZero) {
+ digit = 0;
+ } else if (v == mOne) {
+ digit = 1;
+ } else if (v == mTwo) {
+ digit = 2;
+ } else if (v == mThree) {
+ digit = 3;
+ } else if (v == mFour) {
+ digit = 4;
+ } else if (v == mFive) {
+ digit = 5;
+ } else if (v == mSix) {
+ digit = 6;
+ } else if (v == mSeven) {
+ digit = 7;
+ } else if (v == mEight) {
+ digit = 8;
+ } else if (v == mNine) {
+ digit = 9;
+ }
+ return digit;
+ }
+ }
+
+ public void onPhoneStateChanged(String newState) {
+ if (mLockPatternUtils.isEmergencyCallCapable()) {
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ }
+ }
+
+ public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
+
+ }
+
+ public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+
+ }
+
+ public void onRingerModeChanged(int state) {
+
+ }
+
+ public void onTimeChanged() {
+
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 486e7aa..7255c27 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -92,16 +92,17 @@
mBackSpaceButton = findViewById(R.id.backspace);
mBackSpaceButton.setOnClickListener(this);
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
mOkButton = (TextView) findViewById(R.id.ok);
mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
mPinText.setFocusable(false);
- mEmergencyCallButton.setOnClickListener(this);
mOkButton.setOnClickListener(this);
+ mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+ mEmergencyCallButton.setOnClickListener(this);
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+
setFocusableInTouchMode(true);
}
@@ -229,7 +230,7 @@
if (success) {
// before closing the keyguard, report back that
// the sim is unlocked so it knows right away
- mUpdateMonitor.reportSimPinUnlocked();
+ mUpdateMonitor.reportSimUnlocked();
mCallback.goToUnlockScreen();
} else {
mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
@@ -291,9 +292,8 @@
mCallback.goToUnlockScreen();
}
}
-
}
-
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -403,7 +403,7 @@
}
public void onPhoneStateChanged(String newState) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
}
public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b1552a8..9330491 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -26,19 +26,23 @@
import android.net.DummyDataStateTracker;
import android.net.EthernetDataTracker;
import android.net.IConnectivityManager;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MobileDataStateTracker;
+import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.net.Proxy;
import android.net.ProxyProperties;
+import android.net.RouteInfo;
import android.net.vpn.VpnManager;
import android.net.wifi.WifiStateTracker;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -58,6 +62,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
+import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
@@ -79,6 +84,10 @@
private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
"android.telephony.apn-restore";
+ // used in recursive route setting to add gateways for the host for which
+ // a host route was requested.
+ private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
+
private Tethering mTethering;
private boolean mTetheringConfigValid = false;
@@ -118,6 +127,8 @@
private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
+ private INetworkManagementService mNetd;
+
private static final int ENABLED = 1;
private static final int DISABLED = 0;
@@ -189,6 +200,14 @@
private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
MAX_NETWORK_STATE_TRACKER_EVENT + 9;
+ /**
+ * used internally to set external dependency met/unmet
+ * arg1 = ENABLED (met) or DISABLED (unmet)
+ * arg2 = NetworkType
+ */
+ private static final int EVENT_SET_DEPENDENCY_MET =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 10;
+
private Handler mHandler;
// list of DeathRecipients used to make sure features are turned off when
@@ -217,28 +236,7 @@
private SettingsObserver mSettingsObserver;
- private static class NetworkAttributes {
- /**
- * Class for holding settings read from resources.
- */
- public String mName;
- public int mType;
- public int mRadio;
- public int mPriority;
- public NetworkInfo.State mLastState;
- public NetworkAttributes(String init) {
- String fragments[] = init.split(",");
- mName = fragments[0].toLowerCase();
- mType = Integer.parseInt(fragments[1]);
- mRadio = Integer.parseInt(fragments[2]);
- mPriority = Integer.parseInt(fragments[3]);
- mLastState = NetworkInfo.State.UNKNOWN;
- }
- public boolean isDefault() {
- return (mType == mRadio);
- }
- }
- NetworkAttributes[] mNetAttributes;
+ NetworkConfig[] mNetConfigs;
int mNetworksDefined;
private static class RadioAttributes {
@@ -305,7 +303,7 @@
mNetworkPreference = getPersistedNetworkPreference();
mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
- mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1];
+ mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
// Load device network attributes from resources
String[] raStrings = context.getResources().getStringArray(
@@ -328,23 +326,23 @@
com.android.internal.R.array.networkAttributes);
for (String naString : naStrings) {
try {
- NetworkAttributes n = new NetworkAttributes(naString);
- if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) {
+ NetworkConfig n = new NetworkConfig(naString);
+ if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
loge("Error in networkAttributes - ignoring attempt to define type " +
- n.mType);
+ n.type);
continue;
}
- if (mNetAttributes[n.mType] != null) {
+ if (mNetConfigs[n.type] != null) {
loge("Error in networkAttributes - ignoring attempt to redefine type " +
- n.mType);
+ n.type);
continue;
}
- if (mRadioAttributes[n.mRadio] == null) {
+ if (mRadioAttributes[n.radio] == null) {
loge("Error in networkAttributes - ignoring attempt to use undefined " +
- "radio " + n.mRadio + " in network type " + n.mType);
+ "radio " + n.radio + " in network type " + n.type);
continue;
}
- mNetAttributes[n.mType] = n;
+ mNetConfigs[n.type] = n;
mNetworksDefined++;
} catch(Exception e) {
// ignore it - leave the entry null
@@ -358,16 +356,16 @@
int currentLowest = 0;
int nextLowest = 0;
while (insertionPoint > -1) {
- for (NetworkAttributes na : mNetAttributes) {
+ for (NetworkConfig na : mNetConfigs) {
if (na == null) continue;
- if (na.mPriority < currentLowest) continue;
- if (na.mPriority > currentLowest) {
- if (na.mPriority < nextLowest || nextLowest == 0) {
- nextLowest = na.mPriority;
+ if (na.priority < currentLowest) continue;
+ if (na.priority > currentLowest) {
+ if (na.priority < nextLowest || nextLowest == 0) {
+ nextLowest = na.priority;
}
continue;
}
- mPriorityList[insertionPoint--] = na.mType;
+ mPriorityList[insertionPoint--] = na.type;
}
currentLowest = nextLowest;
nextLowest = 0;
@@ -393,7 +391,7 @@
* to change very often.
*/
for (int netType : mPriorityList) {
- switch (mNetAttributes[netType].mRadio) {
+ switch (mNetConfigs[netType].radio) {
case ConnectivityManager.TYPE_WIFI:
if (DBG) log("Starting Wifi Service.");
WifiStateTracker wst = new WifiStateTracker();
@@ -409,12 +407,12 @@
break;
case ConnectivityManager.TYPE_MOBILE:
mNetTrackers[netType] = new MobileDataStateTracker(netType,
- mNetAttributes[netType].mName);
+ mNetConfigs[netType].name);
mNetTrackers[netType].startMonitoring(context, mHandler);
break;
case ConnectivityManager.TYPE_DUMMY:
mNetTrackers[netType] = new DummyDataStateTracker(netType,
- mNetAttributes[netType].mName);
+ mNetConfigs[netType].name);
mNetTrackers[netType].startMonitoring(context, mHandler);
break;
case ConnectivityManager.TYPE_BLUETOOTH:
@@ -427,7 +425,7 @@
break;
default:
loge("Trying to create a DataStateTracker for an unknown radio type " +
- mNetAttributes[netType].mRadio);
+ mNetConfigs[netType].radio);
continue;
}
}
@@ -474,8 +472,8 @@
private void handleSetNetworkPreference(int preference) {
if (ConnectivityManager.isNetworkTypeValid(preference) &&
- mNetAttributes[preference] != null &&
- mNetAttributes[preference].isDefault()) {
+ mNetConfigs[preference] != null &&
+ mNetConfigs[preference].isDefault()) {
if (mNetworkPreference != preference) {
final ContentResolver cr = mContext.getContentResolver();
Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
@@ -542,21 +540,7 @@
* active
*/
public NetworkInfo getActiveNetworkInfo() {
- enforceAccessPermission();
- for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- if (mNetAttributes[type] == null || !mNetAttributes[type].isDefault()) {
- continue;
- }
- NetworkStateTracker t = mNetTrackers[type];
- NetworkInfo info = t.getNetworkInfo();
- if (info.isConnected()) {
- if (DBG && type != mActiveDefaultNetwork) {
- loge("connected default network is not mActiveDefaultNetwork!");
- }
- return info;
- }
- }
- return null;
+ return getNetworkInfo(mActiveDefaultNetwork);
}
public NetworkInfo getNetworkInfo(int networkType) {
@@ -588,18 +572,7 @@
* none is active
*/
public LinkProperties getActiveLinkProperties() {
- enforceAccessPermission();
- for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- if (mNetAttributes[type] == null || !mNetAttributes[type].isDefault()) {
- continue;
- }
- NetworkStateTracker t = mNetTrackers[type];
- NetworkInfo info = t.getNetworkInfo();
- if (info.isConnected()) {
- return t.getLinkProperties();
- }
- }
- return null;
+ return getLinkProperties(mActiveDefaultNetwork);
}
public LinkProperties getLinkProperties(int networkType) {
@@ -692,7 +665,7 @@
}
enforceChangePermission();
if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
- mNetAttributes[networkType] == null) {
+ mNetConfigs[networkType] == null) {
return Phone.APN_REQUEST_FAILED;
}
@@ -701,15 +674,10 @@
// TODO - move this into the MobileDataStateTracker
int usedNetworkType = networkType;
if(networkType == ConnectivityManager.TYPE_MOBILE) {
- if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
- TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+ usedNetworkType = convertFeatureToNetworkType(feature);
+ if (usedNetworkType < 0) {
+ Slog.e(TAG, "Can't match any netTracker!");
+ usedNetworkType = networkType;
}
}
NetworkStateTracker network = mNetTrackers[usedNetworkType];
@@ -735,9 +703,13 @@
mNetRequestersPids[usedNetworkType].add(currentPid);
}
}
- mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
- f), getRestoreDefaultNetworkDelay());
+ int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
+
+ if (restoreTimer >= 0) {
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
+ }
if ((ni.isConnectedOrConnecting() == true) &&
!network.isTeardownRequested()) {
@@ -853,15 +825,9 @@
// TODO - move to MobileDataStateTracker
int usedNetworkType = networkType;
if (networkType == ConnectivityManager.TYPE_MOBILE) {
- if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
- TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
- usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+ usedNetworkType = convertFeatureToNetworkType(feature);
+ if (usedNetworkType < 0) {
+ usedNetworkType = networkType;
}
}
tracker = mNetTrackers[usedNetworkType];
@@ -939,7 +905,7 @@
}
try {
InetAddress addr = InetAddress.getByAddress(hostAddress);
- return addHostRoute(tracker, addr);
+ return addHostRoute(tracker, addr, 0);
} catch (UnknownHostException e) {}
return false;
}
@@ -952,24 +918,49 @@
* TODO - deprecate
* @return {@code true} on success, {@code false} on failure
*/
- private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
- if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
- return false;
- }
+ private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
+ LinkProperties lp = nt.getLinkProperties();
+ if ((lp == null) || (hostAddress == null)) return false;
- LinkProperties p = nt.getLinkProperties();
- if (p == null) return false;
- String interfaceName = p.getInterfaceName();
-
+ String interfaceName = lp.getInterfaceName();
if (DBG) {
- log("Requested host route to " + hostAddress + "(" + interfaceName + ")");
+ log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
+ cycleCount);
}
- if (interfaceName != null) {
- return NetworkUtils.addHostRoute(interfaceName, hostAddress, null);
- } else {
+ if (interfaceName == null) {
if (DBG) loge("addHostRoute failed due to null interface name");
return false;
}
+
+ RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
+ InetAddress gatewayAddress = null;
+ if (bestRoute != null) {
+ gatewayAddress = bestRoute.getGateway();
+ // if the best route is ourself, don't relf-reference, just add the host route
+ if (hostAddress.equals(gatewayAddress)) gatewayAddress = null;
+ }
+ if (gatewayAddress != null) {
+ if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
+ loge("Error adding hostroute - too much recursion");
+ return false;
+ }
+ if (!addHostRoute(nt, gatewayAddress, cycleCount+1)) return false;
+ }
+
+ RouteInfo route = RouteInfo.makeHostRoute(hostAddress, gatewayAddress);
+
+ try {
+ mNetd.addRoute(interfaceName, route);
+ return true;
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+
+ // TODO support the removal of single host routes. Keep a ref count of them so we
+ // aren't over-zealous
+ private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
+ return false;
}
/**
@@ -1015,6 +1006,24 @@
return retVal;
}
+ public void setDataDependency(int networkType, boolean met) {
+ enforceChangePermission();
+ if (DBG) {
+ log("setDataDependency(" + networkType + ", " + met + ")");
+ }
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
+ (met ? ENABLED : DISABLED), networkType));
+ }
+
+ private void handleSetDependencyMet(int networkType, boolean met) {
+ if (mNetTrackers[networkType] != null) {
+ if (DBG) {
+ log("handleSetDependencyMet(" + networkType + ", " + met + ")");
+ }
+ mNetTrackers[networkType].setDependencyMet(met);
+ }
+ }
+
/**
* @see ConnectivityManager#setMobileDataEnabled(boolean)
*/
@@ -1023,7 +1032,7 @@
if (DBG) log("setMobileDataEnabled(" + enabled + ")");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
- (enabled ? ENABLED : DISABLED), 0));
+ (enabled ? ENABLED : DISABLED), 0));
}
private void handleSetMobileData(boolean enabled) {
@@ -1084,7 +1093,7 @@
* getting the disconnect for a network that we explicitly disabled
* in accordance with network preference policies.
*/
- if (!mNetAttributes[prevNetType].isDefault()) {
+ if (!mNetConfigs[prevNetType].isDefault()) {
List pids = mNetRequestersPids[prevNetType];
for (int i = 0; i<pids.size(); i++) {
Integer pid = (Integer)pids.get(i);
@@ -1109,7 +1118,7 @@
info.getExtraInfo());
}
- if (mNetAttributes[prevNetType].isDefault()) {
+ if (mNetConfigs[prevNetType].isDefault()) {
tryFailover(prevNetType);
if (mActiveDefaultNetwork != -1) {
NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
@@ -1139,7 +1148,7 @@
* Try to reconnect on all available and let them hash it out when
* more than one connects.
*/
- if (mNetAttributes[prevNetType].isDefault()) {
+ if (mNetConfigs[prevNetType].isDefault()) {
if (mActiveDefaultNetwork == prevNetType) {
mActiveDefaultNetwork = -1;
}
@@ -1149,12 +1158,12 @@
// TODO - don't filter by priority now - nice optimization but risky
// int currentPriority = -1;
// if (mActiveDefaultNetwork != -1) {
-// currentPriority = mNetAttributes[mActiveDefaultNetwork].mPriority;
+// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
// }
for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
if (checkType == prevNetType) continue;
- if (mNetAttributes[checkType] == null) continue;
- if (!mNetAttributes[checkType].isDefault()) continue;
+ if (mNetConfigs[checkType] == null) continue;
+ if (!mNetConfigs[checkType].isDefault()) continue;
// Enabling the isAvailable() optimization caused mobile to not get
// selected if it was in the middle of error handling. Specifically
@@ -1166,7 +1175,7 @@
// complete before it is really complete.
// if (!mNetTrackers[checkType].isAvailable()) continue;
-// if (currentPriority >= mNetAttributes[checkType].mPriority) continue;
+// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
NetworkStateTracker checkTracker = mNetTrackers[checkType];
NetworkInfo checkInfo = checkTracker.getNetworkInfo();
@@ -1239,7 +1248,7 @@
info.setFailover(false);
}
- if (mNetAttributes[info.getType()].isDefault()) {
+ if (mNetConfigs[info.getType()].isDefault()) {
tryFailover(info.getType());
if (mActiveDefaultNetwork != -1) {
NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
@@ -1272,6 +1281,9 @@
}
void systemReady() {
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ mNetd = INetworkManagementService.Stub.asInterface(b);
+
synchronized(this) {
mSystemReady = true;
if (mInitialBroadcast != null) {
@@ -1292,11 +1304,11 @@
// if this is a default net and other default is running
// kill the one not preferred
- if (mNetAttributes[type].isDefault()) {
+ if (mNetConfigs[type].isDefault()) {
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
if ((type != mNetworkPreference &&
- mNetAttributes[mActiveDefaultNetwork].mPriority >
- mNetAttributes[type].mPriority) ||
+ mNetConfigs[mActiveDefaultNetwork].priority >
+ mNetConfigs[type].priority) ||
mNetworkPreference == mActiveDefaultNetwork) {
// don't accept this one
if (DBG) {
@@ -1360,14 +1372,20 @@
handleDnsConfigurationChange(netType);
if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
- if (mNetAttributes[netType].isDefault()) {
+ if (mNetConfigs[netType].isDefault()) {
handleApplyDefaultProxy(netType);
addDefaultRoute(mNetTrackers[netType]);
} else {
addPrivateDnsRoutes(mNetTrackers[netType]);
}
+
+ /** Notify TetheringService if interface name has been changed. */
+ if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
+ Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+ handleTetherIfaceChange(netType);
+ }
} else {
- if (mNetAttributes[netType].isDefault()) {
+ if (mNetConfigs[netType].isDefault()) {
removeDefaultRoute(mNetTrackers[netType]);
} else {
removePrivateDnsRoutes(mNetTrackers[netType]);
@@ -1388,16 +1406,13 @@
if (interfaceName != null && !privateDnsRouteSet) {
Collection<InetAddress> dnsList = p.getDnses();
for (InetAddress dns : dnsList) {
- if (DBG) log(" adding " + dns);
- NetworkUtils.addHostRoute(interfaceName, dns, null);
+ addHostRoute(nt, dns, 0);
}
nt.privateDnsRouteSet(true);
}
}
private void removePrivateDnsRoutes(NetworkStateTracker nt) {
- // TODO - we should do this explicitly but the NetUtils api doesnt
- // support this yet - must remove all. No worse than before
LinkProperties p = nt.getLinkProperties();
if (p == null) return;
String interfaceName = p.getInterfaceName();
@@ -1407,7 +1422,17 @@
log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
" (" + interfaceName + ")");
}
- NetworkUtils.removeHostRoutes(interfaceName);
+
+ Collection<InetAddress> dnsList = p.getDnses();
+ for (InetAddress dns : dnsList) {
+ if (DBG) log(" removing " + dns);
+ RouteInfo route = RouteInfo.makeHostRoute(dns);
+ try {
+ mNetd.removeRoute(interfaceName, route);
+ } catch (Exception ex) {
+ loge("error (" + ex + ") removing dns route " + route);
+ }
+ }
nt.privateDnsRouteSet(false);
}
}
@@ -1418,14 +1443,27 @@
if (p == null) return;
String interfaceName = p.getInterfaceName();
if (TextUtils.isEmpty(interfaceName)) return;
- for (InetAddress gateway : p.getGateways()) {
- if (NetworkUtils.addHostRoute(interfaceName, gateway, null) &&
- NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
- if (DBG) {
- NetworkInfo networkInfo = nt.getNetworkInfo();
- log("addDefaultRoute for " + networkInfo.getTypeName() +
- " (" + interfaceName + "), GatewayAddr=" + gateway.getHostAddress());
+ for (RouteInfo route : p.getRoutes()) {
+ //TODO - handle non-default routes
+ if (route.isDefaultRoute()) {
+ if (DBG) log("adding default route " + route);
+ InetAddress gateway = route.getGateway();
+ if (addHostRoute(nt, gateway, 0)) {
+ try {
+ mNetd.addRoute(interfaceName, route);
+ } catch (Exception e) {
+ loge("error adding default route " + route);
+ continue;
+ }
+ if (DBG) {
+ NetworkInfo networkInfo = nt.getNetworkInfo();
+ log("addDefaultRoute for " + networkInfo.getTypeName() +
+ " (" + interfaceName + "), GatewayAddr=" +
+ gateway.getHostAddress());
+ }
+ } else {
+ loge("error adding host route for default route " + route);
}
}
}
@@ -1437,8 +1475,17 @@
if (p == null) return;
String interfaceName = p.getInterfaceName();
- if (interfaceName != null) {
- if (NetworkUtils.removeDefaultRoute(interfaceName) >= 0) {
+ if (interfaceName == null) return;
+
+ for (RouteInfo route : p.getRoutes()) {
+ //TODO - handle non-default routes
+ if (route.isDefaultRoute()) {
+ try {
+ mNetd.removeRoute(interfaceName, route);
+ } catch (Exception ex) {
+ loge("error (" + ex + ") removing default route " + route);
+ continue;
+ }
if (DBG) {
NetworkInfo networkInfo = nt.getNetworkInfo();
log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
@@ -1528,7 +1575,7 @@
{
if (DBG) log("reassessPidDns for pid " + myPid);
for(int i : mPriorityList) {
- if (mNetAttributes[i].isDefault()) {
+ if (mNetConfigs[i].isDefault()) {
continue;
}
NetworkStateTracker nt = mNetTrackers[i];
@@ -1610,7 +1657,7 @@
if (p == null) return;
Collection<InetAddress> dnses = p.getDnses();
boolean changed = false;
- if (mNetAttributes[netType].isDefault()) {
+ if (mNetConfigs[netType].isDefault()) {
int j = 1;
if (dnses.size() == 0 && mDefaultDns != null) {
String dnsString = mDefaultDns.getHostAddress();
@@ -1657,7 +1704,7 @@
}
}
- private int getRestoreDefaultNetworkDelay() {
+ private int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = SystemProperties.get(
NETWORK_RESTORE_DELAY_PROP_NAME);
if(restoreDefaultNetworkDelayStr != null &&
@@ -1667,7 +1714,14 @@
} catch (NumberFormatException e) {
}
}
- return RESTORE_DEFAULT_NETWORK_DELAY;
+ // if the system property isn't set, use the value for the apn type
+ int ret = RESTORE_DEFAULT_NETWORK_DELAY;
+
+ if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
+ (mNetConfigs[networkType] != null)) {
+ ret = mNetConfigs[networkType].restoreTime;
+ }
+ return ret;
}
@Override
@@ -1741,23 +1795,6 @@
info = (NetworkInfo) msg.obj;
int type = info.getType();
NetworkInfo.State state = info.getState();
- // only do this optimization for wifi. It going into scan mode for location
- // services generates alot of noise. Meanwhile the mms apn won't send out
- // subsequent notifications when on default cellular because it never
- // disconnects.. so only do this to wifi notifications. Fixed better when the
- // APN notifications are standardized.
- if (mNetAttributes[type].mLastState == state &&
- mNetAttributes[type].mRadio == ConnectivityManager.TYPE_WIFI) {
- if (DBG) {
- // TODO - remove this after we validate the dropping doesn't break
- // anything
- log("Dropping ConnectivityChange for " +
- info.getTypeName() + ": " +
- state + "/" + info.getDetailedState());
- }
- return;
- }
- mNetAttributes[type].mLastState = state;
if (DBG) log("ConnectivityChange for " +
info.getTypeName() + ": " +
@@ -1796,8 +1833,7 @@
break;
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
info = (NetworkInfo) msg.obj;
- type = info.getType();
- handleConnectivityChange(type);
+ handleConnectivityChange(info.getType());
break;
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
String causedBy = null;
@@ -1851,6 +1887,13 @@
case EVENT_APPLY_GLOBAL_HTTP_PROXY:
{
handleDeprecatedGlobalHttpProxy();
+ break;
+ }
+ case EVENT_SET_DEPENDENCY_MET:
+ {
+ boolean met = (msg.arg1 == ENABLED);
+ handleSetDependencyMet(msg.arg2, met);
+ break;
}
}
}
@@ -2177,6 +2220,14 @@
}
}
+ private void handleTetherIfaceChange(int type) {
+ String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();
+
+ if (isTetheringSupported()) {
+ mTethering.handleTetherIfaceChange(iface);
+ }
+ }
+
private void log(String s) {
Slog.d(TAG, s);
}
@@ -2184,4 +2235,24 @@
private void loge(String s) {
Slog.e(TAG, s);
}
+ int convertFeatureToNetworkType(String feature){
+ int networkType = -1;
+ if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_MMS;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
+ TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_DUN;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_IMS;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
+ networkType = ConnectivityManager.TYPE_MOBILE_CBS;
+ }
+ return networkType;
+ }
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 44f5df2..0b4b958 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -28,6 +28,7 @@
import android.net.INetworkManagementEventObserver;
import android.net.LinkAddress;
import android.net.NetworkUtils;
+import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.os.INetworkManagementService;
@@ -43,11 +44,16 @@
import android.content.ContentResolver;
import android.database.ContentObserver;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
import java.lang.IllegalStateException;
-
import java.net.InetAddress;
+import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
@@ -60,6 +66,9 @@
private static final boolean DBG = false;
private static final String NETD_TAG = "NetdConnector";
+ private static final int ADD = 1;
+ private static final int REMOVE = 2;
+
class NetdResponseCode {
public static final int InterfaceListResult = 110;
public static final int TetherInterfaceListResult = 111;
@@ -309,6 +318,164 @@
}
}
+ public void addRoute(String interfaceName, RouteInfo route) {
+ modifyRoute(interfaceName, ADD, route);
+ }
+
+ public void removeRoute(String interfaceName, RouteInfo route) {
+ modifyRoute(interfaceName, REMOVE, route);
+ }
+
+ private void modifyRoute(String interfaceName, int action, RouteInfo route) {
+ ArrayList<String> rsp;
+
+ StringBuilder cmd;
+
+ switch (action) {
+ case ADD:
+ {
+ cmd = new StringBuilder("interface route add " + interfaceName);
+ break;
+ }
+ case REMOVE:
+ {
+ cmd = new StringBuilder("interface route remove " + interfaceName);
+ break;
+ }
+ default:
+ throw new IllegalStateException("Unknown action type " + action);
+ }
+
+ // create triplet: dest-ip-addr prefixlength gateway-ip-addr
+ LinkAddress la = route.getDestination();
+ cmd.append(' ');
+ cmd.append(la.getAddress().getHostAddress());
+ cmd.append(' ');
+ cmd.append(la.getNetworkPrefixLength());
+ cmd.append(' ');
+ if (route.getGateway() == null) {
+ if (la.getAddress() instanceof Inet4Address) {
+ cmd.append("0.0.0.0");
+ } else {
+ cmd.append ("::0");
+ }
+ } else {
+ cmd.append(route.getGateway().getHostAddress());
+ }
+ try {
+ rsp = mConnector.doCommand(cmd.toString());
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException(
+ "Unable to communicate with native dameon to add routes - "
+ + e);
+ }
+
+ for (String line : rsp) {
+ Log.v(TAG, "add route response is " + line);
+ }
+ }
+
+ private ArrayList<String> readRouteList(String filename) {
+ FileInputStream fstream = null;
+ ArrayList<String> list = new ArrayList<String>();
+
+ try {
+ fstream = new FileInputStream(filename);
+ DataInputStream in = new DataInputStream(fstream);
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+ String s;
+
+ // throw away the title line
+
+ while (((s = br.readLine()) != null) && (s.length() != 0)) {
+ list.add(s);
+ }
+ } catch (IOException ex) {
+ // return current list, possibly empty
+ } finally {
+ if (fstream != null) {
+ try {
+ fstream.close();
+ } catch (IOException ex) {}
+ }
+ }
+
+ return list;
+ }
+
+ public RouteInfo[] getRoutes(String interfaceName) {
+ ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
+
+ // v4 routes listed as:
+ // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
+ for (String s : readRouteList("/proc/net/route")) {
+ String[] fields = s.split("\t");
+
+ if (fields.length > 7) {
+ String iface = fields[0];
+
+ if (interfaceName.equals(iface)) {
+ String dest = fields[1];
+ String gate = fields[2];
+ String flags = fields[3]; // future use?
+ String mask = fields[7];
+ try {
+ // address stored as a hex string, ex: 0014A8C0
+ InetAddress destAddr =
+ NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
+ int prefixLength =
+ NetworkUtils.netmaskIntToPrefixLength(
+ (int)Long.parseLong(mask, 16));
+ LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
+
+ // address stored as a hex string, ex 0014A8C0
+ InetAddress gatewayAddr =
+ NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
+
+ RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
+ routes.add(route);
+ } catch (Exception e) {
+ Log.e(TAG, "Error parsing route " + s + " : " + e);
+ continue;
+ }
+ }
+ }
+ }
+
+ // v6 routes listed as:
+ // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
+ for (String s : readRouteList("/proc/net/ipv6_route")) {
+ String[]fields = s.split("\\s+");
+ if (fields.length > 9) {
+ String iface = fields[9].trim();
+ if (interfaceName.equals(iface)) {
+ String dest = fields[0];
+ String prefix = fields[1];
+ String gate = fields[4];
+
+ try {
+ // prefix length stored as a hex string, ex 40
+ int prefixLength = Integer.parseInt(prefix, 16);
+
+ // address stored as a 32 char hex string
+ // ex fe800000000000000000000000000000
+ InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
+ LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
+
+ InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
+
+ RouteInfo route = new RouteInfo(linkAddress, gateAddr);
+ routes.add(route);
+ } catch (Exception e) {
+ Log.e(TAG, "Error parsing route " + s + " : " + e);
+ continue;
+ }
+ }
+ }
+ }
+ return (RouteInfo[]) routes.toArray(new RouteInfo[0]);
+ }
+
public void shutdown() {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SHUTDOWN)
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index eb14180..a8d40b7 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -546,7 +546,6 @@
}
Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Bundle data = new Bundle();
state.fillInNotifierBundle(data);
intent.putExtras(data);
@@ -586,7 +585,6 @@
}
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
if (!TextUtils.isEmpty(incomingNumber)) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
@@ -602,7 +600,6 @@
// status bar takes care of that after taking into account all of the
// required info.
Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
if (!isDataConnectivityPossible) {
intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
@@ -627,7 +624,6 @@
private void broadcastDataConnectionFailed(String reason, String apnType) {
Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
mContext.sendStickyBroadcast(intent);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 6e88490..fceaa4e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -235,6 +235,15 @@
}
break;
}
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
+ Slog.d(TAG, "Send failed, client connection lost");
+ } else {
+ Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+ }
+ mClients.remove((AsyncChannel) msg.obj);
+ break;
+ }
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, this, msg.replyTo);
@@ -312,6 +321,13 @@
}
break;
}
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1);
+ mWifiStateMachineChannel = null;
+ //Re-establish connection to state machine
+ mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
+ break;
+ }
default: {
Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg);
break;
@@ -584,7 +600,12 @@
*/
public WifiConfiguration getWifiApConfiguration() {
enforceAccessPermission();
- return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel);
+ if (mWifiStateMachineChannel != null) {
+ return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel);
+ } else {
+ Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
+ return null;
+ }
}
/**
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 5853696..ffadc65 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -49,8 +49,9 @@
import android.util.Log;
import com.android.internal.telephony.Phone;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.IState;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -122,7 +123,7 @@
// resampled each time we turn on tethering - used as cache for settings/config-val
private boolean mDunRequired; // configuration info - must use DUN apn on 3g
- private HierarchicalStateMachine mTetherMasterSM;
+ private StateMachine mTetherMasterSM;
private Notification mTetheredNotification;
@@ -667,8 +668,18 @@
return retVal;
}
+ public void handleTetherIfaceChange(String iface) {
+ // check if iface is white listed
+ for (String regex : mUpstreamIfaceRegexs) {
+ if (iface.matches(regex)) {
+ if (DEBUG) Log.d(TAG, "Tethering got Interface Change");
+ mTetherMasterSM.sendMessage(TetherMasterSM.CMD_IFACE_CHANGED, iface);
+ break;
+ }
+ }
+ }
- class TetherInterfaceSM extends HierarchicalStateMachine {
+ class TetherInterfaceSM extends StateMachine {
// notification from the master SM that it's not in tether mode
static final int CMD_TETHER_MODE_DEAD = 1;
// request from the user that it wants to tether
@@ -694,13 +705,13 @@
// the upstream connection has changed
static final int CMD_TETHER_CONNECTION_CHANGED = 12;
- private HierarchicalState mDefaultState;
+ private State mDefaultState;
- private HierarchicalState mInitialState;
- private HierarchicalState mStartingState;
- private HierarchicalState mTetheredState;
+ private State mInitialState;
+ private State mStartingState;
+ private State mTetheredState;
- private HierarchicalState mUnavailableState;
+ private State mUnavailableState;
private boolean mAvailable;
private boolean mTethered;
@@ -732,7 +743,7 @@
public String toString() {
String res = new String();
res += mIfaceName + " - ";
- HierarchicalState current = getCurrentState();
+ IState current = getCurrentState();
if (current == mInitialState) res += "InitialState";
if (current == mStartingState) res += "StartingState";
if (current == mTetheredState) res += "TetheredState";
@@ -782,7 +793,7 @@
return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
}
- class InitialState extends HierarchicalState {
+ class InitialState extends State {
@Override
public void enter() {
setAvailable(true);
@@ -812,7 +823,7 @@
}
}
- class StartingState extends HierarchicalState {
+ class StartingState extends State {
@Override
public void enter() {
setAvailable(false);
@@ -870,7 +881,7 @@
}
}
- class TetheredState extends HierarchicalState {
+ class TetheredState extends State {
@Override
public void enter() {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
@@ -1034,7 +1045,7 @@
}
}
- class UnavailableState extends HierarchicalState {
+ class UnavailableState extends State {
@Override
public void enter() {
setAvailable(false);
@@ -1064,7 +1075,7 @@
}
- class TetherMasterSM extends HierarchicalStateMachine {
+ class TetherMasterSM extends StateMachine {
// an interface SM has requested Tethering
static final int CMD_TETHER_MODE_REQUESTED = 1;
// an interface SM has unrequested Tethering
@@ -1075,6 +1086,8 @@
static final int CMD_CELL_CONNECTION_RENEW = 4;
// we don't have a valid upstream conn, check again after a delay
static final int CMD_RETRY_UPSTREAM = 5;
+ // received an indication that upstream interface has changed
+ static final int CMD_IFACE_CHANGED = 6;
// This indicates what a timeout event relates to. A state that
// sends itself a delayed timeout event and handles incoming timeout events
@@ -1082,14 +1095,14 @@
// We do not flush the old ones.
private int mSequenceNumber;
- private HierarchicalState mInitialState;
- private HierarchicalState mTetherModeAliveState;
+ private State mInitialState;
+ private State mTetherModeAliveState;
- private HierarchicalState mSetIpForwardingEnabledErrorState;
- private HierarchicalState mSetIpForwardingDisabledErrorState;
- private HierarchicalState mStartTetheringErrorState;
- private HierarchicalState mStopTetheringErrorState;
- private HierarchicalState mSetDnsForwardersErrorState;
+ private State mSetIpForwardingEnabledErrorState;
+ private State mSetIpForwardingDisabledErrorState;
+ private State mStartTetheringErrorState;
+ private State mStopTetheringErrorState;
+ private State mSetDnsForwardersErrorState;
private ArrayList mNotifyList;
@@ -1125,7 +1138,7 @@
setInitialState(mInitialState);
}
- class TetherMasterUtilState extends HierarchicalState {
+ class TetherMasterUtilState extends State {
protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
@@ -1428,19 +1441,24 @@
turnOnMobileConnection();
}
break;
- case CMD_RETRY_UPSTREAM:
- chooseUpstreamType(mTryCell);
- mTryCell = !mTryCell;
- break;
- default:
- retValue = false;
- break;
+ case CMD_RETRY_UPSTREAM:
+ chooseUpstreamType(mTryCell);
+ mTryCell = !mTryCell;
+ break;
+ case CMD_IFACE_CHANGED:
+ String iface = (String)message.obj;
+ if (DEBUG) Log.d(TAG, "Activie upstream interface changed: " + iface);
+ notifyTetheredOfNewUpstreamIface(iface);
+ break;
+ default:
+ retValue = false;
+ break;
}
return retValue;
}
}
- class ErrorState extends HierarchicalState {
+ class ErrorState extends State {
int mErrorNotification;
@Override
public boolean processMessage(Message message) {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 290f2c1..fce7cdc 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -91,6 +91,12 @@
public static final int RADIO_TECHNOLOGY_HSPA = 11;
/** @hide */
public static final int RADIO_TECHNOLOGY_EVDO_B = 12;
+ /** @hide */
+ public static final int RADIO_TECHNOLOGY_EHRPD = 13;
+ /** @hide */
+ public static final int RADIO_TECHNOLOGY_LTE = 14;
+ /** @hide */
+ public static final int RADIO_TECHNOLOGY_HSPAP = 15;
/**
* Available registration states for GSM, UMTS and CDMA.
@@ -381,53 +387,77 @@
&& mIsEmergencyOnly == s.mIsEmergencyOnly);
}
+ /**
+ * Convert radio technology to String
+ *
+ * @param radioTechnology
+ * @return String representation of the RAT
+ *
+ * @hide
+ */
+ public static String radioTechnologyToString(int rt) {
+ String rtString;
+
+ switch(rt) {
+ case 0:
+ rtString = "Unknown";
+ break;
+ case 1:
+ rtString = "GPRS";
+ break;
+ case 2:
+ rtString = "EDGE";
+ break;
+ case 3:
+ rtString = "UMTS";
+ break;
+ case 4:
+ rtString = "CDMA-IS95A";
+ break;
+ case 5:
+ rtString = "CDMA-IS95B";
+ break;
+ case 6:
+ rtString = "1xRTT";
+ break;
+ case 7:
+ rtString = "EvDo-rev.0";
+ break;
+ case 8:
+ rtString = "EvDo-rev.A";
+ break;
+ case 9:
+ rtString = "HSDPA";
+ break;
+ case 10:
+ rtString = "HSUPA";
+ break;
+ case 11:
+ rtString = "HSPA";
+ break;
+ case 12:
+ rtString = "EvDo-rev.B";
+ break;
+ case 13:
+ rtString = "eHRPD";
+ break;
+ case 14:
+ rtString = "LTE";
+ break;
+ case 15:
+ rtString = "HSPAP";
+ break;
+ default:
+ rtString = "Unexpected";
+ Log.w(LOG_TAG, "Unexpected radioTechnology=" + rt);
+ break;
+ }
+ return rtString + ":" + rt;
+ }
+
@Override
public String toString() {
- String radioTechnology = new String("Error in radioTechnology");
- switch(this.mRadioTechnology) {
- case 0:
- radioTechnology = "Unknown";
- break;
- case 1:
- radioTechnology = "GPRS";
- break;
- case 2:
- radioTechnology = "EDGE";
- break;
- case 3:
- radioTechnology = "UMTS";
- break;
- case 4:
- radioTechnology = "IS95A";
- break;
- case 5:
- radioTechnology = "IS95B";
- break;
- case 6:
- radioTechnology = "1xRTT";
- break;
- case 7:
- radioTechnology = "EvDo rev. 0";
- break;
- case 8:
- radioTechnology = "EvDo rev. A";
- break;
- case 9:
- radioTechnology = "HSDPA";
- break;
- case 10:
- radioTechnology = "HSUPA";
- break;
- case 11:
- radioTechnology = "HSPA";
- break;
- case 12:
- radioTechnology = "EvDo rev. B";
- break;
- default:
- Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
- break;
- }
+ String radioTechnology = radioTechnologyToString(mRadioTechnology);
return (mState + " " + (mRoaming ? "roaming" : "home")
+ " " + mOperatorAlphaLong
@@ -536,7 +566,7 @@
*
* @hide
*/
- public void setCdmaEriText(String longName) {
+ public void setOperatorAlphaLong(String longName) {
mOperatorAlphaLong = longName;
}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 1767dd9..a88825b 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -556,10 +556,7 @@
* @hide
*/
public int getLteDbm() {
- log("TODO: teach getLteDbm to compute dBm properly");
- int level = -1;
- if (DBG) log("getLteDbm=" + level);
- return level;
+ return mLteRsrp;
}
/**
@@ -568,22 +565,33 @@
* @hide
*/
public int getLteLevel() {
- log("TODO: teach getLteLevel to compute Level properly");
- int level = SIGNAL_STRENGTH_MODERATE;
- if (DBG) log("getLteLevel=" + level);
- return level;
+ int levelLteRsrp = 0;
+
+ if (mLteRsrp == -1) levelLteRsrp = 0;
+ else if (mLteRsrp >= -85) levelLteRsrp = SIGNAL_STRENGTH_GREAT;
+ else if (mLteRsrp >= -95) levelLteRsrp = SIGNAL_STRENGTH_GOOD;
+ else if (mLteRsrp >= -105) levelLteRsrp = SIGNAL_STRENGTH_MODERATE;
+ else if (mLteRsrp >= -115) levelLteRsrp = SIGNAL_STRENGTH_POOR;
+ else levelLteRsrp = 0;
+
+ if (DBG) log("Lte level: "+levelLteRsrp);
+ return levelLteRsrp;
}
/**
- * Get the LTE signal level as an asu value between 0..31, 99 is unknown
+ * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+ * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
*
* @hide
*/
public int getLteAsuLevel() {
- log("TODO: teach getLteAsuLevel to compute asu Level properly");
- int level = 4;
- if (DBG) log("getLteAsuLevel=" + level);
- return level;
+ int lteAsuLevel = 99;
+ int lteDbm = getLteDbm();
+ if (lteDbm <= -140) lteAsuLevel = 0;
+ else if (lteDbm >= -43) lteAsuLevel = 97;
+ else lteAsuLevel = lteDbm + 140;
+ if (DBG) log("Lte Asu level: "+lteAsuLevel);
+ return lteAsuLevel;
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3af9462..36e0202 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -30,7 +30,6 @@
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;
import java.util.List;
@@ -636,6 +635,28 @@
}
}
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link Phone#LTE_ON_CDMA_TRUE}
+ *
+ * @hide
+ */
+ public int getLteOnCdmaMode() {
+ try {
+ return getITelephony().getLteOnCdmaMode();
+ } catch (RemoteException ex) {
+ // Assume no ICC card if remote exception which shouldn't happen
+ return Phone.LTE_ON_CDMA_UNKNOWN;
+ } catch (NullPointerException ex) {
+ // This could happen before phone restarts due to crashing
+ return Phone.LTE_ON_CDMA_UNKNOWN;
+ }
+ }
+
//
//
// Subscriber Info
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
new file mode 100644
index 0000000..496c43c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Maintain the Apn context
+ */
+public class ApnContext {
+
+ public final String LOG_TAG;
+
+ protected static final boolean DBG = true;
+
+ private final String mApnType;
+
+ private DataConnectionTracker.State mState;
+
+ private ArrayList<ApnSetting> mWaitingApns = null;
+
+ /** A zero indicates that all waiting APNs had a permanent error */
+ private AtomicInteger mWaitingApnsPermanentFailureCountDown;
+
+ private ApnSetting mApnSetting;
+
+ DataConnection mDataConnection;
+
+ DataConnectionAc mDataConnectionAc;
+
+ String mReason;
+
+ PendingIntent mReconnectIntent;
+
+ /**
+ * user/app requested connection on this APN
+ */
+ AtomicBoolean mDataEnabled;
+
+ /**
+ * carrier requirements met
+ */
+ AtomicBoolean mDependencyMet;
+
+ public ApnContext(String apnType, String logTag) {
+ mApnType = apnType;
+ mState = DataConnectionTracker.State.IDLE;
+ setReason(Phone.REASON_DATA_ENABLED);
+ mDataEnabled = new AtomicBoolean(false);
+ mDependencyMet = new AtomicBoolean(true);
+ mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0);
+ LOG_TAG = logTag;
+ }
+
+ public String getApnType() {
+ return mApnType;
+ }
+
+ public synchronized DataConnection getDataConnection() {
+ return mDataConnection;
+ }
+
+ public synchronized void setDataConnection(DataConnection dataConnection) {
+ mDataConnection = dataConnection;
+ }
+
+
+ public synchronized DataConnectionAc getDataConnectionAc() {
+ return mDataConnectionAc;
+ }
+
+ public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
+ mDataConnectionAc = dcac;
+ }
+
+ public synchronized ApnSetting getApnSetting() {
+ return mApnSetting;
+ }
+
+ public synchronized void setApnSetting(ApnSetting apnSetting) {
+ mApnSetting = apnSetting;
+ }
+
+ public synchronized void setWaitingApns(ArrayList<ApnSetting> waitingApns) {
+ mWaitingApns = waitingApns;
+ mWaitingApnsPermanentFailureCountDown.set(mWaitingApns.size());
+ }
+
+ public int getWaitingApnsPermFailCount() {
+ return mWaitingApnsPermanentFailureCountDown.get();
+ }
+
+ public void decWaitingApnsPermFailCount() {
+ mWaitingApnsPermanentFailureCountDown.decrementAndGet();
+ }
+
+ public synchronized ApnSetting getNextWaitingApn() {
+ ArrayList<ApnSetting> list = mWaitingApns;
+ ApnSetting apn = null;
+
+ if (list != null) {
+ if (!list.isEmpty()) {
+ apn = list.get(0);
+ }
+ }
+ return apn;
+ }
+
+ public synchronized void removeNextWaitingApn() {
+ if ((mWaitingApns != null) && (!mWaitingApns.isEmpty())) {
+ mWaitingApns.remove(0);
+ }
+ }
+
+ public synchronized ArrayList<ApnSetting> getWaitingApns() {
+ return mWaitingApns;
+ }
+
+ public synchronized void setState(DataConnectionTracker.State s) {
+ if (DBG) {
+ log("setState: " + s + " for type " + mApnType + ", previous state:" + mState);
+ }
+
+ mState = s;
+
+ if (mState == DataConnectionTracker.State.FAILED) {
+ if (mWaitingApns != null) {
+ mWaitingApns.clear(); // when teardown the connection and set to IDLE
+ }
+ }
+ }
+
+ public synchronized DataConnectionTracker.State getState() {
+ return mState;
+ }
+
+ public synchronized void setReason(String reason) {
+ if (DBG) {
+ log("set reason as " + reason + ", for type " + mApnType + ",current state " + mState);
+ }
+ mReason = reason;
+ }
+
+ public synchronized String getReason() {
+ return mReason;
+ }
+
+ public synchronized void setReconnectIntent(PendingIntent intent) {
+ if (DBG)
+ log("set ReconnectIntent for type " + mApnType);
+ mReconnectIntent = intent;
+ }
+
+ public synchronized PendingIntent getReconnectIntent() {
+ return mReconnectIntent;
+ }
+
+ public boolean isReady() {
+ return mDataEnabled.get() && mDependencyMet.get();
+ }
+
+ public void setEnabled(boolean enabled) {
+ if (DBG) {
+ log("set enabled as " + enabled + ", for type " +
+ mApnType + ", current state is " + mDataEnabled.get());
+ }
+ mDataEnabled.set(enabled);
+ }
+
+ public boolean isEnabled() {
+ return mDataEnabled.get();
+ }
+
+ public void setDependencyMet(boolean met) {
+ if (DBG) {
+ log("set mDependencyMet as " + met + ", for type " + mApnType +
+ ", current state is " + mDependencyMet.get());
+ }
+ mDependencyMet.set(met);
+ }
+
+ public boolean getDependencyMet() {
+ return mDependencyMet.get();
+ }
+
+ @Override
+ public String toString() {
+ return "state=" + getState() + " apnType=" + mApnType;
+ }
+
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[ApnContext] " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/ApnSetting.java b/telephony/java/com/android/internal/telephony/ApnSetting.java
index 20dbaf3..b88bcf7 100644
--- a/telephony/java/com/android/internal/telephony/ApnSetting.java
+++ b/telephony/java/com/android/internal/telephony/ApnSetting.java
@@ -23,21 +23,21 @@
static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
- 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;
- public int id;
- public String numeric;
- public String protocol;
- public String roamingProtocol;
+ public final String carrier;
+ public final String apn;
+ public final String proxy;
+ public final String port;
+ public final String mmsc;
+ public final String mmsProxy;
+ public final String mmsPort;
+ public final String user;
+ public final String password;
+ public final int authType;
+ public final String[] types;
+ public final int id;
+ public final String numeric;
+ public final String protocol;
+ public final String roamingProtocol;
public ApnSetting(int id, String numeric, String carrier, String apn,
String proxy, String port,
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 9b19600..13afbb7 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -22,9 +22,15 @@
import android.os.Registrant;
import android.os.Handler;
import android.os.AsyncResult;
+import android.os.SystemProperties;
import android.util.Config;
import android.util.Log;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* {@hide}
*/
@@ -34,6 +40,9 @@
//***** Instance Variables
protected Context mContext;
protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
+ protected RadioState mSimState = RadioState.RADIO_UNAVAILABLE;
+ protected RadioState mRuimState = RadioState.RADIO_UNAVAILABLE;
+ protected RadioState mNvState = RadioState.RADIO_UNAVAILABLE;
protected Object mStateMonitor = new Object();
protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
@@ -68,6 +77,8 @@
protected RegistrantList mCdmaSubscriptionChangedRegistrants = new RegistrantList();
protected RegistrantList mCdmaPrlChangedRegistrants = new RegistrantList();
protected RegistrantList mExitEmergencyCallbackModeRegistrants = new RegistrantList();
+ protected RegistrantList mRilConnectedRegistrants = new RegistrantList();
+ protected RegistrantList mIccRefreshRegistrants = new RegistrantList();
protected Registrant mSMSRegistrant;
protected Registrant mNITZTimeRegistrant;
@@ -82,18 +93,20 @@
protected Registrant mCatCallSetUpRegistrant;
protected Registrant mIccSmsFullRegistrant;
protected Registrant mEmergencyCallbackModeRegistrant;
- protected Registrant mIccRefreshRegistrant;
protected Registrant mRingRegistrant;
protected Registrant mRestrictedStateRegistrant;
protected Registrant mGsmBroadcastSmsRegistrant;
- // Network Mode received from PhoneFactory
- protected int mNetworkMode;
+ // Preferred network type received from PhoneFactory.
+ // This is used when establishing a connection to the
+ // vendor ril so it starts up in the correct mode.
+ protected int mPreferredNetworkType;
// CDMA subscription received from PhoneFactory
protected int mCdmaSubscription;
// Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
protected int mPhoneType;
-
+ // RIL Version
+ protected int mRilVersion = -1;
public BaseCommands(Context context) {
mContext = context; // May be null (if so we won't log statistics)
@@ -105,6 +118,18 @@
return mState;
}
+ public RadioState getSimState() {
+ return mSimState;
+ }
+
+ public RadioState getRuimState() {
+ return mRuimState;
+ }
+
+ public RadioState getNvState() {
+ return mNvState;
+ }
+
public void registerForRadioStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
@@ -200,7 +225,7 @@
synchronized (mStateMonitor) {
mSIMReadyRegistrants.add(r);
- if (mState.isSIMReady()) {
+ if (mSimState.isSIMReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -219,7 +244,7 @@
synchronized (mStateMonitor) {
mRUIMReadyRegistrants.add(r);
- if (mState.isRUIMReady()) {
+ if (mRuimState.isRUIMReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -238,7 +263,7 @@
synchronized (mStateMonitor) {
mNVReadyRegistrants.add(r);
- if (mState.isNVReady()) {
+ if (mNvState.isNVReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -256,7 +281,7 @@
synchronized (mStateMonitor) {
mSIMLockedRegistrants.add(r);
- if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+ if (mSimState == RadioState.SIM_LOCKED_OR_ABSENT) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -274,7 +299,7 @@
synchronized (mStateMonitor) {
mRUIMLockedRegistrants.add(r);
- if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+ if (mRuimState == RadioState.RUIM_LOCKED_OR_ABSENT) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -438,16 +463,23 @@
mIccSmsFullRegistrant.clear();
}
+ public void registerForIccRefresh(Handler h, int what, Object obj) {
+ Registrant r = new Registrant (h, what, obj);
+ mIccRefreshRegistrants.add(r);
+ }
public void setOnIccRefresh(Handler h, int what, Object obj) {
- mIccRefreshRegistrant = new Registrant (h, what, obj);
+ registerForIccRefresh(h, what, obj);
}
public void setEmergencyCallbackMode(Handler h, int what, Object obj) {
mEmergencyCallbackModeRegistrant = new Registrant (h, what, obj);
}
- public void unSetOnIccRefresh(Handler h) {
- mIccRefreshRegistrant.clear();
+ public void unregisterForIccRefresh(Handler h) {
+ mIccRefreshRegistrants.remove(h);
+ }
+ public void unsetOnIccRefresh(Handler h) {
+ unregisterForIccRefresh(h);
}
public void setOnCallRing(Handler h, int what, Object obj) {
@@ -624,6 +656,25 @@
mExitEmergencyCallbackModeRegistrants.remove(h);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void registerForRilConnected(Handler h, int what, Object obj) {
+ Log.d(LOG_TAG, "registerForRilConnected h=" + h + " w=" + what);
+ Registrant r = new Registrant (h, what, obj);
+ mRilConnectedRegistrants.add(r);
+ if (mRilVersion != -1) {
+ Log.d(LOG_TAG, "Notifying: ril connected mRilVersion=" + mRilVersion);
+ r.notifyRegistrant(new AsyncResult(null, new Integer(mRilVersion), null));
+ }
+ }
+
+ @Override
+ public void unregisterForRilConnected(Handler h) {
+ mRilConnectedRegistrants.remove(h);
+ }
+
//***** Protected Methods
/**
* Store new RadioState and send notification based on the changes
@@ -653,6 +704,22 @@
return;
}
+ // FIXME: Use Constants or Enums
+ if(mState.getType() == 0) {
+ mSimState = mState;
+ mRuimState = mState;
+ mNvState = mState;
+ }
+ else if (mState.getType() == 1) {
+ mSimState = mState;
+ }
+ else if (mState.getType() == 2) {
+ mRuimState = mState;
+ }
+ else if (mState.getType() == 3) {
+ mNvState = mState;
+ }
+
mRadioStateChangedRegistrants.notifyRegistrants();
if (mState.isAvailable() && !oldState.isAvailable()) {
@@ -733,4 +800,81 @@
protected void onRadioAvailable() {
}
+
+ /**
+ * The contents of the /proc/cmdline file
+ */
+ private static String getProcCmdLine()
+ {
+ String cmdline = "";
+ FileInputStream is = null;
+ try {
+ is = new FileInputStream("/proc/cmdline");
+ byte [] buffer = new byte[2048];
+ int count = is.read(buffer);
+ if (count > 0) {
+ cmdline = new String(buffer, 0, count);
+ }
+ } catch (IOException e) {
+ Log.d(LOG_TAG, "No /proc/cmdline exception=" + e);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ Log.d(LOG_TAG, "/proc/cmdline=" + cmdline);
+ return cmdline;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getLteOnCdmaMode() {
+ return getLteOnCdmaModeStatic();
+ }
+
+ /** Kernel command line */
+ private static final String sKernelCmdLine = getProcCmdLine();
+
+ /** Pattern for selecting the product type from the kernel command line */
+ private static final Pattern sProductTypePattern =
+ Pattern.compile("\\sproduct_type\\s*=\\s*(\\w+)");
+
+ /** The ProductType used for LTE on CDMA devices */
+ private static final String sLteOnCdmaProductType =
+ SystemProperties.get(TelephonyProperties.PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE, "");
+
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link Phone#LTE_ON_CDMA_TRUE}
+ */
+ public static int getLteOnCdmaModeStatic() {
+ int retVal;
+ String productType;
+
+ Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);
+ if (matcher.find()) {
+ productType = matcher.group(1);
+ if (sLteOnCdmaProductType.equals(productType)) {
+ retVal = Phone.LTE_ON_CDMA_TRUE;
+ } else {
+ retVal = Phone.LTE_ON_CDMA_FALSE;
+ }
+ } else {
+ retVal = Phone.LTE_ON_CDMA_FALSE;
+ productType = "";
+ }
+
+ Log.d(LOG_TAG, "getLteOnCdmaMode=" + retVal + " product_type='" + productType +
+ "' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'");
+ return retVal;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/CallTracker.java b/telephony/java/com/android/internal/telephony/CallTracker.java
index 9619a66..31f9e18 100644
--- a/telephony/java/com/android/internal/telephony/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/CallTracker.java
@@ -119,6 +119,10 @@
//***** Overridden from Handler
public abstract void handleMessage (Message msg);
+ public abstract void registerForVoiceCallStarted(Handler h, int what, Object obj);
+ public abstract void unregisterForVoiceCallStarted(Handler h);
+ public abstract void registerForVoiceCallEnded(Handler h, int what, Object obj);
+ public abstract void unregisterForVoiceCallEnded(Handler h);
protected abstract void log(String msg);
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index ad21a18..b68cbe9 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -20,6 +20,7 @@
import android.os.Message;
import android.os.Handler;
+import android.os.SystemProperties;
/**
@@ -27,18 +28,18 @@
*/
public interface CommandsInterface {
enum RadioState {
- 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 */
- SIM_READY, /* Radio is on and SIM interface is available */
- RUIM_NOT_READY, /* Radio is on, but the RUIM interface is not ready */
- RUIM_READY, /* Radio is on and the RUIM interface is available */
- RUIM_LOCKED_OR_ABSENT, /* RUIM PIN locked, PUK required, network
- personalization locked, or RUIM absent */
- NV_NOT_READY, /* Radio is on, but the NV interface is not available */
- NV_READY; /* Radio is on and the NV interface is available */
+ RADIO_OFF(0), /* Radio explictly powered off (eg CFUN=0) */
+ RADIO_UNAVAILABLE(0), /* Radio unavailable (eg, resetting or not booted) */
+ SIM_NOT_READY(1), /* Radio is on, but the SIM interface is not ready */
+ SIM_LOCKED_OR_ABSENT(1), /* SIM PIN locked, PUK required, network
+ personalization, or SIM absent */
+ SIM_READY(1), /* Radio is on and SIM interface is available */
+ RUIM_NOT_READY(2), /* Radio is on, but the RUIM interface is not ready */
+ RUIM_READY(2), /* Radio is on and the RUIM interface is available */
+ RUIM_LOCKED_OR_ABSENT(2), /* RUIM PIN locked, PUK required, network
+ personalization locked, or RUIM absent */
+ NV_NOT_READY(3), /* Radio is on, but the NV interface is not available */
+ NV_READY(3); /* Radio is on and the NV interface is available */
public boolean isOn() /* and available...*/ {
return this == SIM_NOT_READY
@@ -50,6 +51,14 @@
|| this == NV_NOT_READY
|| this == NV_READY;
}
+ private int stateType;
+ private RadioState (int type) {
+ stateType = type;
+ }
+
+ public int getType() {
+ return stateType;
+ }
public boolean isAvailable() {
return this != RADIO_UNAVAILABLE;
@@ -68,17 +77,25 @@
}
public boolean isGsm() {
- return this == SIM_NOT_READY
- || this == SIM_LOCKED_OR_ABSENT
- || this == SIM_READY;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ return false;
+ } else {
+ return this == SIM_NOT_READY
+ || this == SIM_LOCKED_OR_ABSENT
+ || this == SIM_READY;
+ }
}
public boolean isCdma() {
- return this == RUIM_NOT_READY
- || this == RUIM_READY
- || this == RUIM_LOCKED_OR_ABSENT
- || this == NV_NOT_READY
- || this == NV_READY;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ return true;
+ } else {
+ return this == RUIM_NOT_READY
+ || this == RUIM_READY
+ || this == RUIM_LOCKED_OR_ABSENT
+ || this == NV_NOT_READY
+ || this == NV_READY;
+ }
}
}
@@ -153,6 +170,9 @@
//***** Methods
RadioState getRadioState();
+ RadioState getSimState();
+ RadioState getRuimState();
+ RadioState getNvState();
/**
* Fires on any RadioState transition
@@ -214,6 +234,9 @@
void registerForSIMLockedOrAbsent(Handler h, int what, Object obj);
void unregisterForSIMLockedOrAbsent(Handler h);
+ void registerForIccStatusChanged(Handler h, int what, Object obj);
+ void unregisterForIccStatusChanged(Handler h);
+
void registerForCallStateChanged(Handler h, int what, Object obj);
void unregisterForCallStateChanged(Handler h);
void registerForVoiceNetworkStateChanged(Handler h, int what, Object obj);
@@ -330,14 +353,16 @@
/**
* Sets the handler for SIM Refresh notifications.
- * Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
+ void registerForIccRefresh(Handler h, int what, Object obj);
+ void unregisterForIccRefresh(Handler h);
+
void setOnIccRefresh(Handler h, int what, Object obj);
- void unSetOnIccRefresh(Handler h);
+ void unsetOnIccRefresh(Handler h);
/**
* Sets the handler for RING notifications.
@@ -582,6 +607,20 @@
void registerForExitEmergencyCallbackMode(Handler h, int what, Object obj);
void unregisterForExitEmergencyCallbackMode(Handler h);
+ /**
+ * Registers the handler for RIL_UNSOL_RIL_CONNECT events.
+ *
+ * When ril connects or disconnects a message is sent to the registrant
+ * which contains an AsyncResult, ar, in msg.obj. The ar.result is an
+ * Integer which is the version of the ril or -1 if the ril disconnected.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ void registerForRilConnected(Handler h, int what, Object obj);
+ void unregisterForRilConnected(Handler h);
+
/**
* Supply the ICC PIN to the ICC card
*
@@ -1419,6 +1458,12 @@
void setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response);
/**
+ * Requests to get the CDMA subscription srouce
+ * @param response is callback message
+ */
+ void getCdmaSubscriptionSource(Message response);
+
+ /**
* Set the TTY mode
*
* @param ttyMode one of the following:
@@ -1528,4 +1573,14 @@
* Callback message containing {@link IccCardStatus} structure for the card.
*/
public void getIccCardStatus(Message result);
+
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link Phone#LTE_ON_CDMA_TRUE}
+ */
+ public int getLteOnCdmaMode();
}
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index fda1e47..1d67d45 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -17,11 +17,27 @@
package com.android.internal.telephony;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.net.RouteInfo;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.internal.telephony.DataConnection.FailCause;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
* This is RIL_Data_Call_Response_v5 from ril.h
* TODO: Rename to DataCallResponse.
*/
public class DataCallState {
+ private final boolean DBG = true;
+ private final String LOG_TAG = "GSM";
+
public int version = 0;
public int status = 0;
public int cid = 0;
@@ -32,6 +48,29 @@
public String [] dnses = new String[0];
public String[] gateways = new String[0];
+ /**
+ * Class returned by onSetupConnectionCompleted.
+ */
+ protected enum SetupResult {
+ SUCCESS,
+ ERR_BadCommand,
+ ERR_UnacceptableParameter,
+ ERR_GetLastErrorFromRil,
+ ERR_Stale,
+ ERR_RilError;
+
+ public FailCause mFailCause;
+
+ SetupResult() {
+ mFailCause = FailCause.fromInt(0);
+ }
+
+ @Override
+ public String toString() {
+ return name() + " SetupResult.mFailCause=" + mFailCause;
+ }
+ }
+
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
@@ -63,4 +102,125 @@
sb.append("]}");
return sb.toString();
}
+
+ public SetupResult setLinkProperties(LinkProperties linkProperties,
+ boolean okToUseSystemPropertyDns) {
+ SetupResult result;
+
+ // Start with clean network properties and if we have
+ // a failure we'll clear again at the bottom of this code.
+ if (linkProperties == null)
+ linkProperties = new LinkProperties();
+ else
+ linkProperties.clear();
+
+ if (status == FailCause.NONE.getErrorCode()) {
+ String propertyPrefix = "net." + ifname + ".";
+
+ try {
+ // set interface name
+ linkProperties.setInterfaceName(ifname);
+
+ // set link addresses
+ if (addresses != null && addresses.length > 0) {
+ for (String addr : addresses) {
+ LinkAddress la;
+ int addrPrefixLen;
+
+ String [] ap = addr.split("/");
+ if (ap.length == 2) {
+ addr = ap[0];
+ addrPrefixLen = Integer.parseInt(ap[1]);
+ } else {
+ addrPrefixLen = 0;
+ }
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(addr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric ip addr=" + addr);
+ }
+ if (addrPrefixLen == 0) {
+ // Assume point to point
+ addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
+ }
+ if (DBG) Log.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
+ la = new LinkAddress(ia, addrPrefixLen);
+ linkProperties.addLinkAddress(la);
+ }
+ } else {
+ throw new UnknownHostException("no address for ifname=" + ifname);
+ }
+
+ // set dns servers
+ if (dnses != null && dnses.length > 0) {
+ for (String addr : dnses) {
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(addr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric dns addr=" + addr);
+ }
+ linkProperties.addDns(ia);
+ }
+ } else if (okToUseSystemPropertyDns){
+ String dnsServers[] = new String[2];
+ dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
+ dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
+ for (String dnsAddr : dnsServers) {
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(dnsAddr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric dns addr="
+ + dnsAddr);
+ }
+ linkProperties.addDns(ia);
+ }
+ } else {
+ throw new UnknownHostException("Empty dns response and no system default dns");
+ }
+
+ // set gateways
+ if ((gateways == null) || (gateways.length == 0)) {
+ String sysGateways = SystemProperties.get(propertyPrefix + "gw");
+ if (sysGateways != null) {
+ gateways = sysGateways.split(" ");
+ } else {
+ gateways = new String[0];
+ }
+ }
+ for (String addr : gateways) {
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(addr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric gateway addr=" + addr);
+ }
+ linkProperties.addRoute(new RouteInfo(ia));
+ }
+
+ result = SetupResult.SUCCESS;
+ } catch (UnknownHostException e) {
+ Log.d(LOG_TAG, "onSetupCompleted: UnknownHostException " + e);
+ e.printStackTrace();
+ result = SetupResult.ERR_UnacceptableParameter;
+ }
+ } else {
+ if (version < 4) {
+ result = SetupResult.ERR_GetLastErrorFromRil;
+ } else {
+ result = SetupResult.ERR_RilError;
+ }
+ }
+
+ // An error occurred so clear properties
+ if (result != SetupResult.SUCCESS) {
+ if(DBG) Log.d(LOG_TAG,
+ "onSetupConnectionCompleted with an error, clearing LinkProperties");
+ linkProperties.clear();
+ }
+
+ return result;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 89513fd..c21a96a 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -17,27 +17,32 @@
package com.android.internal.telephony;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkUtils;
+import android.net.ProxyProperties;
import android.os.AsyncResult;
+import android.os.Bundle;
import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.SystemProperties;
import android.text.TextUtils;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* {@hide}
*
- * DataConnection HierarchicalStateMachine.
+ * DataConnection StateMachine.
*
* This is an abstract base class for representing a single data connection.
* Instances of this class such as <code>CdmaDataConnection</code> and
@@ -55,34 +60,14 @@
*
* The other public methods are provided for debugging.
*/
-public abstract class DataConnection extends HierarchicalStateMachine {
+public abstract class DataConnection extends StateMachine {
protected static final boolean DBG = true;
+ protected static final boolean VDBG = false;
protected static Object mCountLock = new Object();
protected static int mCount;
+ protected AsyncChannel mAc;
- /**
- * Class returned by onSetupConnectionCompleted.
- */
- protected enum SetupResult {
- SUCCESS,
- ERR_BadCommand,
- ERR_UnacceptableParameter,
- ERR_GetLastErrorFromRil,
- ERR_Stale,
- ERR_RilError;
-
- public FailCause mFailCause;
-
- SetupResult() {
- mFailCause = FailCause.fromInt(0);
- }
-
- @Override
- public String toString() {
- return name() + " SetupResult.mFailCause=" + mFailCause;
- }
- }
/**
* Used internally for saving connecting parameters.
@@ -99,26 +84,16 @@
}
/**
- * An instance used for notification of blockingReset.
- * TODO: Remove when blockingReset is removed.
- */
- class ResetSynchronouslyLock {
- }
-
- /**
* Used internally for saving disconnecting parameters.
*/
protected static class DisconnectParams {
- public DisconnectParams(Message onCompletedMsg) {
+ public DisconnectParams(String reason, Message onCompletedMsg) {
+ this.reason = reason;
this.onCompletedMsg = onCompletedMsg;
}
- public DisconnectParams(ResetSynchronouslyLock lockObj) {
- this.lockObj = lockObj;
- }
-
public int tag;
+ public String reason;
public Message onCompletedMsg;
- public ResetSynchronouslyLock lockObj;
}
/**
@@ -167,7 +142,7 @@
static {
sErrorCodeToFailCauseMap = new HashMap<Integer, FailCause>();
for (FailCause fc : values()) {
- sErrorCodeToFailCauseMap.put(fc.ordinal(), fc);
+ sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
}
}
@@ -208,21 +183,22 @@
}
// ***** Event codes for driving the state machine
- protected static final int EVENT_RESET = 1;
- protected static final int EVENT_CONNECT = 2;
- protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3;
- protected static final int EVENT_GET_LAST_FAIL_DONE = 4;
- protected static final int EVENT_DEACTIVATE_DONE = 5;
- protected static final int EVENT_DISCONNECT = 6;
+ protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
+ protected static final int EVENT_CONNECT = BASE + 0;
+ protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
+ protected static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
+ protected static final int EVENT_DEACTIVATE_DONE = BASE + 3;
+ protected static final int EVENT_DISCONNECT = BASE + 4;
+ protected static final int EVENT_RIL_CONNECTED = BASE + 5;
//***** Tag IDs for EventLog
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
//***** Member Variables
- protected int mId;
+ protected ApnSetting mApn;
protected int mTag;
protected PhoneBase phone;
- protected RetryManager mRetryMgr;
+ protected int mRilVersion = -1;
protected int cid;
protected LinkProperties mLinkProperties = new LinkProperties();
protected LinkCapabilities mCapabilities = new LinkCapabilities();
@@ -230,6 +206,7 @@
protected long lastFailTime;
protected FailCause lastFailCause;
protected static final String NULL_IP = "0.0.0.0";
+ private int mRefCount;
Object userData;
//***** Abstract methods
@@ -244,10 +221,11 @@
//***** Constructor
- protected DataConnection(PhoneBase phone, String name, RetryManager rm) {
+ protected DataConnection(PhoneBase phone, String name, int id, RetryManager rm) {
super(name);
if (DBG) log("DataConnection constructor E");
this.phone = phone;
+ mId = id;
mRetryMgr = rm;
this.cid = -1;
clearSettings();
@@ -274,10 +252,10 @@
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 (TextUtils.equals(dp.reason, Phone.REASON_RADIO_TURNED_OFF)) {
+ discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
+ } else if (TextUtils.equals(dp.reason, Phone.REASON_PDP_RESET)) {
+ discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
}
}
if (phone.mCM.getRadioState().isOn()) {
@@ -313,7 +291,7 @@
lastFailTime = timeStamp;
AsyncResult.forMessage(connectionCompletedMsg, cause, new Exception());
}
- if (DBG) log("notifyConnection at " + timeStamp + " cause=" + cause);
+ if (DBG) log("notifyConnectionCompleted at " + timeStamp + " cause=" + cause);
connectionCompletedMsg.sendToTarget();
}
@@ -324,39 +302,140 @@
* @param dp is the DisconnectParams.
*/
private void notifyDisconnectCompleted(DisconnectParams dp) {
- if (DBG) log("NotifyDisconnectCompleted");
+ if (VDBG) log("NotifyDisconnectCompleted");
if (dp.onCompletedMsg != null) {
Message msg = dp.onCompletedMsg;
- log(String.format("msg=%s msg.obj=%s", msg.toString(),
+ if (VDBG) {
+ log(String.format("msg=%s msg.obj=%s", msg.toString(),
((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
+ }
AsyncResult.forMessage(msg);
msg.sendToTarget();
}
- if (dp.lockObj != null) {
- synchronized(dp.lockObj) {
- dp.lockObj.notify();
- }
- }
-
clearSettings();
+ if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
}
- public RetryManager getRetryMgr() {
- return mRetryMgr;
+ protected int getRadioTechnology(int defaultRadioTechnology) {
+ int radioTechnology;
+ if (mRilVersion < 6) {
+ radioTechnology = defaultRadioTechnology;
+ } else {
+ radioTechnology = phone.getServiceState().getRadioTechnology() + 2;
+ }
+ return radioTechnology;
}
+ /*
+ * **************************************************************************
+ * Begin Members and methods owned by DataConnectionTracker but stored
+ * in a DataConnection because there is one per connection.
+ * **************************************************************************
+ */
+
+ /*
+ * The id is owned by DataConnectionTracker.
+ */
+ private int mId;
+
+ /**
+ * Get the DataConnection ID
+ */
+ public int getDataConnectionId() {
+ return mId;
+ }
+
+ /*
+ * The retry manager is currently owned by the DataConnectionTracker but is stored
+ * in the DataConnection because there is one per connection. These methods
+ * should only be used by the DataConnectionTracker although someday the retrying
+ * maybe managed by the DataConnection itself and these methods could disappear.
+ */
+ private RetryManager mRetryMgr;
+
+ /**
+ * @return retry manager retryCount
+ */
+ public int getRetryCount() {
+ return mRetryMgr.getRetryCount();
+ }
+
+ /**
+ * @return retry manager retryTimer
+ */
+ public int getRetryTimer() {
+ return mRetryMgr.getRetryTimer();
+ }
+
+ /**
+ * increaseRetryCount of retry manager
+ */
+ public void increaseRetryCount() {
+ mRetryMgr.increaseRetryCount();
+ }
+
+ /**
+ * @return retry manager isRetryNeeded
+ */
+ public boolean isRetryNeeded() {
+ return mRetryMgr.isRetryNeeded();
+ }
+
+ /**
+ * resetRetryCount of retry manager
+ */
+ public void resetRetryCount() {
+ mRetryMgr.resetRetryCount();
+ }
+
+ /**
+ * set retryForeverUsingLasttimeout of retry manager
+ */
+ public void retryForeverUsingLastTimeout() {
+ mRetryMgr.retryForeverUsingLastTimeout();
+ }
+
+ /**
+ * @return retry manager isRetryForever
+ */
+ public boolean isRetryForever() {
+ return mRetryMgr.isRetryForever();
+ }
+
+ /**
+ * @return whether the retry config is set successfully or not
+ */
+ public boolean configureRetry(int maxRetryCount, int retryTime, int randomizationTime) {
+ return mRetryMgr.configure(maxRetryCount, retryTime, randomizationTime);
+ }
+
+ /**
+ * @return whether the retry config is set successfully or not
+ */
+ public boolean configureRetry(String configStr) {
+ return mRetryMgr.configure(configStr);
+ }
+
+ /*
+ * **************************************************************************
+ * End members owned by DataConnectionTracker
+ * **************************************************************************
+ */
+
/**
* Clear all settings called when entering mInactiveState.
*/
protected void clearSettings() {
if (DBG) log("clearSettings");
- this.createTime = -1;
- this.lastFailTime = -1;
- this.lastFailCause = FailCause.NONE;
+ createTime = -1;
+ lastFailTime = -1;
+ lastFailCause = FailCause.NONE;
+ mRefCount = 0;
mLinkProperties = new LinkProperties();
+ mApn = null;
}
/**
@@ -365,10 +444,10 @@
* @param ar is the result
* @return SetupResult.
*/
- private SetupResult onSetupConnectionCompleted(AsyncResult ar) {
+ private DataCallState.SetupResult onSetupConnectionCompleted(AsyncResult ar) {
DataCallState response = (DataCallState) ar.result;
ConnectionParams cp = (ConnectionParams) ar.userObj;
- SetupResult result;
+ DataCallState.SetupResult result;
if (ar.exception != null) {
if (DBG) {
@@ -379,168 +458,189 @@
if (ar.exception instanceof CommandException
&& ((CommandException) (ar.exception)).getCommandError()
== CommandException.Error.RADIO_NOT_AVAILABLE) {
- result = SetupResult.ERR_BadCommand;
+ result = DataCallState.SetupResult.ERR_BadCommand;
result.mFailCause = FailCause.RADIO_NOT_AVAILABLE;
} else if ((response == null) || (response.version < 4)) {
- result = SetupResult.ERR_GetLastErrorFromRil;
+ result = DataCallState.SetupResult.ERR_GetLastErrorFromRil;
} else {
- result = SetupResult.ERR_RilError;
+ result = DataCallState.SetupResult.ERR_RilError;
result.mFailCause = FailCause.fromInt(response.status);
}
} else if (cp.tag != mTag) {
if (DBG) {
log("BUG: onSetupConnectionCompleted is stale cp.tag=" + cp.tag + ", mtag=" + mTag);
}
- result = SetupResult.ERR_Stale;
+ result = DataCallState.SetupResult.ERR_Stale;
+ } else if (response.status != 0) {
+ result = DataCallState.SetupResult.ERR_RilError;
+ result.mFailCause = FailCause.fromInt(response.status);
} else {
- log("onSetupConnectionCompleted received DataCallState: " + response);
-
- // 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.status == FailCause.NONE.getErrorCode()) {
- String propertyPrefix = "net." + response.ifname + ".";
-
- try {
- cid = response.cid;
- linkProperties.setInterfaceName(response.ifname);
- if (response.addresses != null && response.addresses.length > 0) {
- for (String addr : response.addresses) {
- LinkAddress la;
- int addrPrefixLen;
-
- String [] ap = addr.split("/");
- if (ap.length == 2) {
- addr = ap[0];
- addrPrefixLen = Integer.parseInt(ap[1]);
- } else {
- addrPrefixLen = 0;
- }
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(addr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writeBadIpAddress(addr);
- throw new UnknownHostException("Non-numeric ip addr=" + addr);
- }
- if (addrPrefixLen == 0) {
- // Assume point to point
- addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
- }
- if (DBG) log("addr/pl=" + addr + "/" + addrPrefixLen);
- la = new LinkAddress(ia, addrPrefixLen);
- linkProperties.addLinkAddress(la);
- }
- } else {
- EventLogTags.writeBadIpAddress("no address for ifname=" + response.ifname);
- throw new UnknownHostException("no address for ifname=" + response.ifname);
- }
- if (response.dnses != null && response.dnses.length > 0) {
- for (String addr : response.dnses) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(addr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writePdpBadDnsAddress("dns=" + addr);
- throw new UnknownHostException("Non-numeric dns addr=" + addr);
- }
- linkProperties.addDns(ia);
- }
- result = SetupResult.SUCCESS;
- } else {
- String dnsServers[] = new String[2];
- dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
- dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
- if (isDnsOk(dnsServers)) {
- for (String dnsAddr : dnsServers) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(dnsAddr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writePdpBadDnsAddress("dnsAddr=" + dnsAddr);
- throw new UnknownHostException("Non-numeric dns addr="
- + dnsAddr);
- }
- linkProperties.addDns(ia);
- }
- result = SetupResult.SUCCESS;
- } else {
- StringBuilder sb = new StringBuilder();
- for (String dnsAddr : dnsServers) {
- sb.append(dnsAddr);
- sb.append(" ");
- }
- EventLogTags.writePdpBadDnsAddress("Unacceptable dns addresses=" + sb);
- throw new UnknownHostException("Unacceptable dns addresses=" + sb);
- }
- }
- if ((response.gateways == null) || (response.gateways.length == 0)) {
- String gateways = SystemProperties.get(propertyPrefix + "gw");
- if (gateways != null) {
- response.gateways = gateways.split(" ");
- } else {
- response.gateways = new String[0];
- }
- }
- for (String addr : response.gateways) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(addr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writePdpBadDnsAddress("gateway=" + addr);
- throw new UnknownHostException("Non-numeric gateway addr=" + addr);
- }
- linkProperties.addGateway(ia);
- }
- result = SetupResult.SUCCESS;
- } catch (UnknownHostException e) {
- log("onSetupCompleted: UnknownHostException " + e);
- e.printStackTrace();
- result = SetupResult.ERR_UnacceptableParameter;
- }
- } else {
- if (response.version < 4) {
- result = SetupResult.ERR_GetLastErrorFromRil;
- } else {
- result = SetupResult.ERR_RilError;
- }
- }
-
- // An error occurred so clear properties
- if (result != SetupResult.SUCCESS) {
- log("onSetupConnectionCompleted with an error, clearing LinkProperties");
- linkProperties.clear();
- }
- mLinkProperties = linkProperties;
+ if (DBG) log("onSetupConnectionCompleted received DataCallState: " + response);
+ cid = response.cid;
+ // set link properties based on data call response
+ result = setLinkProperties(response, mLinkProperties);
}
- if (DBG) {
- log("onSetupConnectionCompleted: DataConnection setup result='"
- + result + "' on cid=" + cid);
- if (result == SetupResult.SUCCESS) {
- log("onSetupConnectionCompleted: LinkProperties: " + mLinkProperties.toString());
- }
- }
return result;
}
+ private DataCallState.SetupResult setLinkProperties(DataCallState response,
+ LinkProperties lp) {
+ // Check if system property dns usable
+ boolean okToUseSystemPropertyDns = false;
+ String propertyPrefix = "net." + response.ifname + ".";
+ String dnsServers[] = new String[2];
+ dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
+ dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
+ okToUseSystemPropertyDns = isDnsOk(dnsServers);
+
+ // set link properties based on data call response
+ return response.setLinkProperties(lp, okToUseSystemPropertyDns);
+ }
+
+ private DataConnectionAc.LinkPropertyChangeAction updateLinkProperty(
+ DataCallState newState) {
+ DataConnectionAc.LinkPropertyChangeAction changed =
+ DataConnectionAc.LinkPropertyChangeAction.NONE;
+
+ if (newState == null) return changed;
+
+ DataCallState.SetupResult result;
+ LinkProperties newLp = new LinkProperties();
+
+ // set link properties based on data call response
+ result = setLinkProperties(newState, newLp);
+ if (result != DataCallState.SetupResult.SUCCESS) {
+ if (DBG) log("UpdateLinkProperty failed : " + result);
+ return changed;
+ }
+ // copy HTTP proxy as it is not part DataCallState.
+ newLp.setHttpProxy(mLinkProperties.getHttpProxy());
+
+ if (DBG) log("old LP=" + mLinkProperties);
+ if (DBG) log("new LP=" + newLp);
+
+ // Check consistency of link address. Currently we expect
+ // only one "global" address is assigned per each IP type.
+ Collection<LinkAddress> oLinks = mLinkProperties.getLinkAddresses();
+ Collection<LinkAddress> nLinks = newLp.getLinkAddresses();
+ for (LinkAddress oldLink : oLinks) {
+ for (LinkAddress newLink : nLinks) {
+ if ((NetworkUtils.addressTypeMatches(oldLink.getAddress(),
+ newLink.getAddress())) &&
+ (oldLink.equals(newLink) == false)) {
+ return DataConnectionAc.LinkPropertyChangeAction.RESET;
+ }
+ }
+ }
+
+ if (mLinkProperties == null || !mLinkProperties.equals(newLp)) {
+ mLinkProperties = newLp;
+ changed = DataConnectionAc.LinkPropertyChangeAction.CHANGED;
+ }
+
+ return changed;
+ }
+
/**
* The parent state for all other states.
*/
- private class DcDefaultState extends HierarchicalState {
+ private class DcDefaultState extends State {
@Override
- protected boolean processMessage(Message msg) {
+ public void enter() {
+ phone.mCM.registerForRilConnected(getHandler(), EVENT_RIL_CONNECTED, null);
+ }
+ @Override
+ public void exit() {
+ phone.mCM.unregisterForRilConnected(getHandler());
+ }
+ @Override
+ public boolean processMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
- case EVENT_RESET:
- if (DBG) log("DcDefaultState: msg.what=EVENT_RESET");
- clearSettings();
- if (msg.obj != null) {
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+ if (mAc != null) {
+ if (VDBG) log("Disconnecting to previous connection mAc=" + mAc);
+ mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
+ } else {
+ mAc = new AsyncChannel();
+ mAc.connected(null, getHandler(), msg.replyTo);
+ if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected");
+ mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
}
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECT");
+ mAc.disconnect();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECTED");
+ mAc = null;
+ break;
+ }
+ case DataConnectionAc.REQ_IS_INACTIVE: {
+ boolean val = getCurrentState() == mInactiveState;
+ if (VDBG) log("REQ_IS_INACTIVE isInactive=" + val);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_IS_INACTIVE, val ? 1 : 0);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_CID: {
+ if (VDBG) log("REQ_GET_CID cid=" + cid);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, cid);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_APNSETTING: {
+ if (VDBG) log("REQ_GET_APNSETTING apnSetting=" + mApn);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNSETTING, mApn);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_PROPERTIES: {
+ LinkProperties lp = new LinkProperties(mLinkProperties);
+ if (VDBG) log("REQ_GET_LINK_PROPERTIES linkProperties" + lp);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_PROPERTIES, lp);
+ break;
+ }
+ case DataConnectionAc.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: {
+ ProxyProperties proxy = (ProxyProperties) msg.obj;
+ if (VDBG) log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy);
+ mLinkProperties.setHttpProxy(proxy);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
+ break;
+ }
+ case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
+ DataCallState newState = (DataCallState) msg.obj;
+ DataConnectionAc.LinkPropertyChangeAction action = updateLinkProperty(newState);
+ if (VDBG) {
+ log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE action="
+ + action + " newState=" + newState);
+ }
+ mAc.replyToMessage(msg,
+ DataConnectionAc.RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE,
+ action.ordinal());
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
+ LinkCapabilities lc = new LinkCapabilities(mCapabilities);
+ if (VDBG) log("REQ_GET_LINK_CAPABILITIES linkCapabilities" + lc);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_CAPABILITIES, lc);
+ break;
+ }
+ case DataConnectionAc.REQ_RESET:
+ if (VDBG) log("DcDefaultState: msg.what=REQ_RESET");
+ clearSettings();
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
transitionTo(mInactiveState);
break;
+ case DataConnectionAc.REQ_GET_REFCOUNT: {
+ if (VDBG) log("REQ_GET_REFCOUNT refCount=" + mRefCount);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
+ break;
+ }
case EVENT_CONNECT:
if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
@@ -553,14 +653,29 @@
notifyDisconnectCompleted((DisconnectParams) msg.obj);
break;
+ case EVENT_RIL_CONNECTED:
+ ar = (AsyncResult)msg.obj;
+ if (ar.exception == null) {
+ mRilVersion = (Integer)ar.result;
+ if (DBG) {
+ log("DcDefaultState: msg.what=EVENT_RIL_CONNECTED mRilVersion=" +
+ mRilVersion);
+ }
+ } else {
+ log("Unexpected exception on EVENT_RIL_CONNECTED");
+ mRilVersion = -1;
+ }
+ break;
+
default:
if (DBG) {
- log("DcDefaultState: shouldn't happen but ignore msg.what=" + msg.what);
+ log("DcDefaultState: shouldn't happen but ignore msg.what=0x" +
+ Integer.toHexString(msg.what));
}
break;
}
- return true;
+ return HANDLED;
}
}
private DcDefaultState mDefaultState = new DcDefaultState();
@@ -568,23 +683,24 @@
/**
* The state machine is inactive and expects a EVENT_CONNECT.
*/
- private class DcInactiveState extends HierarchicalState {
+ private class DcInactiveState extends State {
private ConnectionParams mConnectionParams = null;
private FailCause mFailCause = null;
private DisconnectParams mDisconnectParams = null;
public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
- log("DcInactiveState: setEnterNoticationParams cp,cause");
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
mConnectionParams = cp;
mFailCause = cause;
}
public void setEnterNotificationParams(DisconnectParams dp) {
- log("DcInactiveState: setEnterNoticationParams dp");
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams dp");
mDisconnectParams = dp;
}
- @Override protected void enter() {
+ @Override
+ public void enter() {
mTag += 1;
/**
@@ -595,48 +711,55 @@
* call to isInactive.
*/
if ((mConnectionParams != null) && (mFailCause != null)) {
- log("DcInactiveState: enter notifyConnectCompleted");
+ if (VDBG) log("DcInactiveState: enter notifyConnectCompleted");
notifyConnectCompleted(mConnectionParams, mFailCause);
}
if (mDisconnectParams != null) {
- log("DcInactiveState: enter notifyDisconnectCompleted");
+ if (VDBG) log("DcInactiveState: enter notifyDisconnectCompleted");
notifyDisconnectCompleted(mDisconnectParams);
}
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
// clear notifications
mConnectionParams = null;
mFailCause = null;
mDisconnectParams = null;
}
- @Override protected boolean processMessage(Message msg) {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
- case EVENT_RESET:
+ case DataConnectionAc.REQ_RESET:
if (DBG) {
- log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset");
+ log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
}
- if (msg.obj != null) {
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
- }
- retVal = true;
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
+ retVal = HANDLED;
break;
case EVENT_CONNECT:
- if (DBG) log("DcInactiveState msg.what=EVENT_CONNECT");
ConnectionParams cp = (ConnectionParams) msg.obj;
cp.tag = mTag;
+ if (DBG) {
+ log("DcInactiveState msg.what=EVENT_CONNECT." + "RefCount = "
+ + mRefCount);
+ }
+ mRefCount = 1;
onConnect(cp);
transitionTo(mActivatingState);
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcInactiveState nothandled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -647,17 +770,26 @@
/**
* The state machine is activating a connection.
*/
- private class DcActivatingState extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class DcActivatingState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
AsyncResult ar;
ConnectionParams cp;
switch (msg.what) {
case EVENT_DISCONNECT:
- if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
+ if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"
+ + mRefCount);
deferMessage(msg);
- retVal = true;
+ retVal = HANDLED;
+ break;
+
+ case EVENT_CONNECT:
+ if (DBG) log("DcActivatingState deferring msg.what=EVENT_CONNECT refCount = "
+ + mRefCount);
+ deferMessage(msg);
+ retVal = HANDLED;
break;
case EVENT_SETUP_DATA_CONNECTION_DONE:
@@ -666,7 +798,7 @@
ar = (AsyncResult) msg.obj;
cp = (ConnectionParams) ar.userObj;
- SetupResult result = onSetupConnectionCompleted(ar);
+ DataCallState.SetupResult result = onSetupConnectionCompleted(ar);
if (DBG) log("DcActivatingState onSetupConnectionCompleted result=" + result);
switch (result) {
case SUCCESS:
@@ -700,9 +832,9 @@
// Request is stale, ignore.
break;
default:
- throw new RuntimeException("Unkown SetupResult, should not happen");
+ throw new RuntimeException("Unknown SetupResult, should not happen");
}
- retVal = true;
+ retVal = HANDLED;
break;
case EVENT_GET_LAST_FAIL_DONE:
@@ -727,12 +859,15 @@
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcActivatingState not handled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -743,12 +878,12 @@
/**
* The state machine is connected, expecting an EVENT_DISCONNECT.
*/
- private class DcActiveState extends HierarchicalState {
+ private class DcActiveState extends State {
private ConnectionParams mConnectionParams = null;
private FailCause mFailCause = null;
public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
- log("DcInactiveState: setEnterNoticationParams cp,cause");
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
mConnectionParams = cp;
mFailCause = cause;
}
@@ -762,33 +897,54 @@
* call to isActive.
*/
if ((mConnectionParams != null) && (mFailCause != null)) {
- log("DcActiveState: enter notifyConnectCompleted");
+ if (VDBG) log("DcActiveState: enter notifyConnectCompleted");
notifyConnectCompleted(mConnectionParams, mFailCause);
}
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
// clear notifications
mConnectionParams = null;
mFailCause = null;
}
- @Override protected boolean processMessage(Message msg) {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
+ case EVENT_CONNECT:
+ mRefCount++;
+ if (DBG) log("DcActiveState msg.what=EVENT_CONNECT RefCount=" + mRefCount);
+ if (msg.obj != null) {
+ notifyConnectCompleted((ConnectionParams) msg.obj, FailCause.NONE);
+ }
+ retVal = HANDLED;
+ break;
case EVENT_DISCONNECT:
- if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT");
- DisconnectParams dp = (DisconnectParams) msg.obj;
- dp.tag = mTag;
- tearDownData(dp);
- transitionTo(mDisconnectingState);
- retVal = true;
+ mRefCount--;
+ if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT RefCount=" + mRefCount);
+ if (mRefCount == 0)
+ {
+ DisconnectParams dp = (DisconnectParams) msg.obj;
+ dp.tag = mTag;
+ tearDownData(dp);
+ transitionTo(mDisconnectingState);
+ } else {
+ if (msg.obj != null) {
+ notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ }
+ }
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcActiveState not handled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -799,11 +955,19 @@
/**
* The state machine is disconnecting.
*/
- private class DcDisconnectingState extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class DcDisconnectingState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
+ case EVENT_CONNECT:
+ if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = "
+ + mRefCount);
+ deferMessage(msg);
+ retVal = HANDLED;
+ break;
+
case EVENT_DEACTIVATE_DONE:
if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE");
AsyncResult ar = (AsyncResult) msg.obj;
@@ -817,12 +981,15 @@
if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
+ dp.tag + " mTag=" + mTag);
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcDisconnectingState not handled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -833,8 +1000,9 @@
/**
* The state machine is disconnecting after an creating a connection.
*/
- private class DcDisconnectionErrorCreatingConnection extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class DcDisconnectionErrorCreatingConnection extends State {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
@@ -858,15 +1026,15 @@
" stale dp.tag=" + cp.tag + ", mTag=" + mTag);
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) {
- log("DcDisconnectionErrorCreatingConnection not handled msg.what="
- + msg.what);
+ if (VDBG) {
+ log("DcDisconnectionErrorCreatingConnection not handled msg.what=0x"
+ + Integer.toHexString(msg.what));
}
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -878,143 +1046,26 @@
// ******* public interface
/**
- * Disconnect from the network.
- *
- * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
- * With AsyncResult.userObj set to the original msg.obj.
- */
- public void reset(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(onCompletedMsg)));
- }
-
- /**
- * Reset the connection and wait for it to complete.
- * TODO: Remove when all callers only need the asynchronous
- * reset defined above.
- */
- public void resetSynchronously() {
- ResetSynchronouslyLock lockObj = new ResetSynchronouslyLock();
- synchronized(lockObj) {
- sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(lockObj)));
- try {
- lockObj.wait();
- } catch (InterruptedException e) {
- log("blockingReset: unexpected interrupted of wait()");
- }
- }
- }
-
- /**
- * Connect to the apn and return an AsyncResult in onCompletedMsg.
+ * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.
* 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 Access Point Name to connect to
+ * @param apn is the Access Point Name to bring up a connection to
*/
- public void connect(Message onCompletedMsg, ApnSetting apn) {
+ public void bringUp(Message onCompletedMsg, ApnSetting apn) {
sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
}
/**
- * Connect to the apn and return an AsyncResult in onCompletedMsg.
- *
- * @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().
- */
- public void connect(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(null, onCompletedMsg)));
- }
-
- /**
- * Disconnect from the network.
+ * Tear down the connection through the apn on the network.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj.
*/
- public void disconnect(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(onCompletedMsg)));
- }
-
- // ****** The following are used for debugging.
-
- /**
- * TODO: This should be an asynchronous call and we wouldn't
- * have to use handle the notification in the DcInactiveState.enter.
- *
- * @return true if the state machine is in the inactive state.
- */
- public boolean isInactive() {
- boolean retVal = getCurrentState() == mInactiveState;
- return retVal;
- }
-
- /**
- * TODO: This should be an asynchronous call and we wouldn't
- * have to use handle the notification in the DcActiveState.enter.
- *
- * @return true if the state machine is in the active state.
- */
- public boolean isActive() {
- boolean retVal = getCurrentState() == mActiveState;
- return retVal;
- }
-
- /**
- * Get the DataConnection ID
- */
- public int getDataConnectionId() {
- return mId;
- }
-
- /**
- * Return the LinkProperties for the connection.
- *
- * @return a copy of the LinkProperties, is never null.
- */
- public LinkProperties getLinkProperties() {
- return new LinkProperties(mLinkProperties);
- }
-
- /**
- * 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 LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mCapabilities);
- }
-
- /**
- * @return the current state as a string.
- */
- public String getStateAsString() {
- String retVal = getCurrentState().getName();
- return retVal;
- }
-
- /**
- * @return the time of when this connection was created.
- */
- public long getConnectionTime() {
- return createTime;
- }
-
- /**
- * @return the time of the last failure.
- */
- public long getLastFailTime() {
- return lastFailTime;
- }
-
- /**
- * @return the last cause of failure.
- */
- public FailCause getLastFailCause() {
- return lastFailCause;
+ public void tearDown(String reason, Message onCompletedMsg) {
+ sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(reason, onCompletedMsg)));
}
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
new file mode 100644
index 0000000..62b90ae
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.ProxyProperties;
+import android.os.Message;
+
+/**
+ * AsyncChannel to a DataConnection
+ */
+public class DataConnectionAc extends AsyncChannel {
+ private static final boolean DBG = false;
+ private String mLogTag;
+
+ public DataConnection dataConnection;
+
+ public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC;
+
+ public static final int REQ_IS_INACTIVE = BASE + 0;
+ public static final int RSP_IS_INACTIVE = BASE + 1;
+
+ public static final int REQ_GET_CID = BASE + 2;
+ public static final int RSP_GET_CID = BASE + 3;
+
+ public static final int REQ_GET_APNSETTING = BASE + 4;
+ public static final int RSP_GET_APNSETTING = BASE + 5;
+
+ public static final int REQ_GET_LINK_PROPERTIES = BASE + 6;
+ public static final int RSP_GET_LINK_PROPERTIES = BASE + 7;
+
+ public static final int REQ_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 8;
+ public static final int RSP_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 9;
+
+ public static final int REQ_GET_LINK_CAPABILITIES = BASE + 10;
+ public static final int RSP_GET_LINK_CAPABILITIES = BASE + 11;
+
+ public static final int REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 12;
+ public static final int RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 13;
+
+ public static final int REQ_RESET = BASE + 14;
+ public static final int RSP_RESET = BASE + 15;
+
+ public static final int REQ_GET_REFCOUNT = BASE + 16;
+ public static final int RSP_GET_REFCOUNT = BASE + 17;
+
+ /**
+ * enum used to notify action taken or necessary to be
+ * taken after the link property is changed.
+ */
+ public enum LinkPropertyChangeAction {
+ NONE, CHANGED, RESET;
+
+ public static LinkPropertyChangeAction fromInt(int value) {
+ if (value == NONE.ordinal()) {
+ return NONE;
+ } else if (value == CHANGED.ordinal()) {
+ return CHANGED;
+ } else if (value == RESET.ordinal()) {
+ return RESET;
+ } else {
+ throw new RuntimeException("LinkPropertyChangeAction.fromInt: bad value=" + value);
+ }
+ }
+ }
+
+ public DataConnectionAc(DataConnection dc, String logTag) {
+ dataConnection = dc;
+ mLogTag = logTag;
+ }
+
+ /**
+ * Request if the state machine is in the inactive state.
+ * Response {@link #rspIsInactive}
+ */
+ public void reqIsInactive() {
+ sendMessage(REQ_IS_INACTIVE);
+ if (DBG) log("reqIsInactive");
+ }
+
+ /**
+ * Evaluate RSP_IS_INACTIVE.
+ *
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean rspIsInactive(Message response) {
+ boolean retVal = response.arg1 == 1;
+ if (DBG) log("rspIsInactive=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean isInactiveSync() {
+ Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
+ if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
+ return rspIsInactive(response);
+ } else {
+ log("rspIsInactive error response=" + response);
+ return false;
+ }
+ }
+
+ /**
+ * Request the Connection ID.
+ * Response {@link #rspCid}
+ */
+ public void reqCid() {
+ sendMessage(REQ_GET_CID);
+ if (DBG) log("reqCid");
+ }
+
+ /**
+ * Evaluate a RSP_GET_CID message and return the cid.
+ *
+ * @param response Message
+ * @return connection id or -1 if an error
+ */
+ public int rspCid(Message response) {
+ int retVal = response.arg1;
+ if (DBG) log("rspCid=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return connection id or -1 if an error
+ */
+ public int getCidSync() {
+ Message response = sendMessageSynchronously(REQ_GET_CID);
+ if ((response != null) && (response.what == RSP_GET_CID)) {
+ return rspCid(response);
+ } else {
+ log("rspCid error response=" + response);
+ return -1;
+ }
+ }
+
+ /**
+ * Request the Reference Count.
+ * Response {@link #rspRefCount}
+ */
+ public void reqRefCount() {
+ sendMessage(REQ_GET_REFCOUNT);
+ if (DBG) log("reqRefCount");
+ }
+
+ /**
+ * Evaluate a RSP_GET_REFCOUNT message and return the refCount.
+ *
+ * @param response Message
+ * @return ref count or -1 if an error
+ */
+ public int rspRefCount(Message response) {
+ int retVal = response.arg1;
+ if (DBG) log("rspRefCount=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return connection id or -1 if an error
+ */
+ public int getRefCountSync() {
+ Message response = sendMessageSynchronously(REQ_GET_REFCOUNT);
+ if ((response != null) && (response.what == RSP_GET_REFCOUNT)) {
+ return rspRefCount(response);
+ } else {
+ log("rspRefCount error response=" + response);
+ return -1;
+ }
+ }
+
+ /**
+ * Request the connections ApnSetting.
+ * Response {@link #rspApnSetting}
+ */
+ public void reqApnSetting() {
+ sendMessage(REQ_GET_APNSETTING);
+ if (DBG) log("reqApnSetting");
+ }
+
+ /**
+ * Evaluate a RSP_APN_SETTING message and return the ApnSetting.
+ *
+ * @param response Message
+ * @return ApnSetting, maybe null
+ */
+ public ApnSetting rspApnSetting(Message response) {
+ ApnSetting retVal = (ApnSetting) response.obj;
+ if (DBG) log("rspApnSetting=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections ApnSetting.
+ *
+ * @return ApnSetting or null if an error
+ */
+ public ApnSetting getApnSettingSync() {
+ Message response = sendMessageSynchronously(REQ_GET_APNSETTING);
+ if ((response != null) && (response.what == RSP_GET_APNSETTING)) {
+ return rspApnSetting(response);
+ } else {
+ log("getApnSetting error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request the connections LinkProperties.
+ * Response {@link #rspLinkProperties}
+ */
+ public void reqLinkProperties() {
+ sendMessage(REQ_GET_LINK_PROPERTIES);
+ if (DBG) log("reqLinkProperties");
+ }
+
+ /**
+ * Evaluate RSP_GET_LINK_PROPERTIES
+ *
+ * @param response
+ * @return LinkProperties, maybe null.
+ */
+ public LinkProperties rspLinkProperties(Message response) {
+ LinkProperties retVal = (LinkProperties) response.obj;
+ if (DBG) log("rspLinkProperties=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections LinkProperties.
+ *
+ * @return LinkProperties or null if an error
+ */
+ public LinkProperties getLinkPropertiesSync() {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) {
+ return rspLinkProperties(response);
+ } else {
+ log("getLinkProperties error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request setting the connections LinkProperties.HttpProxy.
+ * Response RSP_SET_LINK_PROPERTIES when complete.
+ */
+ public void reqSetLinkPropertiesHttpProxy(ProxyProperties proxy) {
+ sendMessage(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
+ if (DBG) log("reqSetLinkPropertiesHttpProxy proxy=" + proxy);
+ }
+
+ /**
+ * Set the connections LinkProperties.HttpProxy
+ */
+ public void setLinkPropertiesHttpProxySync(ProxyProperties proxy) {
+ Message response =
+ sendMessageSynchronously(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
+ if ((response != null) && (response.what == RSP_SET_LINK_PROPERTIES_HTTP_PROXY)) {
+ if (DBG) log("setLinkPropertiesHttpPoxy ok");
+ } else {
+ log("setLinkPropertiesHttpPoxy error response=" + response);
+ }
+ }
+
+ /**
+ * Request update LinkProperties from DataCallState
+ * Response {@link #rspUpdateLinkPropertiesDataCallState}
+ */
+ public void reqUpdateLinkPropertiesDataCallState(DataCallState newState) {
+ sendMessage(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
+ if (DBG) log("reqUpdateLinkPropertiesDataCallState");
+ }
+
+ public LinkPropertyChangeAction rspUpdateLinkPropertiesDataCallState(Message response) {
+ LinkPropertyChangeAction retVal = LinkPropertyChangeAction.fromInt(response.arg1);
+ if (DBG) log("rspUpdateLinkPropertiesState=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Update link properties in the data connection
+ *
+ * @return true if link property has been updated. false otherwise.
+ */
+ public LinkPropertyChangeAction updateLinkPropertiesDataCallStateSync(DataCallState newState) {
+ Message response =
+ sendMessageSynchronously(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
+ if ((response != null) &&
+ (response.what == RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE)) {
+ return rspUpdateLinkPropertiesDataCallState(response);
+ } else {
+ log("getLinkProperties error response=" + response);
+ return LinkPropertyChangeAction.NONE;
+ }
+ }
+
+ /**
+ * Request the connections LinkCapabilities.
+ * Response {@link #rspLinkCapabilities}
+ */
+ public void reqLinkCapabilities() {
+ sendMessage(REQ_GET_LINK_CAPABILITIES);
+ if (DBG) log("reqLinkCapabilities");
+ }
+
+ /**
+ * Evaluate RSP_GET_LINK_CAPABILITIES
+ *
+ * @param response
+ * @return LinkCapabilites, maybe null.
+ */
+ public LinkCapabilities rspLinkCapabilities(Message response) {
+ LinkCapabilities retVal = (LinkCapabilities) response.obj;
+ if (DBG) log("rspLinkCapabilities=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections LinkCapabilities.
+ *
+ * @return LinkCapabilities or null if an error
+ */
+ public LinkCapabilities getLinkCapabilitiesSync() {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_CAPABILITIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_CAPABILITIES)) {
+ return rspLinkCapabilities(response);
+ } else {
+ log("getLinkCapabilities error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request the connections LinkCapabilities.
+ * Response RSP_RESET when complete
+ */
+ public void reqReset() {
+ sendMessage(REQ_RESET);
+ if (DBG) log("reqReset");
+ }
+
+ /**
+ * Reset the connection and wait for it to complete.
+ */
+ public void resetSync() {
+ Message response = sendMessageSynchronously(REQ_RESET);
+ if ((response != null) && (response.what == RSP_RESET)) {
+ if (DBG) log("restSync ok");
+ } else {
+ log("restSync error response=" + response);
+ }
+ }
+
+ private void log(String s) {
+ android.util.Log.d(mLogTag, "DataConnectionAc " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 7f8485b..2c26f62 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -22,24 +22,30 @@
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.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.R;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -87,38 +93,39 @@
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;
- protected static final int EVENT_RECORDS_LOADED = 4;
- protected static final int EVENT_TRY_SETUP_DATA = 5;
- protected static final int EVENT_DATA_STATE_CHANGED = 6;
- protected static final int EVENT_POLL_PDP = 7;
- protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
- protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
- protected static final int EVENT_VOICE_CALL_STARTED = 14;
- protected static final int EVENT_VOICE_CALL_ENDED = 15;
- protected static final int EVENT_GPRS_DETACHED = 19;
- protected static final int EVENT_LINK_STATE_CHANGED = 20;
- protected static final int EVENT_ROAMING_ON = 21;
- protected static final int EVENT_ROAMING_OFF = 22;
- protected static final int EVENT_ENABLE_NEW_APN = 23;
- protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
- protected static final int EVENT_DISCONNECT_DONE = 25;
- protected static final int EVENT_GPRS_ATTACHED = 26;
- protected static final int EVENT_START_NETSTAT_POLL = 27;
- protected static final int EVENT_START_RECOVERY = 28;
- protected static final int EVENT_APN_CHANGED = 29;
- protected static final int EVENT_CDMA_DATA_DETACHED = 30;
- protected static final int EVENT_NV_READY = 31;
- protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
- protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
- 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_INTERNAL_DATA_ENABLE = 37;
- protected static final int EVENT_RESET_DONE = 38;
-
- public static final int CMD_SET_DATA_ENABLE = 39;
+ protected static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
+ protected static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
+ protected static final int EVENT_RADIO_AVAILABLE = BASE + 1;
+ protected static final int EVENT_RECORDS_LOADED = BASE + 2;
+ protected static final int EVENT_TRY_SETUP_DATA = BASE + 3;
+ protected static final int EVENT_DATA_STATE_CHANGED = BASE + 4;
+ protected static final int EVENT_POLL_PDP = BASE + 5;
+ protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
+ protected static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
+ protected static final int EVENT_VOICE_CALL_ENDED = BASE + 8;
+ protected static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
+ protected static final int EVENT_LINK_STATE_CHANGED = BASE + 10;
+ protected static final int EVENT_ROAMING_ON = BASE + 11;
+ protected static final int EVENT_ROAMING_OFF = BASE + 12;
+ protected static final int EVENT_ENABLE_NEW_APN = BASE + 13;
+ protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
+ protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
+ protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
+ protected static final int EVENT_START_NETSTAT_POLL = BASE + 17;
+ protected static final int EVENT_START_RECOVERY = BASE + 18;
+ protected static final int EVENT_APN_CHANGED = BASE + 19;
+ protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
+ protected static final int EVENT_NV_READY = BASE + 21;
+ protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
+ protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
+ public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
+ protected static final int EVENT_CDMA_OTA_PROVISION = BASE + 25;
+ protected static final int EVENT_RESTART_RADIO = BASE + 26;
+ protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
+ protected static final int EVENT_RESET_DONE = BASE + 28;
+ public static final int CMD_SET_DATA_ENABLE = BASE + 29;
+ public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
+ public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
/***** Constants *****/
@@ -128,11 +135,19 @@
protected static final int APN_SUPL_ID = 2;
protected static final int APN_DUN_ID = 3;
protected static final int APN_HIPRI_ID = 4;
- protected static final int APN_NUM_TYPES = 5;
+ protected static final int APN_IMS_ID = 5;
+ protected static final int APN_FOTA_ID = 6;
+ protected static final int APN_CBS_ID = 7;
+ protected static final int APN_NUM_TYPES = 8;
public static final int DISABLED = 0;
public static final int ENABLED = 1;
+ public static final String APN_TYPE_KEY = "apnType";
+
+ /** Delay between APN attempts */
+ protected static final int APN_DELAY_MILLIS = 5000;
+
// responds to the setInternalDataEnabled call - used internally to turn off data
// for example during emergency calls
protected boolean mInternalDataEnabled = true;
@@ -192,6 +207,21 @@
// getActionIntentReconnectAlarm.
protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+ // Used for debugging. Send the INTENT with an optional counter value with the number
+ // of times the setup is to fail before succeeding. If the counter isn't passed the
+ // setup will fail once. Example fail two times with FailCause.SIGNAL_LOST(-3)
+ // adb shell am broadcast \
+ // -a com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter \
+ // --ei fail_data_setup_counter 3 --ei fail_data_setup_fail_cause -3
+ protected static final String INTENT_SET_FAIL_DATA_SETUP_COUNTER =
+ "com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter";
+ protected static final String FAIL_DATA_SETUP_COUNTER = "fail_data_setup_counter";
+ protected int mFailDataSetupCounter = 0;
+ protected static final String FAIL_DATA_SETUP_FAIL_CAUSE = "fail_data_setup_fail_cause";
+ protected FailCause mFailDataSetupFailCause = FailCause.ERROR_UNSPECIFIED;
+
+ protected static final String DEFALUT_DATA_ON_BOOT_PROP = "net.def_data_on_boot";
+
// member variables
protected PhoneBase mPhone;
protected Activity mActivity = Activity.NONE;
@@ -206,9 +236,6 @@
protected int mNoRecvPollCount = 0;
protected boolean mNetStatPollEnabled = false;
- /** 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
protected boolean mIsWifiConnected = false;
@@ -221,7 +248,7 @@
/** 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.
+ // When false we will not auto attach and manually attaching is required.
protected boolean mAutoAttachOnCreation = false;
// State of screen
@@ -229,12 +256,6 @@
// 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);
@@ -242,15 +263,39 @@
protected HashMap<Integer, DataConnection> mDataConnections =
new HashMap<Integer, DataConnection>();
+ /** The data connection async channels */
+ protected HashMap<Integer, DataConnectionAc> mDataConnectionAsyncChannels =
+ new HashMap<Integer, DataConnectionAc>();
+
+ /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
+ protected HashMap<String, Integer> mApnToDataConnectionId =
+ new HashMap<String, Integer>();
+
+ /** Phone.APN_TYPE_* ===> ApnContext */
+ protected ConcurrentHashMap<String, ApnContext> mApnContexts;
+
/* Currently active APN */
protected ApnSetting mActiveApn;
+ /** allApns holds all apns */
+ protected ArrayList<ApnSetting> mAllApns = null;
+
+ /** preferred apn */
+ protected ApnSetting mPreferredApn = null;
+
+ /** Is packet service restricted by network */
+ protected boolean mIsPsRestricted = false;
+
+ /* Once disposed dont handle any messages */
+ protected boolean mIsDisposed = false;
+
protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
+ if (DBG) log("onReceive: action=" + action);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
mIsScreenOn = true;
stopNetStatPoll();
@@ -259,17 +304,10 @@
mIsScreenOn = false;
stopNetStatPoll();
startNetStatPoll();
- } else if (action.equals(getActionIntentReconnectAlarm())) {
+ } else if (action.startsWith(getActionIntentReconnectAlarm())) {
log("Reconnect alarm. Previous state was " + mState);
+ onActionIntentReconnectAlarm(intent);
- 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);
@@ -283,10 +321,48 @@
// quit and won't report disconnected until next enabling.
mIsWifiConnected = false;
}
+ } else if (action.equals(INTENT_SET_FAIL_DATA_SETUP_COUNTER)) {
+ mFailDataSetupCounter = intent.getIntExtra(FAIL_DATA_SETUP_COUNTER, 1);
+ mFailDataSetupFailCause = FailCause.fromInt(
+ intent.getIntExtra(FAIL_DATA_SETUP_FAIL_CAUSE,
+ FailCause.ERROR_UNSPECIFIED.getErrorCode()));
+ if (DBG) log("set mFailDataSetupCounter=" + mFailDataSetupCounter +
+ " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
}
}
};
+ protected boolean isDataSetupCompleteOk(AsyncResult ar) {
+ if (ar.exception != null) {
+ if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
+ return false;
+ }
+ if (mFailDataSetupCounter <= 0) {
+ if (DBG) log("isDataSetupCompleteOk return true");
+ return true;
+ }
+ ar.result = mFailDataSetupFailCause;
+ if (DBG) {
+ log("isDataSetupCompleteOk return false" +
+ " mFailDataSetupCounter=" + mFailDataSetupCounter +
+ " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
+ }
+ mFailDataSetupCounter -= 1;
+ return false;
+ }
+
+ protected void onActionIntentReconnectAlarm(Intent intent) {
+ 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.arg2 = 0;
+ msg.obj = reason;
+ sendMessage(msg);
+ }
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+ }
+
/**
* Default constructor
*/
@@ -300,6 +376,7 @@
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ filter.addAction(INTENT_SET_FAIL_DATA_SETUP_COUNTER);
mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
Settings.Secure.MOBILE_DATA, 1) == 1;
@@ -310,16 +387,23 @@
// 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);
+
+ dataEnabled[APN_DEFAULT_ID] = SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP,
+ true);
if (dataEnabled[APN_DEFAULT_ID]) {
enabledCount++;
}
- mAutoAttachOnCreation = dataEnabled[APN_DEFAULT_ID];
+
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+ mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
}
public void dispose() {
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ dcac.disconnect();
+ }
+ mDataConnectionAsyncChannels.clear();
+ mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
@@ -333,36 +417,28 @@
return mActivity;
}
- public State getState() {
- return mState;
- }
-
- public String getStateInString() {
- switch (mState) {
- case IDLE: return "IDLE";
- case INITING: return "INIT";
- case CONNECTING: return "CING";
- case SCANNING: return "SCAN";
- case CONNECTED: return "CNTD";
- case DISCONNECTING: return "DING";
- case FAILED: return "FAIL";
- default: return "ERRO";
- }
- }
-
- /**
- * @return the data connections
- */
- public ArrayList<DataConnection> getAllDataConnections() {
- /** TODO: change return type to Collection? */
- return new ArrayList<DataConnection>(mDataConnections.values());
- }
-
public boolean isApnTypeActive(String type) {
// TODO: support simultaneous with List instead
+ if (Phone.APN_TYPE_DUN.equals(type)) {
+ ApnSetting dunApn = fetchDunApn();
+ if (dunApn != null) {
+ return ((mActiveApn != null) && (dunApn.toString().equals(mActiveApn.toString())));
+ }
+ }
return mActiveApn != null && mActiveApn.canHandleType(type);
}
+ protected ApnSetting fetchDunApn() {
+ Context c = mPhone.getContext();
+ String apnData = Settings.Secure.getString(c.getContentResolver(),
+ Settings.Secure.TETHER_DUN_APN);
+ ApnSetting dunSetting = ApnSetting.fromString(apnData);
+ if (dunSetting != null) return dunSetting;
+
+ apnData = c.getResources().getString(R.string.config_tether_apndata);
+ return ApnSetting.fromString(apnData);
+ }
+
public String[] getActiveApnTypes() {
String[] result;
if (mActiveApn != null) {
@@ -374,17 +450,8 @@
return result;
}
- public String getActiveApnType() {
- String result;
- if (mActiveApn != null) {
- result = apnIdToType(mActiveApn.id);
- } else {
- result = null;
- }
- return result;
- }
-
- protected String getActiveApnString() {
+ /** TODO: See if we can remove */
+ public String getActiveApnString(String apnType) {
String result = null;
if (mActiveApn != null) {
result = mActiveApn.apn;
@@ -392,17 +459,6 @@
return result;
}
- /**
- * The data connection is expected to be setup while device
- * 1. has Icc card
- * 2. registered for data service
- * 3. user doesn't explicitly disable data service
- * 4. wifi is not on
- *
- * @return false while no data connection if all above requirements are met.
- */
- public abstract boolean isDataConnectionAsDesired();
-
//The data roaming setting is now located in the shared preferences.
// See if the requested preference value is the same as that stored in
// the shared values. If it is not, then update it.
@@ -412,7 +468,7 @@
Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
if (mPhone.getServiceState().getRoaming()) {
if (enabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
}
sendMessage(obtainMessage(EVENT_ROAMING_ON));
}
@@ -429,10 +485,19 @@
}
}
-
+ // abstract methods
protected abstract String getActionIntentReconnectAlarm();
+ protected abstract void startNetStatPoll();
+ protected abstract void stopNetStatPoll();
+ protected abstract void restartRadio();
+ protected abstract void log(String s);
+ protected abstract void loge(String s);
+ protected abstract boolean isDataAllowed();
+ protected abstract boolean isApnTypeAvailable(String type);
+ public abstract State getState(String apnType);
+ protected abstract void setState(State s);
+ protected abstract void gotoIdleAndNotifyDataConnection(String reason);
- // abstract handler methods
protected abstract boolean onTrySetupData(String reason);
protected abstract void onRoamingOff();
protected abstract void onRoamingOn();
@@ -440,15 +505,22 @@
protected abstract void onRadioOffOrNotAvailable();
protected abstract void onDataSetupComplete(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);
+ protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason);
+ protected abstract void onCleanUpAllConnections(String cause);
+ protected abstract boolean isDataPossible(String apnType);
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
-
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ log("DISCONNECTED_CONNECTED: msg=" + msg);
+ DataConnectionAc dcac = (DataConnectionAc) msg.obj;
+ mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
+ dcac.disconnected();
+ break;
+ }
case EVENT_ENABLE_NEW_APN:
onEnableApn(msg.arg1, msg.arg2);
break;
@@ -463,7 +535,7 @@
case EVENT_ROAMING_OFF:
if (getDataOnRoamingEnabled() == false) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
}
onRoamingOff();
break;
@@ -498,28 +570,47 @@
onVoiceCallEnded();
break;
- case EVENT_CLEAN_UP_CONNECTION:
- boolean tearDown = (msg.arg1 == 0) ? false : true;
- onCleanUpConnection(tearDown, (String) msg.obj);
+ case EVENT_CLEAN_UP_ALL_CONNECTIONS: {
+ onCleanUpAllConnections((String) msg.obj);
break;
-
+ }
+ case EVENT_CLEAN_UP_CONNECTION: {
+ boolean tearDown = (msg.arg1 == 0) ? false : true;
+ onCleanUpConnection(tearDown, msg.arg2, (String) msg.obj);
+ break;
+ }
case EVENT_SET_INTERNAL_DATA_ENABLE: {
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
onSetInternalDataEnabled(enabled);
break;
}
- case EVENT_RESET_DONE:
+ case EVENT_RESET_DONE: {
+ if (DBG) log("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;
+ if (DBG) log("CMD_SET_DATA_ENABLE enabled=" + enabled);
onSetDataEnabled(enabled);
break;
}
+ case CMD_SET_DEPENDENCY_MET: {
+ boolean met = (msg.arg1 == ENABLED) ? true : false;
+ if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
+ Bundle bundle = msg.getData();
+ if (bundle != null) {
+ String apnType = (String)bundle.get(APN_TYPE_KEY);
+ if (apnType != null) {
+ onSetDependencyMet(apnType, met);
+ }
+ }
+ break;
+ }
+
default:
- Log.e("DATA", "Unidentified event = " + msg.what);
+ Log.e("DATA", "Unidentified event msg=" + msg);
break;
}
}
@@ -536,16 +627,6 @@
return result;
}
- protected abstract void startNetStatPoll();
-
- protected abstract void stopNetStatPoll();
-
- protected abstract void restartRadio();
-
- 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;
@@ -557,6 +638,12 @@
return APN_DUN_ID;
} else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
return APN_HIPRI_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_IMS)) {
+ return APN_IMS_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_FOTA)) {
+ return APN_FOTA_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_CBS)) {
+ return APN_CBS_ID;
} else {
return APN_INVALID_ID;
}
@@ -574,20 +661,25 @@
return Phone.APN_TYPE_DUN;
case APN_HIPRI_ID:
return Phone.APN_TYPE_HIPRI;
+ case APN_IMS_ID:
+ return Phone.APN_TYPE_IMS;
+ case APN_FOTA_ID:
+ return Phone.APN_TYPE_FOTA;
+ case APN_CBS_ID:
+ return Phone.APN_TYPE_CBS;
default:
log("Unknown id (" + id + ") in apnIdToType");
return Phone.APN_TYPE_DEFAULT;
}
}
- protected abstract boolean isApnTypeAvailable(String type);
-
- protected abstract void setState(State s);
-
protected LinkProperties getLinkProperties(String apnType) {
int id = apnTypeToId(apnType);
+
if (isApnIdEnabled(id)) {
- return new LinkProperties(mLinkProperties);
+ // TODO - remove this cdma-only hack and support multiple DCs.
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
+ return dcac.getLinkPropertiesSync();
} else {
return new LinkProperties();
}
@@ -596,33 +688,14 @@
protected LinkCapabilities getLinkCapabilities(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
- return new LinkCapabilities(mLinkCapabilities);
+ // TODO - remove this cdma-only hack and support multiple DCs.
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
+ return dcac.getLinkCapabilitiesSync();
} else {
return new LinkCapabilities();
}
}
- /**
- * 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();
- }
-
- /**
- * 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();
- }
-
// tell all active apns of the current condition
protected void notifyDataConnection(String reason) {
for (int id = 0; id < APN_NUM_TYPES; id++) {
@@ -678,39 +751,15 @@
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());
+ notifyOffApnsOfAvailability(reason, isDataPossible(Phone.APN_TYPE_DEFAULT));
}
- /**
- * 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 dataAllowed = isDataAllowed();
- boolean anyDataEnabled = getAnyDataEnabled();
- boolean possible = (dataAllowed
- && !(anyDataEnabled && (mState == State.FAILED || mState == State.IDLE)));
- if (!possible && DBG) {
- log("isDataPossible() " + possible + ", dataAllowed=" + dataAllowed +
- " anyDataEnabled=" + anyDataEnabled + " dataState=" + mState);
- }
- return possible;
- }
-
- protected abstract boolean isDataAllowed();
-
public boolean isApnTypeEnabled(String apnType) {
if (apnType == null) {
- apnType = getActiveApnType();
+ return false;
+ } else {
+ return isApnIdEnabled(apnTypeToId(apnType));
}
- return isApnIdEnabled(apnTypeToId(apnType));
}
protected synchronized boolean isApnIdEnabled(int id) {
@@ -790,7 +839,7 @@
}
}
- private void setEnabled(int id, boolean enable) {
+ protected void setEnabled(int id, boolean enable) {
if (DBG) {
log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id]
+ " and enabledCount = " + enabledCount);
@@ -801,7 +850,7 @@
sendMessage(msg);
}
- protected synchronized void onEnableApn(int apnId, int enabled) {
+ protected void onEnableApn(int apnId, int enabled) {
if (DBG) {
log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) +
", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] +
@@ -809,9 +858,11 @@
isApnTypeActive(apnIdToType(apnId)));
}
if (enabled == ENABLED) {
- if (!dataEnabled[apnId]) {
- dataEnabled[apnId] = true;
- enabledCount++;
+ synchronized (this) {
+ if (!dataEnabled[apnId]) {
+ dataEnabled[apnId] = true;
+ enabledCount++;
+ }
}
String type = apnIdToType(apnId);
if (!isApnTypeActive(type)) {
@@ -822,12 +873,16 @@
}
} else {
// disable
- if (dataEnabled[apnId]) {
- dataEnabled[apnId] = false;
- enabledCount--;
- if (enabledCount == 0) {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ boolean didDisable = false;
+ synchronized (this) {
+ if (dataEnabled[apnId]) {
+ dataEnabled[apnId] = false;
+ enabledCount--;
+ didDisable = true;
}
+ }
+ if (didDisable && enabledCount == 0) {
+ onCleanUpConnection(true, apnId, Phone.REASON_DATA_DISABLED);
// send the disconnect msg manually, since the normal route wont send
// it (it's not enabled)
@@ -855,6 +910,22 @@
}
/**
+ * Called when EVENT_RESET_DONE is received so goto
+ * IDLE state and send notifications to those interested.
+ *
+ * TODO - currently unused. Needs to be hooked into DataConnection cleanup
+ * TODO - needs to pass some notion of which connection is reset..
+ */
+ protected void onResetDone(AsyncResult ar) {
+ if (DBG) log("EVENT_RESET_DONE");
+ String reason = null;
+ if (ar.userObj instanceof String) {
+ reason = (String) ar.userObj;
+ }
+ gotoIdleAndNotifyDataConnection(reason);
+ }
+
+ /**
* 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.
@@ -881,19 +952,23 @@
}
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ cleanUpAllConnections(null);
}
}
}
}
- public synchronized boolean getDataEnabled() {
- return mDataEnabled;
+ public void cleanUpAllConnections(String cause) {
+ Message msg = obtainMessage(EVENT_CLEAN_UP_ALL_CONNECTIONS);
+ msg.obj = cause;
+ sendMessage(msg);
}
+ public abstract boolean isAnyActiveDataConnections();
+
protected void onSetDataEnabled(boolean enable) {
boolean prevEnabled = getAnyDataEnabled();
if (mDataEnabled != enable) {
@@ -904,12 +979,22 @@
Settings.Secure.MOBILE_DATA, enable ? 1 : 0);
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
}
}
}
}
+
+ protected void onSetDependencyMet(String apnType, boolean met) {
+ }
+
+
+ protected void resetAllRetryCounts() {
+ for (DataConnection dc : mDataConnections.values()) {
+ dc.resetRetryCount();
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 83db3d1..910905a 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -114,8 +114,8 @@
try {
mRegistry.notifyDataConnection(
convertDataState(state),
- sender.isDataConnectivityPossible(), reason,
- sender.getActiveApnHost(),
+ sender.isDataConnectivityPossible(apnType), reason,
+ sender.getActiveApnHost(apnType),
apnType,
linkProperties,
linkCapabilities,
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 3c4bb12..19441cd 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -145,6 +145,15 @@
boolean supplyPin(String pin);
/**
+ * Supply puk to unlock the SIM and set SIM pin to new pin.
+ * Blocks until a result is determined.
+ * @param puk The puk to check.
+ * pin The new pin to be set in SIM
+ * @return whether the operation was a success.
+ */
+ boolean supplyPuk(String puk, String pin);
+
+ /**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
* without SEND (so <code>dial</code> is not appropriate).
*
@@ -254,10 +263,20 @@
* Returns the network type
*/
int getNetworkType();
-
+
/**
* Return true if an ICC card is present
*/
boolean hasIccCard();
+
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link PHone#LTE_ON_CDMA_TRUE}
+ */
+ int getLteOnCdmaMode();
}
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index e270ce9..5d8fc78 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -18,16 +18,28 @@
import static android.Manifest.permission.READ_PHONE_STATE;
import android.app.ActivityManagerNative;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
+import android.os.Power;
+import android.os.PowerManager;
import android.os.Registrant;
import android.os.RegistrantList;
import android.util.Log;
+import android.view.WindowManager;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.CommandsInterface.RadioState;
+import com.android.internal.telephony.gsm.SIMRecords;
+
+import android.os.SystemProperties;
+
+import com.android.internal.R;
/**
* {@hide}
@@ -84,6 +96,9 @@
private static final int EVENT_CHANGE_ICC_PASSWORD_DONE = 9;
private static final int EVENT_QUERY_FACILITY_FDN_DONE = 10;
private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 11;
+ private static final int EVENT_ICC_STATUS_CHANGED = 12;
+ private static final int EVENT_CARD_REMOVED = 13;
+ private static final int EVENT_CARD_ADDED = 14;
/*
UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
@@ -102,6 +117,11 @@
public boolean isPinLocked() {
return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED));
}
+
+ public boolean iccCardExist() {
+ return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)
+ || (this == NETWORK_LOCKED) || (this == READY));
+ }
}
public State getState() {
@@ -137,11 +157,14 @@
public IccCard(PhoneBase phone, String logTag, Boolean dbg) {
mPhone = phone;
+ mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_STATUS_CHANGED, null);
mLogTag = logTag;
mDbg = dbg;
}
- abstract public void dispose();
+ public void dispose() {
+ mPhone.mCM.unregisterForIccStatusChanged(mHandler);
+ }
protected void finalize() {
if(mDbg) Log.d(mLogTag, "IccCard finalized");
@@ -393,6 +416,8 @@
boolean transitionedIntoPinLocked;
boolean transitionedIntoAbsent;
boolean transitionedIntoNetworkLocked;
+ boolean isIccCardRemoved;
+ boolean isIccCardAdded;
State oldState, newState;
@@ -409,23 +434,87 @@
transitionedIntoAbsent = (oldState != State.ABSENT && newState == State.ABSENT);
transitionedIntoNetworkLocked = (oldState != State.NETWORK_LOCKED
&& newState == State.NETWORK_LOCKED);
+ isIccCardRemoved = (oldState != null &&
+ oldState.iccCardExist() && newState == State.ABSENT);
+ isIccCardAdded = (oldState == State.ABSENT &&
+ newState != null && newState.iccCardExist());
if (transitionedIntoPinLocked) {
- if(mDbg) log("Notify SIM pin or puk locked.");
+ if (mDbg) log("Notify SIM pin or puk locked.");
mPinLockedRegistrants.notifyRegistrants();
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED,
(newState == State.PIN_REQUIRED) ?
INTENT_VALUE_LOCKED_ON_PIN : INTENT_VALUE_LOCKED_ON_PUK);
} else if (transitionedIntoAbsent) {
- if(mDbg) log("Notify SIM missing.");
+ if (mDbg) log("Notify SIM missing.");
mAbsentRegistrants.notifyRegistrants();
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_ABSENT, null);
} else if (transitionedIntoNetworkLocked) {
- if(mDbg) log("Notify SIM network locked.");
+ if (mDbg) log("Notify SIM network locked.");
mNetworkLockedRegistrants.notifyRegistrants();
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED,
INTENT_VALUE_LOCKED_NETWORK);
}
+
+ if (isIccCardRemoved) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
+ } else if (isIccCardAdded) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
+ }
+
+
+
+ /*
+ * TODO: We need to try to remove this, maybe if the RIL sends up a RIL_UNSOL_SIM_REFRESH?
+ */
+ if (oldState != State.READY && newState == State.READY &&
+ mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ if (mPhone.mIccRecords instanceof SIMRecords) {
+ ((SIMRecords)mPhone.mIccRecords).onSimReady();
+ }
+ }
+
+ }
+
+ private void onIccSwap(boolean isAdded) {
+ // TODO: Here we assume the device can't handle SIM hot-swap
+ // and has to reboot. We may want to add a property,
+ // e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support
+ // hot-swap.
+ DialogInterface.OnClickListener listener = null;
+
+
+ // TODO: SimRecords is not reset while SIM ABSENT (only reset while
+ // Radio_off_or_not_available). Have to reset in both both
+ // added or removed situation.
+ listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ if (mDbg) log("Reboot due to SIM swap");
+ PowerManager pm = (PowerManager) mPhone.getContext()
+ .getSystemService(Context.POWER_SERVICE);
+ pm.reboot("SIM is added.");
+ }
+ }
+
+ };
+
+ Resources r = Resources.getSystem();
+
+ String title = (isAdded) ? r.getString(R.string.sim_added_title) :
+ r.getString(R.string.sim_removed_title);
+ String message = (isAdded) ? r.getString(R.string.sim_added_message) :
+ r.getString(R.string.sim_removed_message);
+ String buttonTxt = r.getString(R.string.sim_restart_button);
+
+ AlertDialog dialog = new AlertDialog.Builder(mPhone.getContext())
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(buttonTxt, listener)
+ .create();
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ dialog.show();
}
/**
@@ -588,6 +677,16 @@
= ar.exception;
((Message)ar.userObj).sendToTarget();
break;
+ case EVENT_ICC_STATUS_CHANGED:
+ Log.d(mLogTag, "Received Event EVENT_ICC_STATUS_CHANGED");
+ mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
+ break;
+ case EVENT_CARD_REMOVED:
+ onIccSwap(false);
+ break;
+ case EVENT_CARD_ADDED:
+ onIccSwap(true);
+ break;
default:
Log.e(mLogTag, "[IccCard] Unknown Event " + msg.what);
}
@@ -612,61 +711,99 @@
currentRadioState == RadioState.SIM_NOT_READY ||
currentRadioState == RadioState.RUIM_NOT_READY ||
currentRadioState == RadioState.NV_NOT_READY ||
- currentRadioState == RadioState.NV_READY) {
+ (currentRadioState == RadioState.NV_READY &&
+ (mPhone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE))) {
return IccCard.State.NOT_READY;
}
if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT ||
currentRadioState == RadioState.SIM_READY ||
currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
- currentRadioState == RadioState.RUIM_READY) {
+ currentRadioState == RadioState.RUIM_READY ||
+ (currentRadioState == RadioState.NV_READY &&
+ (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE))) {
- int index;
+ State csimState =
+ getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
+ State usimState =
+ getAppState(mIccCardStatus.getGsmUmtsSubscriptionAppIndex());
+
+ if(mDbg) log("USIM=" + usimState + " CSIM=" + csimState);
+
+ if (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ // UICC card contains both USIM and CSIM
+ // Return consolidated status
+ return getConsolidatedState(csimState, usimState, csimState);
+ }
// check for CDMA radio technology
if (currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
currentRadioState == RadioState.RUIM_READY) {
- index = mIccCardStatus.getCdmaSubscriptionAppIndex();
+ return csimState;
}
- else {
- index = mIccCardStatus.getGsmUmtsSubscriptionAppIndex();
- }
-
- IccCardApplication app;
- if (index >= 0 && index < IccCardStatus.CARD_MAX_APPS) {
- app = mIccCardStatus.getApplication(index);
- } else {
- Log.e(mLogTag, "[IccCard] Invalid Subscription Application index:" + index);
- return IccCard.State.ABSENT;
- }
-
- if (app == null) {
- Log.e(mLogTag, "[IccCard] Subscription Application in not present");
- return IccCard.State.ABSENT;
- }
-
- // check if PIN required
- if (app.app_state.isPinRequired()) {
- return IccCard.State.PIN_REQUIRED;
- }
- if (app.app_state.isPukRequired()) {
- return IccCard.State.PUK_REQUIRED;
- }
- if (app.app_state.isSubscriptionPersoEnabled()) {
- return IccCard.State.NETWORK_LOCKED;
- }
- if (app.app_state.isAppReady()) {
- return IccCard.State.READY;
- }
- if (app.app_state.isAppNotReady()) {
- return IccCard.State.NOT_READY;
- }
- return IccCard.State.NOT_READY;
+ return usimState;
}
return IccCard.State.ABSENT;
}
+ private State getAppState(int appIndex) {
+ IccCardApplication app;
+ if (appIndex >= 0 && appIndex < IccCardStatus.CARD_MAX_APPS) {
+ app = mIccCardStatus.getApplication(appIndex);
+ } else {
+ Log.e(mLogTag, "[IccCard] Invalid Subscription Application index:" + appIndex);
+ return IccCard.State.ABSENT;
+ }
+
+ if (app == null) {
+ Log.e(mLogTag, "[IccCard] Subscription Application in not present");
+ return IccCard.State.ABSENT;
+ }
+
+ // check if PIN required
+ if (app.app_state.isPinRequired()) {
+ return IccCard.State.PIN_REQUIRED;
+ }
+ if (app.app_state.isPukRequired()) {
+ return IccCard.State.PUK_REQUIRED;
+ }
+ if (app.app_state.isSubscriptionPersoEnabled()) {
+ return IccCard.State.NETWORK_LOCKED;
+ }
+ if (app.app_state.isAppReady()) {
+ return IccCard.State.READY;
+ }
+ if (app.app_state.isAppNotReady()) {
+ return IccCard.State.NOT_READY;
+ }
+ return IccCard.State.NOT_READY;
+ }
+
+ private State getConsolidatedState(State left, State right, State preferredState) {
+ // Check if either is absent.
+ if (right == IccCard.State.ABSENT) return left;
+ if (left == IccCard.State.ABSENT) return right;
+
+ // Only if both are ready, return ready
+ if ((left == IccCard.State.READY) && (right == IccCard.State.READY)) {
+ return State.READY;
+ }
+
+ // Case one is ready, but the other is not.
+ if (((right == IccCard.State.NOT_READY) && (left == IccCard.State.READY)) ||
+ ((left == IccCard.State.NOT_READY) && (right == IccCard.State.READY))) {
+ return IccCard.State.NOT_READY;
+ }
+
+ // At this point, the other state is assumed to be one of locked state
+ if (right == IccCard.State.NOT_READY) return left;
+ if (left == IccCard.State.NOT_READY) return right;
+
+ // At this point, FW currently just assumes the status will be
+ // consistent across the applications...
+ return preferredState;
+ }
public boolean isApplicationOnIcc(IccCardApplication.AppType type) {
if (mIccCardStatus == null) return false;
diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java
index 9f60a6c..434c484 100644
--- a/telephony/java/com/android/internal/telephony/IccCardApplication.java
+++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java
@@ -28,7 +28,8 @@
APPTYPE_SIM,
APPTYPE_USIM,
APPTYPE_RUIM,
- APPTYPE_CSIM
+ APPTYPE_CSIM,
+ APPTYPE_ISIM
};
public enum AppState{
@@ -115,6 +116,7 @@
case 2: newType = AppType.APPTYPE_USIM; break;
case 3: newType = AppType.APPTYPE_RUIM; break;
case 4: newType = AppType.APPTYPE_CSIM; break;
+ case 5: newType = AppType.APPTYPE_ISIM; break;
default:
throw new RuntimeException(
"Unrecognized RIL_AppType: " +type);
@@ -175,4 +177,15 @@
return newSubState;
}
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("{").append(app_type).append(",").append(app_state);
+ if (app_state == AppState.APPSTATE_SUBSCRIPTION_PERSO) {
+ sb.append(",").append(perso_substate);
+ }
+ sb.append("}");
+ return sb.toString();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/IccCardStatus.java b/telephony/java/com/android/internal/telephony/IccCardStatus.java
index 7199616..e9de922 100644
--- a/telephony/java/com/android/internal/telephony/IccCardStatus.java
+++ b/telephony/java/com/android/internal/telephony/IccCardStatus.java
@@ -144,4 +144,33 @@
return mApplications.get(index);
}
+ @Override
+ public String toString() {
+ IccCardApplication app;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("IccCardState {").append(mCardState).append(",")
+ .append(mUniversalPinState)
+ .append(",num_apps=").append(mNumApplications)
+ .append(",gsm_id=").append(mGsmUmtsSubscriptionAppIndex);
+ if (mGsmUmtsSubscriptionAppIndex >=0
+ && mGsmUmtsSubscriptionAppIndex <CARD_MAX_APPS) {
+ app = getApplication(mGsmUmtsSubscriptionAppIndex);
+ sb.append(app == null ? "null" : app);
+ }
+
+ sb.append(",cmda_id=").append(mCdmaSubscriptionAppIndex);
+ if (mCdmaSubscriptionAppIndex >=0
+ && mCdmaSubscriptionAppIndex <CARD_MAX_APPS) {
+ app = getApplication(mCdmaSubscriptionAppIndex);
+ sb.append(app == null ? "null" : app);
+ }
+
+ sb.append(",ism_id=").append(mImsSubscriptionAppIndex);
+
+ sb.append("}");
+
+ return sb.toString();
+ }
+
}
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index b12d2d4..1ba6dfe 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -58,6 +58,23 @@
static final int EF_CST = 0x6f32;
static final int EF_RUIM_SPN =0x6F41;
+ // ETSI TS.102.221
+ static final int EF_PL = 0x2F05;
+ // 3GPP2 C.S0065
+ static final int EF_CSIM_LI = 0x6F3A;
+ static final int EF_CSIM_SPN =0x6F41;
+ static final int EF_CSIM_MDN = 0x6F44;
+ static final int EF_CSIM_IMSIM = 0x6F22;
+ static final int EF_CSIM_CDMAHOME = 0x6F28;
+ static final int EF_CSIM_EPRL = 0x6F5A;
+
+ //ISIM access
+ static final int EF_IMPU = 0x6f04;
+ static final int EF_IMPI = 0x6f02;
+ static final int EF_DOMAIN = 0x6f03;
+ static final int EF_IST = 0x6f07;
+ static final int EF_PCSCF = 0x6f09;
+
// SMS record length from TS 51.011 10.5.3
static public final int SMS_RECORD_LENGTH = 176;
@@ -67,4 +84,7 @@
static final String DF_GRAPHICS = "5F50";
static final String DF_GSM = "7F20";
static final String DF_CDMA = "7F25";
+
+ //ISIM access
+ static final String DF_ADFISIM = "7FFF";
}
diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java
index 92ddd2c..93b9b79 100644
--- a/telephony/java/com/android/internal/telephony/IccFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java
@@ -529,6 +529,7 @@
return MF_SIM + DF_TELECOM;
case EF_ICCID:
+ case EF_PL:
return MF_SIM;
case EF_IMG:
return MF_SIM + DF_TELECOM + DF_GRAPHICS;
diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java
index b8d9e3c..3a27901 100644
--- a/telephony/java/com/android/internal/telephony/IccRecords.java
+++ b/telephony/java/com/android/internal/telephony/IccRecords.java
@@ -21,9 +21,6 @@
import android.os.Message;
import android.os.Registrant;
import android.os.RegistrantList;
-import android.util.Log;
-
-import java.util.ArrayList;
/**
* {@hide}
@@ -79,6 +76,11 @@
this.phone = p;
}
+ /**
+ * Call when the IccRecords object is no longer going to be used.
+ */
+ public abstract void dispose();
+
protected abstract void onRadioOffOrNotAvailable();
//***** Public Methods
@@ -99,6 +101,17 @@
recordsLoadedRegistrants.remove(h);
}
+ /**
+ * Get the International Mobile Subscriber ID (IMSI) on a SIM
+ * for GSM, UMTS and like networks. Default is null if IMSI is
+ * not supported or unavailable.
+ *
+ * @return null if SIM is not yet ready or unavailable
+ */
+ public String getIMSI() {
+ return null;
+ }
+
public String getMsisdnNumber() {
return msisdn;
}
@@ -220,6 +233,7 @@
}
//***** Overridden from Handler
+ @Override
public abstract void handleMessage(Message msg);
protected abstract void onRecordLoaded();
@@ -232,8 +246,61 @@
* and TS 51.011 10.3.11 for details.
*
* If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
+ * Generally used for GSM/UMTS and the like SIMs.
*/
- protected abstract int getDisplayRule(String plmn);
+ public abstract int getDisplayRule(String plmn);
+ /**
+ * Return true if "Restriction of menu options for manual PLMN selection"
+ * bit is set or EF_CSP data is unavailable, return false otherwise.
+ * Generally used for GSM/UMTS and the like SIMs.
+ */
+ public boolean isCspPlmnEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns the 5 or 6 digit MCC/MNC of the operator that
+ * provided the SIM card. Returns null of SIM is not yet ready
+ * or is not valid for the type of IccCard. Generally used for
+ * GSM/UMTS and the like SIMS
+ */
+ public String getOperatorNumeric() {
+ return null;
+ }
+
+ /**
+ * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs
+ *
+ * @return true if enabled
+ */
+ public boolean getVoiceCallForwardingFlag() {
+ return false;
+ }
+
+ /**
+ * Set the voice call forwarding flag for GSM/UMTS and the like SIMs
+ *
+ * @param line to enable/disable
+ * @param enable
+ */
+ public void setVoiceCallForwardingFlag(int line, boolean enable) {
+ }
+
+ /**
+ * Indicates wether SIM is in provisioned state or not.
+ * Overridden only if SIM can be dynamically provisioned via OTA.
+ *
+ * @return true if provisioned
+ */
+ public boolean isProvisioned () {
+ return true;
+ }
+
+ /**
+ * Write string to log file
+ *
+ * @param s is the string to write
+ */
protected abstract void log(String s);
}
diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
index df579b0..8e60e6e 100644
--- a/telephony/java/com/android/internal/telephony/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -63,6 +63,29 @@
return ret.toString();
}
+ /**
+ * Decode cdma byte into String.
+ */
+ public static String
+ cdmaBcdToString(byte[] data, int offset, int length) {
+ StringBuilder ret = new StringBuilder(length);
+
+ int count = 0;
+ for (int i = offset; count < length; i++) {
+ int v;
+ v = data[i] & 0xf;
+ if (v > 9) v = 0;
+ ret.append((char)('0' + v));
+
+ if (++count == length) break;
+
+ v = (data[i] >> 4) & 0xf;
+ if (v > 9) v = 0;
+ ret.append((char)('0' + v));
+ ++count;
+ }
+ return ret.toString();
+ }
/**
* Decodes a GSM-style BCD byte, returning an int ranging from 0-99.
diff --git a/telephony/java/com/android/internal/telephony/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java
index fde1b59..cdce841 100644
--- a/telephony/java/com/android/internal/telephony/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/MccTable.java
@@ -234,7 +234,7 @@
String country = MccTable.countryCodeForMcc(mcc);
Log.d(LOG_TAG, "locale set to "+language+"_"+country);
- phone.setSystemLocale(language, country);
+ phone.setSystemLocale(language, country, true);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index acb86d4..48c5318 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -21,6 +21,7 @@
import android.net.LinkProperties;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemProperties;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
@@ -125,6 +126,12 @@
static final String APN_TYPE_DUN = "dun";
/** APN type for HiPri traffic */
static final String APN_TYPE_HIPRI = "hipri";
+ /** APN type for FOTA */
+ static final String APN_TYPE_FOTA = "fota";
+ /** APN type for IMS */
+ static final String APN_TYPE_IMS = "ims";
+ /** APN type for CBS */
+ static final String APN_TYPE_CBS = "cbs";
// "Features" accessible through the connectivity manager
static final String FEATURE_ENABLE_MMS = "enableMMS";
@@ -132,6 +139,9 @@
static final String FEATURE_ENABLE_DUN = "enableDUN";
static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
static final String FEATURE_ENABLE_DUN_ALWAYS = "enableDUNAlways";
+ static final String FEATURE_ENABLE_FOTA = "enableFOTA";
+ static final String FEATURE_ENABLE_IMS = "enableIMS";
+ static final String FEATURE_ENABLE_CBS = "enableCBS";
/**
* Return codes for <code>enableApnType()</code>
@@ -140,6 +150,7 @@
static final int APN_REQUEST_STARTED = 1;
static final int APN_TYPE_NOT_AVAILABLE = 2;
static final int APN_REQUEST_FAILED = 3;
+ static final int APN_ALREADY_INACTIVE = 4;
/**
@@ -149,8 +160,8 @@
static final String REASON_ROAMING_OFF = "roamingOff";
static final String REASON_DATA_DISABLED = "dataDisabled";
static final String REASON_DATA_ENABLED = "dataEnabled";
- static final String REASON_GPRS_ATTACHED = "gprsAttached";
- static final String REASON_GPRS_DETACHED = "gprsDetached";
+ static final String REASON_DATA_ATTACHED = "dataAttached";
+ static final String REASON_DATA_DETACHED = "dataDetached";
static final String REASON_CDMA_DATA_ATTACHED = "cdmaDataAttached";
static final String REASON_CDMA_DATA_DETACHED = "cdmaDataDetached";
static final String REASON_APN_CHANGED = "apnChanged";
@@ -164,6 +175,10 @@
static final String REASON_PS_RESTRICT_ENABLED = "psRestrictEnabled";
static final String REASON_PS_RESTRICT_DISABLED = "psRestrictDisabled";
static final String REASON_SIM_LOADED = "simLoaded";
+ static final String REASON_NW_TYPE_CHANGED = "nwTypeChanged";
+ static final String REASON_DATA_DEPENDENCY_MET = "dependencyMet";
+ static final String REASON_DATA_DEPENDENCY_UNMET = "dependencyUnmet";
+ static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged";
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
@@ -180,6 +195,11 @@
static final int PHONE_TYPE_CDMA = RILConstants.CDMA_PHONE;
static final int PHONE_TYPE_SIP = RILConstants.SIP_PHONE;
+ // Modes for LTE_ON_CDMA
+ static final int LTE_ON_CDMA_UNKNOWN = RILConstants.LTE_ON_CDMA_UNKNOWN;
+ static final int LTE_ON_CDMA_FALSE = RILConstants.LTE_ON_CDMA_FALSE;
+ static final int LTE_ON_CDMA_TRUE = RILConstants.LTE_ON_CDMA_TRUE;
+
// Used for preferred network type
// Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone
int NT_MODE_WCDMA_PREF = RILConstants.NETWORK_MODE_WCDMA_PREF;
@@ -193,6 +213,7 @@
int NT_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
int NT_MODE_GLOBAL = RILConstants.NETWORK_MODE_GLOBAL;
+ int NT_MODE_LTE_ONLY = RILConstants.NETWORK_MODE_LTE_ONLY;
int PREFERRED_NT_MODE = RILConstants.PREFERRED_NETWORK_MODE;
@@ -319,7 +340,7 @@
* Returns string for the active APN host.
* @return type as a string or null if none.
*/
- String getActiveApnHost();
+ String getActiveApnHost(String apnType);
/**
* Return the LinkProperties for the named apn or null if not available
@@ -1236,13 +1257,6 @@
void getDataCallList(Message response);
/**
- * Get current mutiple data connection status
- *
- * @return list of data connections
- */
- List<DataConnection> getCurrentDataConnectionList();
-
- /**
* Update the ServiceState CellLocation for current network registration.
*/
void updateServiceLocation();
@@ -1361,6 +1375,11 @@
boolean isDataConnectivityPossible();
/**
+ * Report on whether data connectivity is allowed for an APN.
+ */
+ boolean isDataConnectivityPossible(String apnType);
+
+ /**
* Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
*/
String getDeviceId();
@@ -1686,6 +1705,14 @@
*/
void unsetOnEcbModeExitResponse(Handler h);
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link #LTE_ON_CDMA_UNKNOWN}, {@link #LTE_ON_CDMA_FALSE} or {@link #LTE_ON_CDMA_TRUE}
+ */
+ public int getLteOnCdmaMode();
/**
* TODO: Adding a function for each property is not good.
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 54341b1..40a70a8 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -38,6 +38,8 @@
import com.android.internal.R;
import com.android.internal.telephony.test.SimulatedRadioControl;
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.gsm.SimCard;
import java.util.Locale;
@@ -110,12 +112,15 @@
public CommandsInterface mCM;
protected IccFileHandler mIccFileHandler;
boolean mDnsCheckDisabled = false;
- public DataConnectionTracker mDataConnection;
+ public DataConnectionTracker mDataConnectionTracker;
boolean mDoesRilSendMultipleCallRing;
int mCallRingContinueToken = 0;
int mCallRingDelay;
public boolean mIsTheCurrentActivePhone = true;
boolean mIsVoiceCapable = true;
+ public IccRecords mIccRecords;
+ public IccCard mIccCard;
+ public SMSDispatcher mSMS;
/**
* Set a system property, unless we're in unit test mode
@@ -237,7 +242,8 @@
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
mCM.unSetOnCallRing(this);
- mDataConnection.onCleanUpConnection(false, REASON_RADIO_TURNED_OFF);
+ // Must cleanup all connectionS and needs to use sendMessage!
+ mDataConnectionTracker.cleanUpAllConnections(null);
mIsTheCurrentActivePhone = false;
}
}
@@ -574,7 +580,7 @@
if (l.length() >=5) {
country = l.substring(3, 5);
}
- setSystemLocale(language, country);
+ setSystemLocale(language, country, false);
if (!country.isEmpty()) {
try {
@@ -596,10 +602,14 @@
* Utility code to set the system locale if it's not set already
* @param language Two character language code desired
* @param country Two character country code desired
+ * @param fromMcc Indicating whether the locale is set according to MCC table.
+ * This flag wil be ignored by default implementation.
+ * TODO: Use a source enumeration so that source of the locale
+ * can be prioritized.
*
* {@hide}
*/
- public void setSystemLocale(String language, String country) {
+ public void setSystemLocale(String language, String country, boolean fromMcc) {
String l = SystemProperties.get("persist.sys.language");
String c = SystemProperties.get("persist.sys.country");
@@ -662,6 +672,45 @@
}
/**
+ * Retrieves the ServiceStateTracker of the phone instance.
+ */
+ public ServiceStateTracker getServiceStateTracker() {
+ return null;
+ }
+
+ /**
+ * Get call tracker
+ */
+ public CallTracker getCallTracker() {
+ return null;
+ }
+
+ @Override
+ public IccCard getIccCard() {
+ return mIccCard;
+ }
+
+ @Override
+ public String getIccSerialNumber() {
+ return mIccRecords.iccid;
+ }
+
+ @Override
+ public boolean getIccRecordsLoaded() {
+ return mIccRecords.getRecordsLoaded();
+ }
+
+ @Override
+ public boolean getMessageWaitingIndicator() {
+ return mIccRecords.getVoiceMessageWaiting();
+ }
+
+ @Override
+ public boolean getCallForwardingIndicator() {
+ return mIccRecords.getVoiceCallForwardingFlag();
+ }
+
+ /**
* Query the status of the CDMA roaming preference
*/
public void queryCdmaRoamingPreference(Message response) {
@@ -954,31 +1003,36 @@
}
public String[] getActiveApnTypes() {
- return mDataConnection.getActiveApnTypes();
+ return mDataConnectionTracker.getActiveApnTypes();
}
- public String getActiveApnHost() {
- return mDataConnection.getActiveApnString();
+ public String getActiveApnHost(String apnType) {
+ return mDataConnectionTracker.getActiveApnString(apnType);
}
public LinkProperties getLinkProperties(String apnType) {
- return mDataConnection.getLinkProperties(apnType);
+ return mDataConnectionTracker.getLinkProperties(apnType);
}
public LinkCapabilities getLinkCapabilities(String apnType) {
- return mDataConnection.getLinkCapabilities(apnType);
+ return mDataConnectionTracker.getLinkCapabilities(apnType);
}
public int enableApnType(String type) {
- return mDataConnection.enableApnType(type);
+ return mDataConnectionTracker.enableApnType(type);
}
public int disableApnType(String type) {
- return mDataConnection.disableApnType(type);
+ return mDataConnectionTracker.disableApnType(type);
}
public boolean isDataConnectivityPossible() {
- return ((mDataConnection != null) && (mDataConnection.isDataPossible()));
+ return isDataConnectivityPossible(Phone.APN_TYPE_DEFAULT);
+ }
+
+ public boolean isDataConnectivityPossible(String apnType) {
+ return ((mDataConnectionTracker != null) &&
+ (mDataConnectionTracker.isDataPossible(apnType)));
}
/**
@@ -1008,7 +1062,7 @@
break;
}
- mDataConnection.setState(dcState);
+ mDataConnectionTracker.setState(dcState);
notifyDataConnection(null, Phone.APN_TYPE_DEFAULT);
}
@@ -1080,4 +1134,22 @@
Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
"called, GSMPhone inactive.");
}
+
+ // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
+ public void notifyCallForwardingIndicator() {
+ // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
+ Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ }
+
+ public void notifyDataConnectionFailed(String reason, String apnType) {
+ mNotifier.notifyDataConnectionFailed(this, reason, apnType);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getLteOnCdmaMode() {
+ return mCM.getLteOnCdmaMode();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 2e391cb..74bae44 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -21,8 +21,10 @@
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
+import android.os.SystemProperties;
import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.cdma.CDMALTEPhone;
import com.android.internal.telephony.gsm.GSMPhone;
import com.android.internal.telephony.sip.SipPhone;
import com.android.internal.telephony.sip.SipPhoneFactory;
@@ -34,6 +36,7 @@
static final String LOG_TAG = "PHONE";
static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
static final int SOCKET_OPEN_MAX_RETRY = 3;
+
//***** Class Variables
static private Phone sProxyPhone = null;
@@ -44,8 +47,6 @@
static private Looper sLooper;
static private Context sContext;
- static final int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
-
static final int preferredCdmaSubscription = RILConstants.PREFERRED_CDMA_SUBSCRIPTION;
//***** Class Methods
@@ -96,15 +97,40 @@
sPhoneNotifier = new DefaultPhoneNotifier();
- //Get preferredNetworkMode from Settings.System
+ // Get preferred network mode
+ int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ preferredNetworkMode = Phone.NT_MODE_GLOBAL;
+ }
int networkMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);
Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
- //Get preferredNetworkMode from Settings.System
- int cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, preferredCdmaSubscription);
- Log.i(LOG_TAG, "Cdma Subscription set to " + Integer.toString(cdmaSubscription));
+ // Get cdmaSubscription
+ // TODO: Change when the ril will provides a way to know at runtime
+ // the configuration, bug 4202572. And the ril issues the
+ // RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, bug 4295439.
+ int cdmaSubscription;
+ int lteOnCdma = BaseCommands.getLteOnCdmaModeStatic();
+ switch (lteOnCdma) {
+ case Phone.LTE_ON_CDMA_FALSE:
+ cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_NV;
+ Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
+ break;
+ case Phone.LTE_ON_CDMA_TRUE:
+ cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_RUIM;
+ Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
+ break;
+ case Phone.LTE_ON_CDMA_UNKNOWN:
+ default:
+ //Get cdmaSubscription mode from Settings.System
+ cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
+ preferredCdmaSubscription);
+ Log.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION");
+ break;
+ }
+ Log.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
//reads the system properties and makes commandsinterface
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
@@ -115,9 +141,19 @@
sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
} else if (phoneType == Phone.PHONE_TYPE_CDMA) {
- Log.i(LOG_TAG, "Creating CDMAPhone");
- sProxyPhone = new PhoneProxy(new CDMAPhone(context,
- sCommandsInterface, sPhoneNotifier));
+ switch (BaseCommands.getLteOnCdmaModeStatic()) {
+ case Phone.LTE_ON_CDMA_TRUE:
+ Log.i(LOG_TAG, "Creating CDMALTEPhone");
+ sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ break;
+ case Phone.LTE_ON_CDMA_FALSE:
+ default:
+ Log.i(LOG_TAG, "Creating CDMAPhone");
+ sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ break;
+ }
}
sMadeDefaults = true;
@@ -145,8 +181,18 @@
case RILConstants.NETWORK_MODE_GSM_UMTS:
return Phone.PHONE_TYPE_GSM;
+ // Use CDMA Phone for the global mode including CDMA
case RILConstants.NETWORK_MODE_GLOBAL:
+ case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:
+ case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA:
return Phone.PHONE_TYPE_CDMA;
+
+ case RILConstants.NETWORK_MODE_LTE_ONLY:
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ return Phone.PHONE_TYPE_CDMA;
+ } else {
+ return Phone.PHONE_TYPE_GSM;
+ }
default:
return Phone.PHONE_TYPE_GSM;
}
@@ -165,10 +211,22 @@
}
public static Phone getCdmaPhone() {
+ Phone phone;
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
- Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
- return phone;
+ switch (BaseCommands.getLteOnCdmaModeStatic()) {
+ case Phone.LTE_ON_CDMA_TRUE: {
+ phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier);
+ break;
+ }
+ case Phone.LTE_ON_CDMA_FALSE:
+ case Phone.LTE_ON_CDMA_UNKNOWN:
+ default: {
+ phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
+ break;
+ }
+ }
}
+ return phone;
}
public static Phone getGsmPhone() {
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 15b23bb..c2212db 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -208,8 +208,8 @@
return mActivePhone.getActiveApnTypes();
}
- public String getActiveApnHost() {
- return mActivePhone.getActiveApnHost();
+ public String getActiveApnHost(String apnType) {
+ return mActivePhone.getActiveApnHost(apnType);
}
public LinkProperties getLinkProperties(String apnType) {
@@ -593,10 +593,6 @@
mActivePhone.getDataCallList(response);
}
- public List<DataConnection> getCurrentDataConnectionList() {
- return mActivePhone.getCurrentDataConnectionList();
- }
-
public void updateServiceLocation() {
mActivePhone.updateServiceLocation();
}
@@ -658,7 +654,11 @@
}
public boolean isDataConnectivityPossible() {
- return mActivePhone.isDataConnectivityPossible();
+ return mActivePhone.isDataConnectivityPossible(Phone.APN_TYPE_DEFAULT);
+ }
+
+ public boolean isDataConnectivityPossible(String apnType) {
+ return mActivePhone.isDataConnectivityPossible(apnType);
}
public String getDeviceId() {
@@ -741,6 +741,10 @@
return mActivePhone.getCdmaEriIconMode();
}
+ public Phone getActivePhone() {
+ return mActivePhone;
+ }
+
public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete){
mActivePhone.sendBurstDtmf(dtmfString, on, off, onComplete);
}
@@ -832,4 +836,12 @@
public boolean isCspPlmnEnabled() {
return mActivePhone.isCspPlmnEnabled();
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getLteOnCdmaMode() {
+ return mActivePhone.getLteOnCdmaMode();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 804ace4..40a396e 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -207,9 +207,8 @@
*/
public final class RIL extends BaseCommands implements CommandsInterface {
static final String LOG_TAG = "RILJ";
- private static final boolean DBG = false;
- static final boolean RILJ_LOGD = Config.LOGD;
- static final boolean RILJ_LOGV = DBG ? Config.LOGD : Config.LOGV;
+ static final boolean RILJ_LOGD = true;
+ static final boolean RILJ_LOGV = false; // STOP SHIP if true
/**
* Wake lock timeout should be longer than the longest timeout in
@@ -236,9 +235,6 @@
// WAKE_LOCK_TIMEOUT occurs.
int mRequestMessagesWaiting;
- // Is this the first radio state change?
- private boolean mInitialRadioStateChange = true;
-
//I'd rather this be LinkedList or something
ArrayList<RILRequest> mRequestsList = new ArrayList<RILRequest>();
@@ -606,41 +602,25 @@
}} catch (Throwable tr) {
Log.e(LOG_TAG,"Uncaught exception", tr);
}
+
+ /* We're disconnected so we don't know the ril version */
+ notifyRegistrantsRilConnectionChanged(-1);
}
}
//***** Constructors
- public
- RIL(Context context) {
- this(context, RILConstants.PREFERRED_NETWORK_MODE,
- RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
- }
- public RIL(Context context, int networkMode, int cdmaSubscription) {
+ public RIL(Context context, int preferredNetworkType, int cdmaSubscription) {
super(context);
- mCdmaSubscription = cdmaSubscription;
- mNetworkMode = networkMode;
- //At startup mPhoneType is first set from networkMode
- switch(networkMode) {
- case RILConstants.NETWORK_MODE_WCDMA_PREF:
- case RILConstants.NETWORK_MODE_GSM_ONLY:
- case RILConstants.NETWORK_MODE_WCDMA_ONLY:
- case RILConstants.NETWORK_MODE_GSM_UMTS:
- mPhoneType = RILConstants.GSM_PHONE;
- break;
- case RILConstants.NETWORK_MODE_CDMA:
- case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
- case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
- mPhoneType = RILConstants.CDMA_PHONE;
- break;
- case RILConstants.NETWORK_MODE_GLOBAL:
- mPhoneType = RILConstants.CDMA_PHONE;
- break;
- default:
- mPhoneType = RILConstants.CDMA_PHONE;
+ if (RILJ_LOGD) {
+ riljLog("RIL(context, preferredNetworkType=" + preferredNetworkType +
+ " cdmaSubscription=" + cdmaSubscription + ")");
}
+ mCdmaSubscription = cdmaSubscription;
+ mPreferredNetworkType = preferredNetworkType;
+ mPhoneType = RILConstants.NO_PHONE;
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
@@ -904,10 +884,7 @@
getIMSI(Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
- if (RILJ_LOGD) riljLog(rr.serialString() +
- "> getIMSI:RIL_REQUEST_GET_IMSI " +
- RIL_REQUEST_GET_IMSI +
- " " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1385,37 +1362,15 @@
public void
setRadioPower(boolean on, Message result) {
- //if radio is OFF set preferred NW type and cmda subscription
- if(mInitialRadioStateChange) {
- synchronized (mStateMonitor) {
- if (!mState.isOn()) {
- RILRequest rrPnt = RILRequest.obtain(
- RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, null);
-
- rrPnt.mp.writeInt(1);
- rrPnt.mp.writeInt(mNetworkMode);
- if (RILJ_LOGD) riljLog(rrPnt.serialString() + "> "
- + requestToString(rrPnt.mRequest) + " : " + mNetworkMode);
-
- send(rrPnt);
-
- RILRequest rrCs = RILRequest.obtain(
- RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, null);
- rrCs.mp.writeInt(1);
- rrCs.mp.writeInt(mCdmaSubscription);
- if (RILJ_LOGD) riljLog(rrCs.serialString() + "> "
- + requestToString(rrCs.mRequest) + " : " + mCdmaSubscription);
- send(rrCs);
- }
- }
- }
- RILRequest rr
- = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
+ RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
rr.mp.writeInt(1);
rr.mp.writeInt(on ? 1 : 0);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ + (on ? " on" : " off"));
+ }
send(rr);
}
@@ -1859,6 +1814,8 @@
rr.mp.writeInt(1);
rr.mp.writeInt(networkType);
+ mPreferredNetworkType = networkType;
+
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " : " + networkType);
@@ -2053,25 +2010,7 @@
}
private void switchToRadioState(RadioState newState) {
-
- if (mInitialRadioStateChange) {
- if (newState.isOn()) {
- /* If this is our first notification, make sure the radio
- * is powered off. This gets the radio into a known state,
- * since it's possible for the phone proc to have restarted
- * (eg, if it or the runtime crashed) without the RIL
- * and/or radio knowing.
- */
- if (RILJ_LOGD) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
- setRadioPower(false, null);
- } else {
- if (DBG) Log.d(LOG_TAG, "Radio OFF @ init");
- setRadioState(newState);
- }
- mInitialRadioStateChange = false;
- } else {
- setRadioState(newState);
- }
+ setRadioState(newState);
}
/**
@@ -2286,7 +2225,7 @@
case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break;
case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break;
case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break;
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseInts(p); break;
+ case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseGetPreferredNetworkType(p); break;
case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break;
case RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE: ret = responseVoid(p); break;
@@ -2361,7 +2300,10 @@
case RIL_REQUEST_GET_IMSI:
case RIL_REQUEST_GET_IMEI:
case RIL_REQUEST_GET_IMEISV:
- return "";
+ if (!RILJ_LOGV) {
+ // If not versbose logging just return and don't display IMSI and IMEI, IMEISV
+ return "";
+ }
}
StringBuilder sb;
@@ -2458,9 +2400,10 @@
case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break;
case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break;
- case RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED: ret = responseInts(p); break;
+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break;
case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
+ case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
default:
throw new RuntimeException("Unrecognized unsol response: " + response);
@@ -2639,8 +2582,8 @@
case RIL_UNSOL_SIM_REFRESH:
if (RILJ_LOGD) unsljLogRet(response, ret);
- if (mIccRefreshRegistrant != null) {
- mIccRefreshRegistrant.notifyRegistrant(
+ if (mIccRefreshRegistrants != null) {
+ mIccRefreshRegistrants.notifyRegistrants(
new AsyncResult (null, ret, null));
}
break;
@@ -2765,7 +2708,7 @@
}
break;
- case RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED:
+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
if (RILJ_LOGD) unsljLogRet(response, ret);
if (mCdmaSubscriptionChangedRegistrants != null) {
@@ -2791,6 +2734,30 @@
new AsyncResult (null, null, null));
}
break;
+
+ case RIL_UNSOL_RIL_CONNECTED: {
+ if (RILJ_LOGD) unsljLogRet(response, ret);
+
+ // Initial conditions
+ setRadioPower(false, null);
+ setPreferredNetworkType(mPreferredNetworkType, null);
+ setCdmaSubscriptionSource(mCdmaSubscription, null);
+ notifyRegistrantsRilConnectionChanged(((int[])ret)[0]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifiy all registrants that the ril has connected or disconnected.
+ *
+ * @param rilVer is the version of the ril or -1 if disconnected.
+ */
+ private void notifyRegistrantsRilConnectionChanged(int rilVer) {
+ mRilVersion = rilVer;
+ if (mRilConnectedRegistrants != null) {
+ mRilConnectedRegistrants.notifyRegistrants(
+ new AsyncResult (null, new Integer(rilVer), null));
}
}
@@ -2924,7 +2891,7 @@
String s = p.readString();
- if (RILJ_LOGD) riljLog("< iccIO: "
+ if (RILJ_LOGV) riljLog("< iccIO: "
+ " 0x" + Integer.toHexString(sw1)
+ " 0x" + Integer.toHexString(sw2) + " "
+ s);
@@ -3038,7 +3005,7 @@
dataCall.active = p.readInt();
dataCall.type = p.readString();
String addresses = p.readString();
- if (TextUtils.isEmpty(addresses)) {
+ if (!TextUtils.isEmpty(addresses)) {
dataCall.addresses = addresses.split(" ");
}
} else {
@@ -3047,7 +3014,8 @@
dataCall.active = p.readInt();
dataCall.type = p.readString();
dataCall.ifname = p.readString();
- if (TextUtils.isEmpty(dataCall.ifname)) {
+ if ((dataCall.status == DataConnection.FailCause.NONE.getErrorCode()) &&
+ TextUtils.isEmpty(dataCall.ifname)) {
throw new RuntimeException("getDataCallState, no ifname");
}
String addresses = p.readString();
@@ -3086,7 +3054,7 @@
responseSetupDataCall(Parcel p) {
int ver = p.readInt();
int num = p.readInt();
- if (RILJ_LOGD) riljLog("responseSetupDataCall ver=" + ver + " num=" + num);
+ if (RILJ_LOGV) riljLog("responseSetupDataCall ver=" + ver + " num=" + num);
DataCallState dataCall;
@@ -3196,6 +3164,18 @@
return response;
}
+ private Object responseGetPreferredNetworkType(Parcel p) {
+ int [] response = (int[]) responseInts(p);
+
+ if (response.length >= 1) {
+ // Since this is the response for getPreferredNetworkType
+ // we'll assume that it should be the value we want the
+ // vendor ril to take if we reestablish a connection to it.
+ mPreferredNetworkType = response[0];
+ }
+ return response;
+ }
+
private Object responseGmsBroadcastConfig(Parcel p) {
int num;
ArrayList<SmsBroadcastConfigInfo> response;
@@ -3525,9 +3505,10 @@
case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW";
case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONG";
case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE";
- case RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED: return "CDMA_SUBSCRIPTION_CHANGED";
+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: return "CDMA_SUBSCRIPTION_SOURCE_CHANGED";
case RIL_UNSOl_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED";
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
+ case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED";
default: return "<unknown reponse>";
}
}
@@ -3576,7 +3557,9 @@
send(rr);
}
- public void setPhoneType(int phoneType) { //Set by CDMAPhone and GSMPhone constructor
+ @Override
+ public void setPhoneType(int phoneType) { // Called by CDMAPhone and GSMPhone constructor
+ if (RILJ_LOGD) riljLog("setPhoneType=" + phoneType + " old value=" + mPhoneType);
mPhoneType = phoneType;
}
@@ -3627,12 +3610,12 @@
/**
* {@inheritDoc}
*/
- public void getCdmaSubscriptionSource(int cdmaSubscription , Message response) {
+ @Override
+ public void getCdmaSubscriptionSource(Message response) {
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, response);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
- + " : " + cdmaSubscription);
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index cdf1977..93fc9ce 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -66,6 +66,11 @@
int NETWORK_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
AVAILABLE Application Settings menu*/
+ int NETWORK_MODE_LTE_CDMA_EVDO = 8; /* LTE, CDMA and EvDo */
+ int NETWORK_MODE_LTE_GSM_WCDMA = 9; /* LTE, GSM/WCDMA */
+ int NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA = 10; /* LTE, CDMA, EvDo, GSM/WCDMA */
+ int NETWORK_MODE_LTE_ONLY = 11; /* LTE Only mode. */
+
int PREFERRED_NETWORK_MODE = NETWORK_MODE_WCDMA_PREF;
/* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
@@ -81,6 +86,10 @@
int CDMA_PHONE = 2;
int SIP_PHONE = 3;
+ int LTE_ON_CDMA_UNKNOWN = -1;
+ int LTE_ON_CDMA_FALSE = 0;
+ int LTE_ON_CDMA_TRUE = 1;
+
int CDM_TTY_MODE_DISABLED = 0;
int CDM_TTY_MODE_ENABLED = 1;
@@ -104,6 +113,7 @@
/* Deactivate data call reasons */
int DEACTIVATE_REASON_NONE = 0;
int DEACTIVATE_REASON_RADIO_OFF = 1;
+ int DEACTIVATE_REASON_PDP_RESET = 2;
/*
cat include/telephony/ril.h | \
@@ -138,10 +148,12 @@
int RIL_RESTRICTED_STATE_PS_ALL = 0x10;
/** Data profile for RIL_REQUEST_SETUP_DATA_CALL */
- static final int DATA_PROFILE_DEFAULT = 0;
- static final int DATA_PROFILE_TETHERED = 1;
- static final int DATA_PROFILE_OEM_BASE = 1000;
-
+ public static final int DATA_PROFILE_DEFAULT = 0;
+ public static final int DATA_PROFILE_TETHERED = 1;
+ public static final int DATA_PROFILE_IMS = 2;
+ public static final int DATA_PROFILE_FOTA = 3;
+ public static final int DATA_PROFILE_CBS = 4;
+ public static final int DATA_PROFILE_OEM_BASE = 1000;
int RIL_REQUEST_GET_SIM_STATUS = 1;
int RIL_REQUEST_ENTER_SIM_PIN = 2;
@@ -279,7 +291,8 @@
int RIL_UNSOL_OEM_HOOK_RAW = 1028;
int RIL_UNSOL_RINGBACK_TONE = 1029;
int RIL_UNSOL_RESEND_INCALL_MUTE = 1030;
- int RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED = 1031;
+ int RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1031;
int RIL_UNSOl_CDMA_PRL_CHANGED = 1032;
int RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE = 1033;
+ int RIL_UNSOL_RIL_CONNECTED = 1034;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/RestrictedState.java b/telephony/java/com/android/internal/telephony/RestrictedState.java
similarity index 98%
rename from telephony/java/com/android/internal/telephony/gsm/RestrictedState.java
rename to telephony/java/com/android/internal/telephony/RestrictedState.java
index 3f7d5d7..ad2b88d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RestrictedState.java
+++ b/telephony/java/com/android/internal/telephony/RestrictedState.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
import android.telephony.ServiceState;
diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java
index b1049a2..29bd104 100644
--- a/telephony/java/com/android/internal/telephony/RetryManager.java
+++ b/telephony/java/com/android/internal/telephony/RetryManager.java
@@ -308,12 +308,10 @@
}
/**
- * Reset network re-registration indicator and clear the data-retry counter
- * and turns off retrying forever.
+ * Clear the data-retry counter
*/
public void resetRetryCount() {
mRetryCount = 0;
- mRetryForever = false;
if (DBG) log("resetRetryCount: " + mRetryCount);
}
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index befee8c..6af9b1c 100755
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -582,7 +582,7 @@
* {@link Activity#RESULT_OK} if the message has been broadcast
* to applications
*/
- protected abstract int dispatchMessage(SmsMessageBase sms);
+ public abstract int dispatchMessage(SmsMessageBase sms);
/**
@@ -916,7 +916,7 @@
* @param response
* Callback message is empty on completion
*/
- protected abstract void activateCellBroadcastSms(int activate, Message response);
+ public abstract void activateCellBroadcastSms(int activate, Message response);
/**
* Query the current configuration of cell broadcast SMS.
@@ -925,7 +925,7 @@
* Callback message contains the configuration from the modem on completion
* @see #setCellBroadcastConfig
*/
- protected abstract void getCellBroadcastSmsConfig(Message response);
+ public abstract void getCellBroadcastSmsConfig(Message response);
/**
* Configure cell broadcast SMS.
@@ -937,7 +937,7 @@
* @param response
* Callback message is empty on completion
*/
- protected abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
+ public abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
/**
* Send an acknowledge message.
@@ -1006,6 +1006,27 @@
return new SmsTracker(data, sentIntent, deliveryIntent);
}
+ public void initSipStack(boolean isObg) {
+ // This function should be overridden by the classes that support
+ // switching modes such as the CdmaSMSDispatcher.
+ // Not implemented in GsmSMSDispatcher.
+ Log.e(TAG, "Error! This function should never be executed.");
+ }
+
+ public void switchToCdma() {
+ // This function should be overridden by the classes that support
+ // switching modes such as the CdmaSMSDispatcher.
+ // Not implemented in GsmSMSDispatcher.
+ Log.e(TAG, "Error! This function should never be executed.");
+ }
+
+ public void switchToGsm() {
+ // This function should be overridden by the classes that support
+ // switching modes such as the CdmaSMSDispatcher.
+ // Not implemented in GsmSMSDispatcher.
+ Log.e(TAG, "Error! This function should never be executed.");
+ }
+
private DialogInterface.OnClickListener mListener =
new DialogInterface.OnClickListener() {
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 3f9ffc3..01b807d 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -29,23 +29,6 @@
*/
public abstract class ServiceStateTracker extends Handler {
- /**
- * Access technology currently in use.
- */
- protected static final int DATA_ACCESS_UNKNOWN = 0;
- protected static final int DATA_ACCESS_GPRS = 1;
- protected static final int DATA_ACCESS_EDGE = 2;
- protected static final int DATA_ACCESS_UMTS = 3;
- protected static final int DATA_ACCESS_CDMA_IS95A = 4;
- protected static final int DATA_ACCESS_CDMA_IS95B = 5;
- protected static final int DATA_ACCESS_CDMA_1xRTT = 6;
- protected static final int DATA_ACCESS_CDMA_EvDo_0 = 7;
- protected static final int DATA_ACCESS_CDMA_EvDo_A = 8;
- protected static final int DATA_ACCESS_HSDPA = 9;
- protected static final int DATA_ACCESS_HSUPA = 10;
- protected static final int DATA_ACCESS_HSPA = 11;
- protected static final int DATA_ACCESS_CDMA_EvDo_B = 12;
-
protected CommandsInterface cm;
public ServiceState ss;
@@ -53,6 +36,9 @@
public SignalStrength mSignalStrength;
+ // TODO - this should not be public
+ public RestrictedState mRestrictedState = new RestrictedState();
+
/* The otaspMode passed to PhoneStateListener#onOtaspChanged */
static public final int OTASP_UNINITIALIZED = 0;
static public final int OTASP_UNKNOWN = 1;
@@ -68,15 +54,29 @@
protected boolean mDesiredPowerState;
/**
+ * Values correspond to ServiceState.RADIO_TECHNOLOGY_ definitions.
+ */
+ protected int mRadioTechnology = 0;
+ protected int mNewRadioTechnology = 0;
+
+ /**
* By default, strength polling is enabled. However, if we're
* getting unsolicited signal strength updates from the radio, set
* value to true and don't bother polling any more.
*/
protected boolean dontPollSignalStrength = false;
- protected RegistrantList networkAttachedRegistrants = new RegistrantList();
- protected RegistrantList roamingOnRegistrants = new RegistrantList();
- protected RegistrantList roamingOffRegistrants = new RegistrantList();
+ protected RegistrantList mRoamingOnRegistrants = new RegistrantList();
+ protected RegistrantList mRoamingOffRegistrants = new RegistrantList();
+ protected RegistrantList mAttachedRegistrants = new RegistrantList();
+ protected RegistrantList mDetachedRegistrants = new RegistrantList();
+ protected RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
+ protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
+ protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
+
+ /* Radio power off pending flag and tag counter */
+ private boolean mPendingRadioPowerOffAfterDataOff = false;
+ private int mPendingRadioPowerOffAfterDataOffTag = 0;
protected static final boolean DBG = true;
@@ -86,8 +86,6 @@
/** Waiting period before recheck gprs and voice registration. */
public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
- public static final int DATA_STATE_POLL_SLEEP_MS = 100;
-
/** GSM events */
protected static final int EVENT_RADIO_STATE_CHANGED = 1;
protected static final int EVENT_NETWORK_STATE_CHANGED = 2;
@@ -163,7 +161,6 @@
protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
public ServiceStateTracker() {
-
}
public boolean getDesiredPowerState() {
@@ -180,7 +177,7 @@
*/
public void registerForRoamingOn(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
- roamingOnRegistrants.add(r);
+ mRoamingOnRegistrants.add(r);
if (ss.getRoaming()) {
r.notifyRegistrant();
@@ -188,7 +185,7 @@
}
public void unregisterForRoamingOn(Handler h) {
- roamingOnRegistrants.remove(h);
+ mRoamingOnRegistrants.remove(h);
}
/**
@@ -201,7 +198,7 @@
*/
public void registerForRoamingOff(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
- roamingOffRegistrants.add(r);
+ mRoamingOffRegistrants.add(r);
if (!ss.getRoaming()) {
r.notifyRegistrant();
@@ -209,7 +206,7 @@
}
public void unregisterForRoamingOff(Handler h) {
- roamingOffRegistrants.remove(h);
+ mRoamingOffRegistrants.remove(h);
}
/**
@@ -272,20 +269,183 @@
}
}
- public abstract void handleMessage(Message msg);
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_SET_RADIO_POWER_OFF:
+ synchronized(this) {
+ if (mPendingRadioPowerOffAfterDataOff &&
+ (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
+ if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
+ hangupAndPowerOff();
+ mPendingRadioPowerOffAfterDataOffTag += 1;
+ mPendingRadioPowerOffAfterDataOff = false;
+ } else {
+ log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 +
+ "!= tag=" + mPendingRadioPowerOffAfterDataOffTag);
+ }
+ }
+ break;
+
+ default:
+ log("Unhandled message with number: " + msg.what);
+ break;
+ }
+ }
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);
+ protected abstract void loge(String s);
+
+ public abstract int getCurrentDataConnectionState();
+ public abstract boolean isConcurrentVoiceAndDataAllowed();
+
+ /**
+ * Registration point for transition into DataConnection attached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mAttachedRegistrants.add(r);
+
+ if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+ public void unregisterForDataConnectionAttached(Handler h) {
+ mAttachedRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition into DataConnection detached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mDetachedRegistrants.add(r);
+
+ if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+ public void unregisterForDataConnectionDetached(Handler h) {
+ mDetachedRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition into network attached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj in Message.obj
+ */
+ public void registerForNetworkAttached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+
+ mNetworkAttachedRegistrants.add(r);
+ if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+ public void unregisterForNetworkAttached(Handler h) {
+ mNetworkAttachedRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition into packet service restricted zone.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mPsRestrictEnabledRegistrants.add(r);
+
+ if (mRestrictedState.isPsRestricted()) {
+ r.notifyRegistrant();
+ }
+ }
+
+ public void unregisterForPsRestrictedEnabled(Handler h) {
+ mPsRestrictEnabledRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition out of packet service restricted zone.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mPsRestrictDisabledRegistrants.add(r);
+
+ if (mRestrictedState.isPsRestricted()) {
+ r.notifyRegistrant();
+ }
+ }
+
+ public void unregisterForPsRestrictedDisabled(Handler h) {
+ mPsRestrictDisabledRegistrants.remove(h);
+ }
/**
* Clean up existing voice and data connection then turn off radio power.
*
* Hang up the existing voice calls to decrease call drop rate.
*/
- protected abstract void powerOffRadioSafely();
+ public void powerOffRadioSafely(DataConnectionTracker dcTracker) {
+ synchronized (this) {
+ if (!mPendingRadioPowerOffAfterDataOff) {
+ if (dcTracker.isAnyActiveDataConnections()) {
+ dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
+ Message msg = Message.obtain(this);
+ msg.what = EVENT_SET_RADIO_POWER_OFF;
+ msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
+ if (sendMessageDelayed(msg, 30000)) {
+ if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
+ mPendingRadioPowerOffAfterDataOff = true;
+ } else {
+ log("Cannot send delayed Msg, turn off radio right away.");
+ hangupAndPowerOff();
+ }
+ } else {
+ dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
+ if (DBG) log("Data disconnected, turn off radio right away.");
+ hangupAndPowerOff();
+ }
+ }
+ }
+ }
+
+ /**
+ * process the pending request to turn radio off after data is disconnected
+ *
+ * return true if there is pending request to process; false otherwise.
+ */
+ public boolean processPendingRadioPowerOffAfterDataOff() {
+ synchronized(this) {
+ if (mPendingRadioPowerOffAfterDataOff) {
+ if (DBG) log("Process pending request to turn radio off.");
+ mPendingRadioPowerOffAfterDataOffTag += 1;
+ hangupAndPowerOff();
+ mPendingRadioPowerOffAfterDataOff = false;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Hang up all voice call and turn off radio. Implemented by derived class.
+ */
+ protected abstract void hangupAndPowerOff();
/** Cancel a pending (if any) pollState() operation */
protected void cancelPollState() {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index e6189be..4309309 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -72,6 +72,13 @@
*/
static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
+ /**
+ * The contents of this property is the value of the kernel command line
+ * product_type variable that corresponds to a product that supports LTE on CDMA.
+ * {@see BaseCommands#getLteOnCdmaMode()}
+ */
+ static final String PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE = "telephony.lteOnCdmaProductType";
+
static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type";
//****** SIM Card
diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java
index 1e23e34..df47350 100644
--- a/telephony/java/com/android/internal/telephony/cat/CatService.java
+++ b/telephony/java/com/android/internal/telephony/cat/CatService.java
@@ -33,6 +33,7 @@
import android.util.Config;
import java.io.ByteArrayOutputStream;
+import java.util.Locale;
/**
* Enumeration for representing the tag value of COMPREHENSION-TLV objects. If
@@ -118,6 +119,8 @@
private static IccRecords mIccRecords;
// Service members.
+ // Protects singleton instance lazy initialization.
+ private static final Object sInstanceLock = new Object();
private static CatService sInstance;
private CommandsInterface mCmdIf;
private Context mContext;
@@ -133,6 +136,7 @@
static final int MSG_ID_CALL_SETUP = 4;
static final int MSG_ID_REFRESH = 5;
static final int MSG_ID_RESPONSE = 6;
+ static final int MSG_ID_SIM_READY = 7;
static final int MSG_ID_RIL_MSG_DECODED = 10;
@@ -170,9 +174,11 @@
mIccRecords = ir;
// Register for SIM ready event.
+ mCmdIf.registerForSIMReady(this, MSG_ID_SIM_READY, null);
+ mCmdIf.registerForRUIMReady(this, MSG_ID_SIM_READY, null);
+ mCmdIf.registerForNVReady(this, MSG_ID_SIM_READY, null);
mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
- mCmdIf.reportStkServiceIsRunning(null);
CatLog.d(this, "Is running");
}
@@ -269,8 +275,20 @@
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
break;
case PROVIDE_LOCAL_INFORMATION:
- sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
- return;
+ ResponseData resp;
+ switch (cmdParams.cmdDet.commandQualifier) {
+ case CommandParamsFactory.DTTZ_SETTING:
+ resp = new DTTZResponseData(null);
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
+ break;
+ case CommandParamsFactory.LANGUAGE_SETTING:
+ resp = new LanguageResponseData(Locale.getDefault().getLanguage());
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
+ break;
+ default:
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
+ return;
+ }
case LAUNCH_BROWSER:
case SELECT_ITEM:
case GET_INPUT:
@@ -373,25 +391,30 @@
private void encodeOptionalTags(CommandDetails cmdDet,
ResultCode resultCode, Input cmdInput, ByteArrayOutputStream buf) {
- switch (AppInterface.CommandType.fromInt(cmdDet.typeOfCommand)) {
- case GET_INKEY:
- // ETSI TS 102 384,27.22.4.2.8.4.2.
- // If it is a response for GET_INKEY command and the response timeout
- // occured, then add DURATION TLV for variable timeout case.
- if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) &&
- (cmdInput != null) && (cmdInput.duration != null)) {
- getInKeyResponse(buf, cmdInput);
- }
- break;
- case PROVIDE_LOCAL_INFORMATION:
- if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) &&
- (resultCode.value() == ResultCode.OK.value())) {
- getPliResponse(buf);
- }
- break;
- default:
- CatLog.d(this, "encodeOptionalTags() Unsupported Cmd:" + cmdDet.typeOfCommand);
- break;
+ CommandType cmdType = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand);
+ if (cmdType != null) {
+ switch (cmdType) {
+ case GET_INKEY:
+ // ETSI TS 102 384,27.22.4.2.8.4.2.
+ // If it is a response for GET_INKEY command and the response timeout
+ // occured, then add DURATION TLV for variable timeout case.
+ if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) &&
+ (cmdInput != null) && (cmdInput.duration != null)) {
+ getInKeyResponse(buf, cmdInput);
+ }
+ break;
+ case PROVIDE_LOCAL_INFORMATION:
+ if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) &&
+ (resultCode.value() == ResultCode.OK.value())) {
+ getPliResponse(buf);
+ }
+ break;
+ default:
+ CatLog.d(this, "encodeOptionalTags() Unsupported Cmd:" + cmdDet.typeOfCommand);
+ break;
+ }
+ } else {
+ CatLog.d(this, "encodeOptionalTags() bad Cmd:" + cmdDet.typeOfCommand);
}
}
@@ -515,26 +538,28 @@
*/
public static CatService getInstance(CommandsInterface ci, IccRecords ir,
Context context, IccFileHandler fh, IccCard ic) {
- if (sInstance == null) {
- if (ci == null || ir == null || context == null || fh == null
- || ic == null) {
- return null;
- }
- HandlerThread thread = new HandlerThread("Cat Telephony service");
- thread.start();
- sInstance = new CatService(ci, ir, context, fh, ic);
- CatLog.d(sInstance, "NEW sInstance");
- } else if ((ir != null) && (mIccRecords != ir)) {
- CatLog.d(sInstance, "Reinitialize the Service with SIMRecords");
- mIccRecords = ir;
+ synchronized (sInstanceLock) {
+ if (sInstance == null) {
+ if (ci == null || ir == null || context == null || fh == null
+ || ic == null) {
+ return null;
+ }
+ HandlerThread thread = new HandlerThread("Cat Telephony service");
+ thread.start();
+ sInstance = new CatService(ci, ir, context, fh, ic);
+ CatLog.d(sInstance, "NEW sInstance");
+ } else if ((ir != null) && (mIccRecords != ir)) {
+ CatLog.d(sInstance, "Reinitialize the Service with SIMRecords");
+ mIccRecords = ir;
- // re-Register for SIM ready event.
- mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
- CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
- } else {
- CatLog.d(sInstance, "Return current sInstance");
+ // re-Register for SIM ready event.
+ mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
+ CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
+ } else {
+ CatLog.d(sInstance, "Return current sInstance");
+ }
+ return sInstance;
}
- return sInstance;
}
/**
@@ -579,6 +604,10 @@
case MSG_ID_RESPONSE:
handleCmdResponse((CatResponseMessage) msg.obj);
break;
+ case MSG_ID_SIM_READY:
+ CatLog.d(this, "SIM ready. Reporting STK service running now...");
+ mCmdIf.reportStkServiceIsRunning(null);
+ break;
default:
throw new AssertionError("Unrecognized CAT command: " + msg.what);
}
diff --git a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
index 12204a0..686fe46 100644
--- a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
+++ b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
@@ -53,6 +53,7 @@
static final int REFRESH_UICC_RESET = 0x04;
// Command Qualifier values for PLI command
+ static final int DTTZ_SETTING = 0x03;
static final int LANGUAGE_SETTING = 0x04;
static synchronized CommandParamsFactory getInstance(RilMessageDecoder caller,
@@ -883,6 +884,10 @@
throws ResultException {
CatLog.d(this, "process ProvideLocalInfo");
switch (cmdDet.commandQualifier) {
+ case DTTZ_SETTING:
+ CatLog.d(this, "PLI [DTTZ_SETTING]");
+ mCmdParams = new CommandParams(cmdDet);
+ break;
case LANGUAGE_SETTING:
CatLog.d(this, "PLI [LANGUAGE_SETTING]");
mCmdParams = new CommandParams(cmdDet);
diff --git a/telephony/java/com/android/internal/telephony/cat/ResponseData.java b/telephony/java/com/android/internal/telephony/cat/ResponseData.java
index 677d66b..4846a3e 100644
--- a/telephony/java/com/android/internal/telephony/cat/ResponseData.java
+++ b/telephony/java/com/android/internal/telephony/cat/ResponseData.java
@@ -18,6 +18,8 @@
import com.android.internal.telephony.EncodeException;
import com.android.internal.telephony.GsmAlphabet;
+import java.util.Calendar;
+import com.android.internal.telephony.cat.AppInterface.CommandType;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
@@ -147,4 +149,109 @@
}
}
+// For "PROVIDE LOCAL INFORMATION" command.
+// See TS 31.111 section 6.4.15/ETSI TS 102 223
+// TS 31.124 section 27.22.4.15 for test spec
+class LanguageResponseData extends ResponseData {
+ private String lang;
+
+ public LanguageResponseData(String lang) {
+ super();
+ this.lang = lang;
+ }
+
+ @Override
+ public void format(ByteArrayOutputStream buf) {
+ if (buf == null) {
+ return;
+ }
+
+ // Text string object
+ int tag = 0x80 | ComprehensionTlvTag.LANGUAGE.value();
+ buf.write(tag); // tag
+
+ byte[] data;
+
+ if (lang != null && lang.length() > 0) {
+ data = GsmAlphabet.stringToGsm8BitPacked(lang);
+ }
+ else {
+ data = new byte[0];
+ }
+
+ buf.write(data.length);
+
+ for (byte b : data) {
+ buf.write(b);
+ }
+ }
+}
+
+// For "PROVIDE LOCAL INFORMATION" command.
+// See TS 31.111 section 6.4.15/ETSI TS 102 223
+// TS 31.124 section 27.22.4.15 for test spec
+class DTTZResponseData extends ResponseData {
+ private Calendar calendar;
+
+ public DTTZResponseData(Calendar cal) {
+ super();
+ calendar = cal;
+ }
+
+ @Override
+ public void format(ByteArrayOutputStream buf) {
+ if (buf == null) {
+ return;
+ }
+
+ // DTTZ object
+ int tag = 0x80 | CommandType.PROVIDE_LOCAL_INFORMATION.value();
+ buf.write(tag); // tag
+
+ byte[] data = new byte[8];
+ byte btmp; // temp variable
+
+ data[0] = 0x07; // Write length of DTTZ data
+
+ if (calendar == null) {
+ calendar = Calendar.getInstance();
+ }
+ // Fill year byte
+ btmp = (byte) (calendar.get(java.util.Calendar.YEAR) % 100);
+ data[1] = (byte) (btmp / 10);
+ data[1] += (byte) ((btmp % 10) << 4);
+
+ // Fill month byte
+ btmp = (byte) (calendar.get(java.util.Calendar.MONTH) + 1);
+ data[2] = (byte) (btmp / 10);
+ data[2] += (byte) ((btmp % 10) << 4);
+
+ // Fill day byte
+ btmp = (byte) (calendar.get(java.util.Calendar.DATE));
+ data[3] = (byte) (btmp / 10);
+ data[3] += (byte) ((btmp % 10) << 4);
+
+ // Fill hour byte
+ btmp = (byte) (calendar.get(java.util.Calendar.HOUR_OF_DAY));
+ data[4] = (byte) (btmp / 10);
+ data[4] += (byte) ((btmp % 10) << 4);
+
+ // Fill minute byte
+ btmp = (byte) (calendar.get(java.util.Calendar.MINUTE));
+ data[5] = (byte) (btmp / 10);
+ data[5] += (byte) ((btmp % 10) << 4);
+
+ // Fill second byte
+ btmp = (byte) (calendar.get(java.util.Calendar.SECOND));
+ data[6] = (byte) (btmp / 10);
+ data[6] += (byte) ((btmp % 10) << 4);
+
+ // No time zone info
+ data[7] = (byte) 0xFF;
+
+ for (byte b : data) {
+ buf.write(b);
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java b/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java
index a197c9a..2a1f508 100644
--- a/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java
+++ b/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java
@@ -20,15 +20,15 @@
import com.android.internal.telephony.IccUtils;
import android.os.Handler;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.os.Message;
/**
* Class used for queuing raw ril messages, decoding them into CommanParams
* objects and sending the result back to the CAT Service.
*/
-class RilMessageDecoder extends HierarchicalStateMachine {
+class RilMessageDecoder extends StateMachine {
// constants
private static final int CMD_START = 1;
@@ -101,8 +101,9 @@
mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh);
}
- private class StateStart extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class StateStart extends State {
+ @Override
+ public boolean processMessage(Message msg) {
if (msg.what == CMD_START) {
if (decodeMessageParams((RilMessage)msg.obj)) {
transitionTo(mStateCmdParamsReady);
@@ -115,8 +116,9 @@
}
}
- private class StateCmdParamsReady extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class StateCmdParamsReady extends State {
+ @Override
+ public boolean processMessage(Message msg) {
if (msg.what == CMD_PARAMS_READY) {
mCurrentRilMessage.mResCode = ResultCode.fromInt(msg.arg1);
mCurrentRilMessage.mData = msg.obj;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
new file mode 100644
index 0000000..6a95b67
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.SystemProperties;
+import android.content.Context;
+import android.net.Uri;
+import android.content.Context;
+import android.provider.Telephony;
+import android.content.ContentValues;
+import android.database.SQLException;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.gsm.SimCard;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+import android.util.Log;
+
+public class CDMALTEPhone extends CDMAPhone {
+ static final String LOG_TAG = "CDMA";
+
+ private static final boolean DBG = true;
+
+ // Constructors
+ public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
+ this(context, ci, notifier, false);
+ }
+
+ public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+ boolean unitTestMode) {
+ super(context, ci, notifier, false);
+ }
+
+ @Override
+ protected void initSstIcc() {
+ mSST = new CdmaLteServiceStateTracker(this);
+ mIccRecords = new CdmaLteUiccRecords(this);
+ mIccCard = new SimCard(this, LOG_TAG, DBG);
+ mIccFileHandler = new CdmaLteUiccFileHandler(this);
+ }
+
+ @Override
+ public DataState getDataConnectionState(String apnType) {
+ DataState ret = DataState.DISCONNECTED;
+
+ if (mSST == null) {
+ // Radio Technology Change is ongoning, dispose() and
+ // removeReferences() have already been called
+
+ ret = DataState.DISCONNECTED;
+ } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false) {
+ ret = DataState.DISCONNECTED;
+ } else {
+ switch (mDataConnectionTracker.getState(apnType)) {
+ case FAILED:
+ case IDLE:
+ ret = DataState.DISCONNECTED;
+ break;
+
+ case CONNECTED:
+ case DISCONNECTING:
+ if (mCT.state != Phone.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed()) {
+ ret = DataState.SUSPENDED;
+ } else {
+ ret = DataState.CONNECTED;
+ }
+ break;
+
+ case INITING:
+ case CONNECTING:
+ case SCANNING:
+ ret = DataState.CONNECTING;
+ break;
+ }
+ }
+
+ log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
+ return ret;
+ }
+
+ public boolean updateCurrentCarrierInProvider() {
+ if (mIccRecords != null) {
+ try {
+ Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
+ ContentValues map = new ContentValues();
+ map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric());
+ log("updateCurrentCarrierInProvider insert uri=" + uri);
+ mContext.getContentResolver().insert(uri, map);
+ return true;
+ } catch (SQLException e) {
+ Log.e(LOG_TAG, "[CDMALTEPhone] Can't store current operator ret false", e);
+ }
+ } else {
+ log("updateCurrentCarrierInProvider mIccRecords == null ret false");
+ }
+ return false;
+ }
+
+ @Override
+ public void setSystemLocale(String language, String country, boolean fromMcc) {
+ // Avoid system locale is set from MCC table if CDMALTEPhone is used.
+ // The locale will be picked up based on EFpl/EFli once CSIM records are loaded.
+ if (fromMcc) return;
+
+ super.setSystemLocale(language, country, false);
+ }
+
+ @Override
+ protected void log(String s) {
+ if (DBG)
+ Log.d(LOG_TAG, "[CDMALTEPhone] " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 74adebd..a283062 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -49,6 +49,7 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.IccRecords;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccException;
@@ -66,6 +67,7 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.UUSInfo;
+import com.android.internal.telephony.CallTracker;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
@@ -97,10 +99,7 @@
// Instance Variables
CdmaCallTracker mCT;
- CdmaSMSDispatcher mSMS;
CdmaServiceStateTracker mSST;
- RuimRecords mRuimRecords;
- RuimCard mRuimCard;
ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>();
RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
RuimSmsInterfaceManager mRuimSmsInterfaceManager;
@@ -141,34 +140,43 @@
// Constructors
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
- this(context,ci,notifier, false);
+ super(notifier, context, ci, false);
+ initSstIcc();
+ init(context, notifier);
}
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
super(notifier, context, ci, unitTestMode);
+ initSstIcc();
+ init(context, notifier);
+ }
+ protected void initSstIcc() {
+ mSST = new CdmaServiceStateTracker(this);
+ mIccRecords = new RuimRecords(this);
+ mIccCard = new RuimCard(this, LOG_TAG, DBG);
+ mIccFileHandler = new RuimFileHandler(this);
+ }
+
+ protected void init(Context context, PhoneNotifier notifier) {
mCM.setPhoneType(Phone.PHONE_TYPE_CDMA);
mCT = new CdmaCallTracker(this);
- mSST = new CdmaServiceStateTracker (this);
mSMS = new CdmaSMSDispatcher(this);
- mIccFileHandler = new RuimFileHandler(this);
- mRuimRecords = new RuimRecords(this);
- mDataConnection = new CdmaDataConnectionTracker (this);
- mRuimCard = new RuimCard(this);
+ mDataConnectionTracker = new CdmaDataConnectionTracker (this);
mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
- mCcatService = CatService.getInstance(mCM, mRuimRecords, mContext,
- mIccFileHandler, mRuimCard);
+ mCcatService = CatService.getInstance(mCM, mIccRecords, mContext,
+ mIccFileHandler, mIccCard);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
- mRuimRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
+ mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(this, EVENT_RADIO_ON, null);
mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
- mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
+ mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
mCM.registerForNVReady(this, EVENT_NV_READY, null);
mCM.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
@@ -213,14 +221,15 @@
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
super.dispose();
+ log("dispose");
//Unregister from all former registered events
- mRuimRecords.unregisterForRecordsLoaded(this); //EVENT_RUIM_RECORDS_LOADED
+ mIccRecords.unregisterForRecordsLoaded(this); //EVENT_RUIM_RECORDS_LOADED
mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(this); //EVENT_RADIO_ON
mCM.unregisterForNVReady(this); //EVENT_NV_READY
- mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
+ mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnSuppServiceNotification(this);
removeCallbacks(mExitEcmRunnable);
@@ -228,12 +237,12 @@
//Force all referenced classes to unregister their former registered events
mCT.dispose();
- mDataConnection.dispose();
+ mDataConnectionTracker.dispose();
mSST.dispose();
mSMS.dispose();
mIccFileHandler.dispose(); // instance of RuimFileHandler
- mRuimRecords.dispose();
- mRuimCard.dispose();
+ mIccRecords.dispose();
+ mIccCard.dispose();
mRuimPhoneBookInterfaceManager.dispose();
mRuimSmsInterfaceManager.dispose();
mSubInfo.dispose();
@@ -243,14 +252,15 @@
}
public void removeReferences() {
+ log("removeReferences");
this.mRuimPhoneBookInterfaceManager = null;
this.mRuimSmsInterfaceManager = null;
this.mSMS = null;
this.mSubInfo = null;
- this.mRuimRecords = null;
+ this.mIccRecords = null;
this.mIccFileHandler = null;
- this.mRuimCard = null;
- this.mDataConnection = null;
+ this.mIccCard = null;
+ this.mDataConnectionTracker = null;
this.mCT = null;
this.mSST = null;
this.mEriManager = null;
@@ -270,10 +280,18 @@
return mSST.ss;
}
+ public CallTracker getCallTracker() {
+ return mCT;
+ }
+
public Phone.State getState() {
return mCT.state;
}
+ public ServiceStateTracker getServiceStateTracker() {
+ return mSST;
+ }
+
public String getPhoneName() {
return "CDMA";
}
@@ -319,9 +337,9 @@
public DataActivityState getDataActivityState() {
DataActivityState ret = DataActivityState.NONE;
- if (mSST.getCurrentCdmaDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
+ if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
- switch (mDataConnection.getActivity()) {
+ switch (mDataConnectionTracker.getActivity()) {
case DATAIN:
ret = DataActivityState.DATAIN;
break;
@@ -530,14 +548,6 @@
Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
}
- public IccCard getIccCard() {
- return mRuimCard;
- }
-
- public String getIccSerialNumber() {
- return mRuimRecords.iccid;
- }
-
public void setCallWaiting(boolean enable, Message onComplete) {
Log.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
}
@@ -547,7 +557,7 @@
}
public void setDataRoamingEnabled(boolean enable) {
- mDataConnection.setDataOnRoamingEnabled(enable);
+ mDataConnectionTracker.setDataOnRoamingEnabled(enable);
}
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
@@ -608,15 +618,15 @@
// already been called
ret = DataState.DISCONNECTED;
- } else if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+ } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
// 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 ||
- mDataConnection.isApnTypeActive(apnType) == false) {
+ } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false ||
+ mDataConnectionTracker.isApnTypeActive(apnType) == false) {
ret = DataState.DISCONNECTED;
} else {
- switch (mDataConnection.getState()) {
+ switch (mDataConnectionTracker.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
@@ -625,7 +635,7 @@
case CONNECTED:
case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData()) {
+ && !mSST.isConcurrentVoiceAndDataAllowed()) {
ret = DataState.SUSPENDED;
} else {
ret = DataState.CONNECTED;
@@ -640,6 +650,7 @@
}
}
+ log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
return ret;
}
@@ -707,11 +718,7 @@
}
public boolean getDataRoamingEnabled() {
- return mDataConnection.getDataOnRoamingEnabled();
- }
-
- public List<DataConnection> getCurrentDataConnectionList () {
- return mDataConnection.getAllDataConnections();
+ return mDataConnectionTracker.getDataOnRoamingEnabled();
}
public void setVoiceMailNumber(String alphaTag,
@@ -720,7 +727,7 @@
Message resp;
mVmNumber = voiceMailNumber;
resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
- mRuimRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
+ mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
public String getVoiceMailNumber() {
@@ -742,7 +749,7 @@
* @hide
*/
public int getVoiceMessageCount() {
- int voicemailCount = mRuimRecords.getVoiceMessageCount();
+ int voicemailCount = mIccRecords.getVoiceMessageCount();
// If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility
// that phone was power cycled and would have lost the voicemail count.
// So get the count from preferences.
@@ -767,10 +774,6 @@
return ret;
}
- public boolean getIccRecordsLoaded() {
- return mRuimRecords.getRecordsLoaded();
- }
-
public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
Log.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
}
@@ -851,13 +854,13 @@
/*package*/ void
updateMessageWaitingIndicator(boolean mwi) {
// this also calls notifyMessageWaitingIndicator()
- mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
+ mIccRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
}
/* This function is overloaded to send number of voicemails instead of sending true/false */
/*package*/ void
updateMessageWaitingIndicator(int mwi) {
- mRuimRecords.setVoiceMessageWaiting(1, mwi);
+ mIccRecords.setVoiceMessageWaiting(1, mwi);
}
@Override
@@ -912,7 +915,7 @@
// send an Intent
sendEmergencyCallbackModeChange();
// Re-initiate data connection
- mDataConnection.setInternalDataEnabled(true);
+ mDataConnectionTracker.setInternalDataEnabled(true);
}
}
@@ -1404,6 +1407,7 @@
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
+ log("updateCurrentCarrierInProvider insert uri=" + uri);
getContext().getContentResolver().insert(uri, map);
// Updates MCC MNC device configuration information
@@ -1416,4 +1420,9 @@
}
return false;
}
+
+ protected void log(String s) {
+ if (DBG)
+ Log.d(LOG_TAG, "[CDMAPhone] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index a89f783..db19321 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -134,6 +134,10 @@
public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
voiceCallStartedRegistrants.add(r);
+ // Notify if in call when registering
+ if (state != Phone.State.IDLE) {
+ r.notifyRegistrant(new AsyncResult(null, null, null));
+ }
}
public void unregisterForVoiceCallStarted(Handler h) {
voiceCallStartedRegistrants.remove(h);
@@ -1058,7 +1062,7 @@
if (PhoneNumberUtils.isEmergencyNumber(dialString)) {
if (Phone.DEBUG_PHONE) log("disableDataCallInEmergencyCall");
mIsInEmergencyCall = true;
- phone.mDataConnection.setInternalDataEnabled(false);
+ phone.mDataConnectionTracker.setInternalDataEnabled(false);
}
}
@@ -1075,7 +1079,7 @@
}
if (inEcm.compareTo("false") == 0) {
// Re-initiate data connection
- phone.mDataConnection.setInternalDataEnabled(true);
+ phone.mDataConnectionTracker.setInternalDataEnabled(true);
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index fbe455e..1a15393 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -430,7 +430,7 @@
} else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
|| serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
return DisconnectCause.OUT_OF_SERVICE;
- } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
+ } else if (phone.mCM.getNvState() != CommandsInterface.RadioState.NV_READY
&& phone.getIccCard().getState() != RuimCard.State.READY) {
return DisconnectCause.ICC_ERROR;
} else if (causeCode==CallFailCause.NORMAL_CLEARING) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 1a0dbc2..d55f346 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -20,7 +20,6 @@
import android.util.Log;
import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
@@ -33,8 +32,8 @@
private static final String LOG_TAG = "CDMA";
// ***** Constructor
- private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
- super(phone, name, rm);
+ private CdmaDataConnection(CDMAPhone phone, String name, int id, RetryManager rm) {
+ super(phone, name, id, rm);
}
/**
@@ -49,11 +48,10 @@
synchronized (mCountLock) {
mCount += 1;
}
- CdmaDataConnection cdmaDc = new CdmaDataConnection(phone,
- "CdmaDataConnection-" + mCount, rm);
+ CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDC-" + mCount,
+ id, rm);
cdmaDc.start();
if (DBG) cdmaDc.log("Made " + cdmaDc.getName());
- cdmaDc.mId = id;
return cdmaDc;
}
@@ -68,6 +66,7 @@
protected void onConnect(ConnectionParams cp) {
if (DBG) log("CdmaDataConnection Connecting...");
+ mApn = cp.apn;
createTime = -1;
lastFailTime = -1;
lastFailCause = FailCause.NONE;
@@ -84,7 +83,7 @@
Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
msg.obj = cp;
phone.mCM.setupDataCall(
- Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
+ Integer.toString(getRadioTechnology(RILConstants.SETUP_DATA_TECH_CDMA)),
Integer.toString(dataProfile),
null, null, null,
Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP),
@@ -99,9 +98,9 @@
@Override
protected boolean isDnsOk(String[] domainNameServers) {
- if ((NULL_IP.equals(domainNameServers[0])
+ if (NULL_IP.equals(domainNameServers[0])
&& NULL_IP.equals(domainNameServers[1])
- && !((CDMAPhone) phone).isDnsCheckDisabled())) {
+ && !phone.isDnsCheckDisabled()) {
return false;
} else {
return true;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 8c36106..800615c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -37,10 +37,12 @@
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone;
+import com.android.internal.util.AsyncChannel;
import java.util.ArrayList;
@@ -52,9 +54,6 @@
private CDMAPhone mCdmaPhone;
- //useful for debugging
- boolean mFailNextConnect = false;
-
/** The DataConnection being setup */
private CdmaDataConnection mPendingDataConnection;
@@ -99,13 +98,13 @@
p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
- p.mRuimRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+ p.mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
p.mCM.registerForNVReady(this, EVENT_NV_READY, null);
p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
- p.mSST.registerForCdmaDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
- p.mSST.registerForCdmaDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
+ p.mSST.registerForDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
+ p.mSST.registerForDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
@@ -118,18 +117,20 @@
@Override
public void dispose() {
+ cleanUpConnection(false, null);
+
super.dispose();
// Unregister from all events
mPhone.mCM.unregisterForAvailable(this);
mPhone.mCM.unregisterForOffOrNotAvailable(this);
- mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this);
+ mCdmaPhone.mIccRecords.unregisterForRecordsLoaded(this);
mPhone.mCM.unregisterForNVReady(this);
mPhone.mCM.unregisterForDataNetworkStateChanged(this);
mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
- mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this);
- mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
+ mCdmaPhone.mSST.unregisterForDataConnectionAttached(this);
+ mCdmaPhone.mSST.unregisterForDataConnectionDetached(this);
mCdmaPhone.mSST.unregisterForRoamingOn(this);
mCdmaPhone.mSST.unregisterForRoamingOff(this);
mPhone.mCM.unregisterForCdmaOtaProvision(this);
@@ -158,6 +159,11 @@
}
@Override
+ public synchronized State getState(String apnType) {
+ return mState;
+ }
+
+ @Override
protected boolean isApnTypeAvailable(String type) {
for (String s : mSupportedApnTypes) {
if (TextUtils.equals(type, s)) {
@@ -167,42 +173,18 @@
return false;
}
- /**
- * The data connection is expected to be setup while device
- * 1. has ruim card or non-volatile data store
- * 2. registered to data connection service
- * 3. user doesn't explicitly disable data service
- * 4. wifi is not on
- *
- * @return false while no data connection if all above requirements are met.
- */
- @Override
- public boolean isDataConnectionAsDesired() {
- boolean roaming = mPhone.getServiceState().getRoaming();
-
- if (((mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
- mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
- (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
- ServiceState.STATE_IN_SERVICE) &&
- (!roaming || getDataOnRoamingEnabled()) &&
- !mIsWifiConnected ) {
- return (mState == State.CONNECTED);
- }
- return true;
- }
-
@Override
protected boolean isDataAllowed() {
- int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
+ int psState = mCdmaPhone.mSST.getCurrentDataConnectionState();
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.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
+ mCdmaPhone.mIccRecords.getRecordsLoaded()) &&
+ (mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
mPhone.getState() == Phone.State.IDLE) &&
!roaming &&
mInternalDataEnabled &&
@@ -214,11 +196,11 @@
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 (!(mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
+ mCdmaPhone.mIccRecords.getRecordsLoaded())) {
+ reason += " - radioState= " + mPhone.mCM.getNvState() + " - RUIM not loaded";
}
- if (!(mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+ if (!(mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
mPhone.getState() == Phone.State.IDLE)) {
reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
}
@@ -232,6 +214,16 @@
return allowed;
}
+ @Override
+ protected boolean isDataPossible(String apnType) {
+ boolean possible = isDataAllowed() && !(getAnyDataEnabled() &&
+ (mState == State.FAILED || mState == State.IDLE));
+ if (!possible && DBG && isDataAllowed()) {
+ log("Data not possible. No coverage: dataState = " + mState);
+ }
+ return possible;
+ }
+
private boolean trySetupData(String reason) {
if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
@@ -246,7 +238,7 @@
return true;
}
- int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
+ int psState = mCdmaPhone.mSST.getCurrentDataConnectionState();
boolean roaming = mPhone.getServiceState().getRoaming();
boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
@@ -262,9 +254,7 @@
}
/**
- * Cleanup all connections.
- *
- * TODO: Cleanup only a specified connection passed as a parameter.
+ * Cleanup the CDMA data connection (only one is supported)
*
* @param tearDown true if the underlying DataConnection should be disconnected.
* @param reason for the clean up.
@@ -286,14 +276,18 @@
boolean notificationDeferred = false;
for (DataConnection conn : mDataConnections.values()) {
if(conn != null) {
+ DataConnectionAc dcac =
+ mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
if (tearDown) {
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
+ conn.tearDown(reason, obtainMessage(EVENT_DISCONNECT_DONE,
conn.getDataConnectionId(), 0, reason));
notificationDeferred = true;
} else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
- conn.resetSynchronously();
+ if (dcac != null) {
+ dcac.resetSync();
+ }
notificationDeferred = false;
}
}
@@ -308,11 +302,13 @@
}
private CdmaDataConnection findFreeDataConnection() {
- for (DataConnection dc : mDataConnections.values()) {
- if (dc.isInactive()) {
- return (CdmaDataConnection) dc;
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.isInactiveSync()) {
+ log("found free GsmDataConnection");
+ return (CdmaDataConnection) dcac.dataConnection;
}
}
+ log("NO free CdmaDataConnection");
return null;
}
@@ -338,12 +334,12 @@
}
mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "",
"", 0, types, "IP", "IP");
- if (DBG) log("setupData: mActiveApn=" + mActiveApn);
+ if (DBG) log("call conn.bringUp mActiveApn=" + mActiveApn);
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
- conn.connect(msg, mActiveApn);
+ conn.bringUp(msg, mActiveApn);
setState(State.INITING);
notifyDataConnection(reason);
@@ -354,7 +350,7 @@
setState(State.CONNECTED);
notifyDataConnection(reason);
startNetStatPoll();
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
}
private void resetPollStats() {
@@ -386,7 +382,7 @@
protected void restartRadio() {
if (DBG) log("Cleanup connection and wait " +
(TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio");
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+ cleanUpAllConnections(null);
sendEmptyMessageDelayed(EVENT_RESTART_RADIO, TIME_DELAYED_TO_RESTART_RADIO);
mPendingRestartRadio = true;
}
@@ -504,21 +500,9 @@
* at the last time until the state is changed.
* TODO: Make this configurable?
*/
- int nextReconnectDelay = mRetryMgr.getRetryTimer();
- log("Data Connection activate failed. Scheduling next attempt for "
- + (nextReconnectDelay / 1000) + "s");
-
- AlarmManager am =
- (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(
- mPhone.getContext(), 0, intent, 0);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + nextReconnectDelay,
- mReconnectIntent);
-
- mRetryMgr.increaseRetryCount();
+ int nextReconnectDelay = mDataConnections.get(0).getRetryTimer();
+ startAlarmForReconnect(nextReconnectDelay, reason);
+ mDataConnections.get(0).increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
log("NOT Posting Data Connection Unavailable notification "
@@ -529,12 +513,28 @@
}
}
+ private void startAlarmForReconnect(int delay, String reason) {
+
+ log("Data Connection activate failed. Scheduling next attempt for "
+ + (delay / 1000) + "s");
+
+ AlarmManager am =
+ (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(
+ mPhone.getContext(), 0, intent, 0);
+ am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delay, mReconnectIntent);
+
+ }
+
private void notifyNoData(FailCause lastFailCauseCode) {
setState(State.FAILED);
notifyDataAvailability(null);
}
- private void gotoIdleAndNotifyDataConnection(String reason) {
+ protected void gotoIdleAndNotifyDataConnection(String reason) {
if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
setState(State.IDLE);
notifyDataConnection(reason);
@@ -543,14 +543,14 @@
protected void onRecordsLoaded() {
if (mState == State.FAILED) {
- cleanUpConnection(false, null);
+ cleanUpAllConnections(null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
}
protected void onNVReady() {
if (mState == State.FAILED) {
- cleanUpConnection(false, null);
+ cleanUpAllConnections(null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
}
@@ -560,6 +560,7 @@
*/
@Override
protected void onEnableNewApn() {
+ // No mRequestedApnType check; only one connection is supported
cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
}
@@ -588,7 +589,7 @@
trySetupData(Phone.REASON_ROAMING_ON);
} else {
if (DBG) log("Tear down data connection on roaming.");
- cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+ cleanUpAllConnections(null);
}
}
@@ -609,7 +610,7 @@
notifyDataAvailability(null);
if (mState != State.IDLE) {
- cleanUpConnection(true, null);
+ cleanUpAllConnections(null);
}
}
@@ -618,7 +619,7 @@
*/
@Override
protected void onRadioOffOrNotAvailable() {
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
@@ -626,7 +627,7 @@
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);
+ cleanUpAllConnections(null);
}
}
@@ -640,12 +641,8 @@
reason = (String) ar.userObj;
}
- if (ar.exception == null) {
- // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mPendingDataConnection);
- mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
-
- // everything is setup
+ if (isDataSetupCompleteOk(ar)) {
+ // Everything is setup
notifyDefaultData(reason);
} else {
FailCause cause = (FailCause) (ar.result);
@@ -688,30 +685,17 @@
notifyDataConnection(reason);
mActiveApn = null;
if (retryAfterDisconnected(reason)) {
- trySetupData(reason);
+ // Wait a bit before trying, so we're not tying up RIL command channel.
+ startAlarmForReconnect(APN_DELAY_MILLIS, reason);
}
}
/**
- * Called when EVENT_RESET_DONE is received so goto
- * IDLE state and send notifications to those interested.
- */
- @Override
- protected void onResetDone(AsyncResult ar) {
- if (DBG) log("EVENT_RESET_DONE");
- String reason = null;
- if (ar.userObj instanceof String) {
- reason = (String) ar.userObj;
- }
- gotoIdleAndNotifyDataConnection(reason);
- }
-
- /**
* @override com.android.internal.telephony.DataConnectionTracker
*/
@Override
protected void onVoiceCallStarted() {
- if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+ if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED);
@@ -724,7 +708,7 @@
@Override
protected void onVoiceCallEnded() {
if (mState == State.CONNECTED) {
- if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+ if (!mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
} else {
@@ -733,36 +717,52 @@
}
notifyDataAvailability(Phone.REASON_VOICE_CALL_ENDED);
} else {
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
// in case data setup was attempted when we were on a voice call
trySetupData(Phone.REASON_VOICE_CALL_ENDED);
}
}
@Override
- protected void onCleanUpConnection(boolean tearDown, String reason) {
+ protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) {
+ // No apnId check; only one connection is supported
cleanUpConnection(tearDown, reason);
}
+ @Override
+ protected void onCleanUpAllConnections(String cause) {
+ // Only one CDMA connection is supported
+ cleanUpConnection(true, cause);
+ }
+
private void createAllDataConnectionList() {
CdmaDataConnection 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);
- }
- }
-
+ String retryConfig = SystemProperties.get("ro.cdma.data_retry_config");
for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
- int id = mUniqueIdGenerator.getAndIncrement();
+ RetryManager rm = new RetryManager();
+ if (!rm.configure(retryConfig)) {
+ 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);
+ }
+ }
+ int id = mUniqueIdGenerator.getAndIncrement();
dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
mDataConnections.put(id, dataConn);
+ DataConnectionAc dcac = new DataConnectionAc(dataConn, LOG_TAG);
+ int status = dcac.fullyConnectSync(mPhone.getContext(), this, dataConn.getHandler());
+ if (status == AsyncChannel.STATUS_SUCCESSFUL) {
+ log("Fully connected");
+ mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
+ } else {
+ log("Could not connect to dcac.dataConnection=" + dcac.dataConnection +
+ " status=" + status);
+ }
+
}
}
@@ -779,7 +779,7 @@
} else {
if (mState == State.FAILED) {
cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
@@ -797,7 +797,7 @@
switch (otaPrivision[0]) {
case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
break;
default:
break;
@@ -893,8 +893,9 @@
@Override
public void handleMessage (Message msg) {
+ if (DBG) log("CdmaDCT handleMessage msg=" + msg);
- if (!mPhone.mIsTheCurrentActivePhone) {
+ if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore CDMA msgs since CDMA phone is inactive");
return;
}
@@ -933,12 +934,17 @@
}
@Override
+ public boolean isAnyActiveDataConnections() {
+ return (mState != State.IDLE);
+ }
+
+ @Override
protected void log(String s) {
- Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+ Log.d(LOG_TAG, "[CdmaDCT] " + s);
}
@Override
protected void loge(String s) {
- Log.e(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+ Log.e(LOG_TAG, "[CdmaDCT] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
new file mode 100644
index 0000000..abd87b8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.RILConstants;
+
+import android.telephony.SignalStrength;
+import android.telephony.ServiceState;
+import android.telephony.cdma.CdmaCellLocation;
+import android.os.AsyncResult;
+import android.os.Message;
+
+
+import android.util.Log;
+import android.util.EventLog;
+
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
+ CDMALTEPhone mCdmaLtePhone;
+
+ private ServiceState mLteSS; // The last LTE state from Voice Registration
+
+ public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
+ super(phone);
+ cm.registerForSIMReady(this, EVENT_SIM_READY, null);
+ mCdmaLtePhone = phone;
+
+ mLteSS = new ServiceState();
+ if (DBG) log("CdmaLteServiceStateTracker Constructors");
+ }
+
+ @Override
+ public void dispose() {
+ cm.unregisterForSIMReady(this);
+ super.dispose();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+ int[] ints;
+ String[] strings;
+ switch (msg.what) {
+ case EVENT_POLL_STATE_GPRS:
+ if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS");
+ ar = (AsyncResult)msg.obj;
+ handlePollStateResult(msg.what, ar);
+ break;
+ case EVENT_SIM_READY:
+ if (DBG) log("handleMessage EVENT_SIM_READY");
+ isSubscriptionFromRuim = false;
+ // Register SIM_RECORDS_LOADED dynamically.
+ // This is to avoid confilct with RUIM_READY scenario)
+ phone.mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
+ pollState();
+ // Signal strength polling stops when radio is off.
+ queueNextSignalStrengthPoll();
+ break;
+ case EVENT_SIM_RECORDS_LOADED:
+ CdmaLteUiccRecords sim = (CdmaLteUiccRecords)phone.mIccRecords;
+ if ((sim != null) && sim.isProvisioned()) {
+ mMdn = sim.getMdn();
+ mMin = sim.getMin();
+ parseSidNid(sim.getSid(), sim.getNid());
+ mPrlVersion = sim.getPrlVersion();;
+ mIsMinInfoReady = true;
+ updateOtaspState();
+ }
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+
+ /**
+ * Set the cdmaSS for EVENT_POLL_STATE_REGISTRATION_CDMA
+ */
+ @Override
+ protected void setCdmaTechnology(int radioTechnology) {
+ // Called on voice registration state response.
+ // Just record new CDMA radio technology
+ newSS.setRadioTechnology(radioTechnology);
+ }
+
+ /**
+ * Handle the result of one of the pollState()-related requests
+ */
+ @Override
+ protected void handlePollStateResultMessage(int what, AsyncResult ar) {
+ if (what == EVENT_POLL_STATE_GPRS) {
+ if (DBG) log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS");
+ String states[] = (String[])ar.result;
+
+ int type = 0;
+ int regState = -1;
+ if (states.length > 0) {
+ try {
+ regState = Integer.parseInt(states[0]);
+
+ // states[3] (if present) is the current radio technology
+ if (states.length >= 4 && states[3] != null) {
+ type = Integer.parseInt(states[3]);
+ }
+ } catch (NumberFormatException ex) {
+ loge("handlePollStateResultMessage: error parsing GprsRegistrationState: "
+ + ex);
+ }
+ }
+
+ mLteSS.setRadioTechnology(type);
+ mLteSS.setState(regCodeToServiceState(regState));
+ } else {
+ super.handlePollStateResultMessage(what, ar);
+ }
+ }
+
+ @Override
+ protected void setSignalStrengthDefaultValues() {
+ mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, false);
+ }
+
+ @Override
+ protected void pollState() {
+ pollingContext = new int[1];
+ pollingContext[0] = 0;
+
+ switch (cm.getRadioState()) {
+ case RADIO_UNAVAILABLE:
+ newSS.setStateOutOfService();
+ newCellLoc.setStateInvalid();
+ setSignalStrengthDefaultValues();
+ mGotCountryCode = false;
+
+ pollStateDone();
+ break;
+
+ case RADIO_OFF:
+ newSS.setStateOff();
+ newCellLoc.setStateInvalid();
+ setSignalStrengthDefaultValues();
+ mGotCountryCode = false;
+
+ pollStateDone();
+ break;
+
+ default:
+ // Issue all poll-related commands at once, then count
+ // down the responses which are allowed to arrive
+ // out-of-order.
+
+ pollingContext[0]++;
+ // RIL_REQUEST_OPERATOR is necessary for CDMA
+ cm.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
+
+ pollingContext[0]++;
+ // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA
+ cm.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA,
+ pollingContext));
+
+ int networkMode = android.provider.Settings.Secure.getInt(phone.getContext()
+ .getContentResolver(),
+ android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+ RILConstants.PREFERRED_NETWORK_MODE);
+ if (DBG) log("pollState: network mode here is = " + networkMode);
+ if ((networkMode == RILConstants.NETWORK_MODE_GLOBAL)
+ || (networkMode == RILConstants.NETWORK_MODE_LTE_ONLY)) {
+ pollingContext[0]++;
+ // RIL_REQUEST_DATA_REGISTRATION_STATE
+ cm.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS,
+ pollingContext));
+ }
+ break;
+ }
+ }
+
+ @Override
+ protected void pollStateDone() {
+ // determine data NetworkType from both LET and CDMA SS
+ if (mLteSS.getState() == ServiceState.STATE_IN_SERVICE) {
+ //in LTE service
+ newNetworkType = mLteSS.getRadioTechnology();
+ mNewDataConnectionState = mLteSS.getState();
+ newSS.setRadioTechnology(newNetworkType);
+ log("pollStateDone LTE/eHRPD STATE_IN_SERVICE newNetworkType = " + newNetworkType);
+ } else {
+ // LTE out of service, get CDMA Service State
+ newNetworkType = newSS.getRadioTechnology();
+ mNewDataConnectionState = radioTechnologyToDataServiceState(newNetworkType);
+ log("pollStateDone CDMA STATE_IN_SERVICE newNetworkType = " + newNetworkType +
+ " mNewDataConnectionState = " + mNewDataConnectionState);
+ }
+
+ if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
+
+ if (cm.getSimState().isSIMReady()) {
+ // If CSIM is used, check roaming status according to SID/NID
+ // on EFcdmahome record.
+ newSS.setRoaming(!isInHomeSidNid(newSS.getSystemId(), newSS.getNetworkId()));
+ }
+
+ boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
+ && newSS.getState() == ServiceState.STATE_IN_SERVICE;
+
+ boolean hasDeregistered = ss.getState() == ServiceState.STATE_IN_SERVICE
+ && newSS.getState() != ServiceState.STATE_IN_SERVICE;
+
+ boolean hasCdmaDataConnectionAttached =
+ mDataConnectionState != ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
+
+ boolean hasCdmaDataConnectionDetached =
+ mDataConnectionState == ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
+
+ boolean hasCdmaDataConnectionChanged =
+ mDataConnectionState != mNewDataConnectionState;
+
+ boolean hasNetworkTypeChanged = networkType != newNetworkType;
+
+ boolean hasChanged = !newSS.equals(ss);
+
+ boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
+
+ boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
+
+ boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
+
+ boolean has4gHandoff =
+ ((networkType == ServiceState.RADIO_TECHNOLOGY_LTE) &&
+ (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) ||
+ ((networkType == ServiceState.RADIO_TECHNOLOGY_EHRPD) &&
+ (newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE));
+
+ boolean hasMultiApnSupport =
+ (((newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE) ||
+ (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) &&
+ ((networkType != ServiceState.RADIO_TECHNOLOGY_LTE) &&
+ (networkType != ServiceState.RADIO_TECHNOLOGY_EHRPD)));
+
+ boolean hasLostMultiApnSupport =
+ ((newNetworkType >= ServiceState.RADIO_TECHNOLOGY_IS95A) &&
+ (newNetworkType <= ServiceState.RADIO_TECHNOLOGY_EVDO_A));
+
+ if (DBG) {
+ log("pollStateDone:"
+ + " hasRegistered=" + hasRegistered
+ + " hasDeegistered=" + hasDeregistered
+ + " hasCdmaDataConnectionAttached=" + hasCdmaDataConnectionAttached
+ + " hasCdmaDataConnectionDetached=" + hasCdmaDataConnectionDetached
+ + " hasCdmaDataConnectionChanged=" + hasCdmaDataConnectionChanged
+ + " hasNetworkTypeChanged = " + hasNetworkTypeChanged
+ + " hasChanged=" + hasChanged
+ + " hasRoamingOn=" + hasRoamingOn
+ + " hasRoamingOff=" + hasRoamingOff
+ + " hasLocationChanged=" + hasLocationChanged
+ + " has4gHandoff = " + has4gHandoff
+ + " hasMultiApnSupport=" + hasMultiApnSupport
+ + " hasLostMultiApnSupport=" + hasLostMultiApnSupport);
+ }
+ // Add an event log when connection state changes
+ if (ss.getState() != newSS.getState()
+ || mDataConnectionState != mNewDataConnectionState) {
+ EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, ss.getState(),
+ mDataConnectionState, newSS.getState(), mNewDataConnectionState);
+ }
+
+ ServiceState tss;
+ tss = ss;
+ ss = newSS;
+ newSS = tss;
+ // clean slate for next time
+ newSS.setStateOutOfService();
+ mLteSS.setStateOutOfService();
+
+ if ((hasMultiApnSupport)
+ && (phone.mDataConnectionTracker instanceof CdmaDataConnectionTracker)) {
+ if (DBG) log("GsmDataConnectionTracker Created");
+ phone.mDataConnectionTracker.dispose();
+ phone.mDataConnectionTracker = new GsmDataConnectionTracker(mCdmaLtePhone);
+ }
+
+ if ((hasLostMultiApnSupport)
+ && (phone.mDataConnectionTracker instanceof GsmDataConnectionTracker)) {
+ if (DBG)log("GsmDataConnectionTracker disposed");
+ phone.mDataConnectionTracker.dispose();
+ phone.mDataConnectionTracker = new CdmaDataConnectionTracker(phone);
+ }
+
+ CdmaCellLocation tcl = cellLoc;
+ cellLoc = newCellLoc;
+ newCellLoc = tcl;
+
+ mDataConnectionState = mNewDataConnectionState;
+ networkType = newNetworkType;
+
+ newSS.setStateOutOfService(); // clean slate for next time
+
+ if (hasNetworkTypeChanged) {
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
+ ServiceState.radioTechnologyToString(networkType));
+ }
+
+ if (hasRegistered) {
+ mNetworkAttachedRegistrants.notifyRegistrants();
+ }
+
+ if (hasChanged) {
+ if (cm.getNvState().isNVReady()) {
+ String eriText;
+ // Now the CDMAPhone sees the new ServiceState so it can get the
+ // new ERI text
+ if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+ eriText = phone.getCdmaEriText();
+ } else {
+ // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
+ // for
+ // mRegistrationState 0,2,3 and 4
+ eriText = phone.getContext()
+ .getText(com.android.internal.R.string.roamingTextSearching).toString();
+ }
+ ss.setOperatorAlphaLong(eriText);
+ }
+ if (cm.getSimState().isSIMReady()) {
+ // SIM is found on the device. Read the operator name from the card.
+ ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName());
+
+ // If SIM card is present, Eri will not be used. Turn it off
+ ss.setCdmaEriIconIndex(EriInfo.ROAMING_INDICATOR_OFF);
+ }
+
+ String operatorNumeric;
+
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
+ ss.getOperatorAlphaLong());
+
+ operatorNumeric = ss.getOperatorNumeric();
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+
+ if (operatorNumeric == null) {
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
+ } else {
+ String isoCountryCode = "";
+ try {
+ isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric
+ .substring(0, 3)));
+ } catch (NumberFormatException ex) {
+ loge("countryCodeForMcc error" + ex);
+ } catch (StringIndexOutOfBoundsException ex) {
+ loge("countryCodeForMcc error" + ex);
+ }
+
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
+ isoCountryCode);
+ mGotCountryCode = true;
+ if (mNeedFixZone) {
+ fixTimeZone(isoCountryCode);
+ }
+ }
+
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
+ ss.getRoaming() ? "true" : "false");
+
+ updateSpnDisplay();
+ phone.notifyServiceStateChanged(ss);
+ }
+
+ if (hasCdmaDataConnectionAttached) {
+ mAttachedRegistrants.notifyRegistrants();
+ }
+
+ if (hasCdmaDataConnectionDetached) {
+ mDetachedRegistrants.notifyRegistrants();
+ }
+
+ if ((hasCdmaDataConnectionChanged || hasNetworkTypeChanged)) {
+ phone.notifyDataConnection();
+ }
+
+ if (hasRoamingOn) {
+ mRoamingOnRegistrants.notifyRegistrants();
+ }
+
+ if (hasRoamingOff) {
+ mRoamingOffRegistrants.notifyRegistrants();
+ }
+
+ if (hasLocationChanged) {
+ phone.notifyLocationChanged();
+ }
+ }
+
+ @Override
+ protected void onSignalStrengthResult(AsyncResult ar) {
+ SignalStrength oldSignalStrength = mSignalStrength;
+
+ if (ar.exception != null) {
+ // Most likely radio is resetting/disconnected change to default
+ // values.
+ setSignalStrengthDefaultValues();
+ } else {
+ int[] ints = (int[])ar.result;
+ int lteCqi = 99, lteRsrp = -1;
+ int lteRssi = 99;
+ int offset = 2;
+ int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -120;
+ int cdmaEcio = (ints[offset + 1] > 0) ? -ints[offset + 1] : -160;
+ int evdoRssi = (ints[offset + 2] > 0) ? -ints[offset + 2] : -120;
+ int evdoEcio = (ints[offset + 3] > 0) ? -ints[offset + 3] : -1;
+ int evdoSnr = ((ints[offset + 4] > 0) && (ints[offset + 4] <= 8)) ? ints[offset + 4]
+ : -1;
+ if (networkType == ServiceState.RADIO_TECHNOLOGY_LTE) {
+ lteRssi = (ints[offset + 5] >= 0) ? ints[offset + 5] : 99;
+ lteRsrp = (ints[offset + 6] < 0) ? ints[offset + 6] : -1;
+ lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 7] : 99;
+ }
+
+ if (networkType != ServiceState.RADIO_TECHNOLOGY_LTE) {
+ mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio, evdoRssi, evdoEcio,
+ evdoSnr, false);
+ } else {
+ mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio, evdoRssi, evdoEcio,
+ evdoSnr, lteRssi, lteRsrp, -1, -1, lteCqi, true);
+ }
+ }
+
+ try {
+ phone.notifySignalStrength();
+ } catch (NullPointerException ex) {
+ loge("onSignalStrengthResult() Phone already destroyed: " + ex
+ + "SignalStrength not notified");
+ }
+ }
+
+ @Override
+ public boolean isConcurrentVoiceAndDataAllowed() {
+ // Note: it needs to be confirmed which CDMA network types
+ // can support voice and data calls concurrently.
+ // For the time-being, the return value will be false.
+ // return (networkType >= ServiceState.RADIO_TECHNOLOGY_LTE);
+ return false;
+ }
+
+ /**
+ * Returns OTASP_NOT_NEEDED as its not needed for LTE
+ */
+ @Override
+ int getOtasp() {
+ int provisioningState = OTASP_NOT_NEEDED;
+ if (DBG) log("getOtasp: state=" + provisioningState);
+ return provisioningState;
+ }
+
+ /**
+ * Check whether the specified SID and NID pair appears in the HOME SID/NID list
+ * read from NV or SIM.
+ *
+ * @return true if provided sid/nid pair belongs to operator's home network.
+ */
+ private boolean isInHomeSidNid(int sid, int nid) {
+ // if SID/NID is not available, do not declare roaming.
+ if (isSidsAllZeros()) return true;
+
+ // length of SID/NID shold be same
+ if (mHomeSystemId.length != mHomeNetworkId.length) return true;
+
+ if (sid == 0) return true;
+
+ for (int i = 0; i < mHomeSystemId.length; i++) {
+ // Use SID only if NID is a reserved value.
+ // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
+ if ((mHomeSystemId[i] == sid) &&
+ ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
+ (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
new file mode 100644
index 0000000..b9d7c46
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.util.Log;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccFileHandler;
+import android.os.Message;
+
+/**
+ * {@hide}
+ */
+public final class CdmaLteUiccFileHandler extends IccFileHandler {
+ static final String LOG_TAG = "CDMA";
+
+ CdmaLteUiccFileHandler(CDMALTEPhone phone) {
+ super(phone);
+ }
+
+ protected String getEFPath(int efid) {
+ switch(efid) {
+ case EF_CSIM_SPN:
+ case EF_CSIM_LI:
+ case EF_CSIM_MDN:
+ case EF_CSIM_IMSIM:
+ case EF_CSIM_CDMAHOME:
+ case EF_CSIM_EPRL:
+ return MF_SIM + DF_CDMA;
+ case EF_AD:
+ return MF_SIM + DF_GSM;
+ }
+ return getCommonIccEFPath(efid);
+ }
+
+ @Override
+ public void loadEFTransparent(int fileid, Message onLoaded) {
+ if (fileid == EF_CSIM_EPRL) {
+ // Entire PRL could be huge. We are only interested in
+ // the first 4 bytes of the record.
+ phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
+ 0, 0, 4, null, null,
+ obtainMessage(EVENT_READ_BINARY_DONE,
+ fileid, 0, onLoaded));
+ } else {
+ super.loadEFTransparent(fileid, onLoaded);
+ }
+ }
+
+
+ protected void logd(String msg) {
+ Log.d(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg);
+ }
+
+ protected void loge(String msg) {
+ Log.e(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg);
+ }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
new file mode 100755
index 0000000..58ef747
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.cdma;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.gsm.SIMRecords;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.util.Log;
+import java.util.Locale;
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public final class CdmaLteUiccRecords extends SIMRecords {
+ // From CSIM application
+ private byte[] mEFpl = null;
+ private byte[] mEFli = null;
+ boolean csimSpnDisplayCondition = false;
+ private String mMdn;
+ private String mMin;
+ private String mPrlVersion;
+ private String mHomeSystemId;
+ private String mHomeNetworkId;
+
+ private static final int EVENT_GET_PL_DONE = CSIM_EVENT_BASE;
+ private static final int EVENT_GET_CSIM_LI_DONE = CSIM_EVENT_BASE + 1;
+ private static final int EVENT_GET_CSIM_SPN_DONE = CSIM_EVENT_BASE + 2;
+ private static final int EVENT_GET_CSIM_MDN_DONE = CSIM_EVENT_BASE + 3;
+ private static final int EVENT_GET_CSIM_IMSIM_DONE = CSIM_EVENT_BASE + 4;
+ private static final int EVENT_GET_CSIM_CDMAHOME_DONE = CSIM_EVENT_BASE + 5;
+ private static final int EVENT_GET_CSIM_EPRL_DONE = CSIM_EVENT_BASE + 6;
+
+ public CdmaLteUiccRecords(PhoneBase p) {
+ super(p);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+ byte data[];
+
+ boolean isCsimRecordLoadResponse = false;
+
+ try { switch (msg.what) {
+ case EVENT_GET_PL_DONE:
+ // Refer to ETSI TS.102.221
+ if (DBG) log("EF_GET_EF_PL_DONE");
+ isCsimRecordLoadResponse = true;
+
+ ar = (AsyncResult) msg.obj;
+
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception = " + ar.exception);
+ break;
+ }
+
+ mEFpl = (byte[]) ar.result;
+ if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
+ break;
+
+ case EVENT_GET_CSIM_LI_DONE:
+ // Refer to C.S0065 5.2.26
+ if (DBG) log("EVENT_GET_CSIM_LI_DONE");
+ isCsimRecordLoadResponse = true;
+
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception = " + ar.exception);
+ break;
+ }
+
+ mEFli = (byte[]) ar.result;
+ // convert csim efli data to iso 639 format
+ for (int i = 0; i < mEFli.length; i+=2) {
+ switch(mEFli[i+1]) {
+ case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
+ case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
+ case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
+ case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
+ case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
+ case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
+ case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
+ default: mEFli[i] = ' '; mEFli[i+1] = ' ';
+ }
+ }
+
+ if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
+ break;
+ case EVENT_GET_CSIM_SPN_DONE:
+ // Refer to C.S0065 5.2.32
+ if (DBG) log("EVENT_GET_CSIM_SPN_DONE");
+ isCsimRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception=" + ar.exception);
+ break;
+ }
+ onGetCSimSpnDone(ar);
+ break;
+ case EVENT_GET_CSIM_MDN_DONE:
+ if (DBG) log("EVENT_GET_CSIM_MDN_DONE");
+ isCsimRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception=" + ar.exception);
+ break;
+ }
+ onGetCSimMdnDone(ar);
+ break;
+ case EVENT_GET_CSIM_IMSIM_DONE:
+ if (DBG) log("EVENT_GET_CSIM_IMSIM_DONE");
+ isCsimRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception=" + ar.exception);
+ break;
+ }
+ onGetCSimImsimDone(ar);
+ break;
+ case EVENT_GET_CSIM_CDMAHOME_DONE:
+ if (DBG) log("EVENT_GET_CSIM_CDMAHOME_DONE");
+ isCsimRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception=" + ar.exception);
+ break;
+ }
+ onGetCSimCdmaHomeDone(ar);
+ break;
+ case EVENT_GET_CSIM_EPRL_DONE:
+ if (DBG) log("EVENT_GET_CSIM_EPRL_DONE");
+ isCsimRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ Log.e(LOG_TAG, "ar.exception=" + ar.exception);
+ break;
+ }
+ onGetCSimEprlDone(ar);
+ break;
+ default:
+ super.handleMessage(msg);
+ }}catch (RuntimeException exc) {
+ Log.w(LOG_TAG, "Exception parsing SIM record", exc);
+ } finally {
+ if (isCsimRecordLoadResponse) {
+ onRecordLoaded();
+ }
+ }
+ }
+
+ @Override
+ protected void onRecordLoaded() {
+ // One record loaded successfully or failed, In either case
+ // we need to update the recordsToLoad count
+ recordsToLoad -= 1;
+
+ if (recordsToLoad == 0 && recordsRequested == true) {
+ onAllRecordsLoaded();
+ } else if (recordsToLoad < 0) {
+ Log.e(LOG_TAG, "SIMRecords: recordsToLoad <0, programmer error suspected");
+ recordsToLoad = 0;
+ }
+ }
+
+ @Override
+ protected void onAllRecordsLoaded() {
+ super.onAllRecordsLoaded();
+ setLocaleFromCsim();
+ }
+
+ @Override
+ protected void fetchSimRecords() {
+ IccFileHandler iccFh = phone.getIccFileHandler();
+ recordsRequested = true;
+
+ phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_PL, obtainMessage(EVENT_GET_PL_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_CSIM_LI, obtainMessage(EVENT_GET_CSIM_LI_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_CSIM_SPN, obtainMessage(EVENT_GET_CSIM_SPN_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFLinearFixed(EF_CSIM_MDN, 1, obtainMessage(EVENT_GET_CSIM_MDN_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_CSIM_IMSIM, obtainMessage(EVENT_GET_CSIM_IMSIM_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME,
+ obtainMessage(EVENT_GET_CSIM_CDMAHOME_DONE));
+ recordsToLoad++;
+
+ iccFh.loadEFTransparent(EF_CSIM_EPRL, obtainMessage(EVENT_GET_CSIM_EPRL_DONE));
+ recordsToLoad++;
+ }
+
+ private void onGetCSimSpnDone(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_SPN=" +
+ IccUtils.bytesToHexString(data));
+
+ // C.S0065 for EF_SPN decoding
+ csimSpnDisplayCondition = ((0x02 & data[0]) > 0)?true:false;
+
+ int encoding = data[1];
+ int language = data[2];
+ byte[] spnData = new byte[32];
+ System.arraycopy(data, 3, spnData, 0, (data.length < 32)?data.length:32);
+
+ int numBytes;
+ for (numBytes = 0; numBytes < spnData.length; numBytes++) {
+ if ((spnData[numBytes] & 0xFF) == 0xFF) break;
+ }
+
+ if (numBytes == 0) {
+ spn = "";
+ return;
+ }
+ try {
+ switch (encoding) {
+ case UserData.ENCODING_OCTET:
+ case UserData.ENCODING_LATIN:
+ spn = new String(spnData, 0, numBytes, "ISO-8859-1");
+ break;
+ case UserData.ENCODING_IA5:
+ case UserData.ENCODING_GSM_7BIT_ALPHABET:
+ case UserData.ENCODING_7BIT_ASCII:
+ spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7);
+ break;
+ case UserData.ENCODING_UNICODE_16:
+ spn = new String(spnData, 0, numBytes, "utf-16");
+ break;
+ default:
+ log("SPN encoding not supported");
+ }
+ } catch(Exception e) {
+ log("spn decode error: " + e);
+ }
+ if (DBG) log("spn=" + spn);
+ if (DBG) log("spnCondition=" + csimSpnDisplayCondition);
+ phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
+ }
+
+ private void onGetCSimMdnDone(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data));
+ int mdnDigitsNum = 0x0F & data[0];
+ mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum);
+ if (DBG) log("CSIM MDN=" + mMdn);
+ }
+
+ private void onGetCSimImsimDone(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
+ // C.S0065 section 5.2.2 for IMSI_M encoding
+ // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
+ boolean provisioned = ((data[7] & 0x80) == 0x80);
+
+ if (provisioned) {
+ int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
+ int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
+ int digit7 = 0x0F & (data[4] >> 2);
+ if (digit7 > 0x09) digit7 = 0;
+ int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
+ first3digits = adjstMinDigits(first3digits);
+ second3digits = adjstMinDigits(second3digits);
+ last3digits = adjstMinDigits(last3digits);
+
+ StringBuilder builder = new StringBuilder();
+ builder.append(String.format(Locale.US, "%03d", first3digits));
+ builder.append(String.format(Locale.US, "%03d", second3digits));
+ builder.append(String.format(Locale.US, "%d", digit7));
+ builder.append(String.format(Locale.US, "%03d", last3digits));
+ if (DBG) log("min present=" + builder.toString());
+
+ mMin = builder.toString();
+ } else {
+ if (DBG) log("min not present");
+ }
+ }
+
+ private int adjstMinDigits (int digits) {
+ // Per C.S0005 section 2.3.1.
+ digits += 111;
+ digits = (digits % 10 == 0)?(digits - 10):digits;
+ digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
+ digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
+ return digits;
+ }
+
+ private void onGetCSimCdmaHomeDone(AsyncResult ar) {
+ // Per C.S0065 section 5.2.8
+ ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result;
+ if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size());
+ if (dataList.isEmpty()) {
+ return;
+ }
+ StringBuilder sidBuf = new StringBuilder();
+ StringBuilder nidBuf = new StringBuilder();
+
+ for (byte[] data : dataList) {
+ if (data.length == 5) {
+ int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
+ int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);
+ sidBuf.append(sid).append(",");
+ nidBuf.append(nid).append(",");
+ }
+ }
+ // remove trailing ","
+ sidBuf.setLength(sidBuf.length()-1);
+ nidBuf.setLength(nidBuf.length()-1);
+
+ mHomeSystemId = sidBuf.toString();
+ mHomeNetworkId = nidBuf.toString();
+ }
+
+ private void onGetCSimEprlDone(AsyncResult ar) {
+ // C.S0065 section 5.2.57 for EFeprl encoding
+ // C.S0016 section 3.5.5 for PRL format.
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data));
+
+ // Only need the first 4 bytes of record
+ if (data.length > 3) {
+ int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+ mPrlVersion = Integer.toString(prlId);
+ }
+ if (DBG) log("CSIM PRL version=" + mPrlVersion);
+ }
+
+ private void setLocaleFromCsim() {
+ String prefLang = null;
+ // check EFli then EFpl
+ prefLang = findBestLanguage(mEFli);
+
+ if (prefLang == null) {
+ prefLang = findBestLanguage(mEFpl);
+ }
+
+ if (prefLang != null) {
+ // check country code from SIM
+ String imsi = getIMSI();
+ String country = null;
+ if (imsi != null) {
+ country = MccTable.countryCodeForMcc(
+ Integer.parseInt(imsi.substring(0,3)));
+ }
+ log("Setting locale to " + prefLang + "_" + country);
+ phone.setSystemLocale(prefLang, country, false);
+ } else {
+ log ("No suitable CSIM selected locale");
+ }
+ }
+
+ private String findBestLanguage(byte[] languages) {
+ String bestMatch = null;
+ String[] locales = phone.getContext().getAssets().getLocales();
+
+ if ((languages == null) || (locales == null)) return null;
+
+ // Each 2-bytes consists of one language
+ for (int i = 0; (i + 1) < languages.length; i += 2) {
+ try {
+ String lang = new String(languages, i, 2, "ISO-8859-1");
+ for (int j = 0; j < locales.length; j++) {
+ if (locales[j] != null && locales[j].length() >= 2 &&
+ locales[j].substring(0, 2).equals(lang)) {
+ return lang;
+ }
+ }
+ if (bestMatch != null) break;
+ } catch(java.io.UnsupportedEncodingException e) {
+ log ("Failed to parse SIM language records");
+ }
+ }
+ // no match found. return null
+ return null;
+ }
+
+ @Override
+ protected void log(String s) {
+ if (DBG) Log.d(LOG_TAG, "[CSIM] " + s);
+ }
+
+ public String getMdn() {
+ return mMdn;
+ }
+
+ public String getMin() {
+ return mMin;
+ }
+
+ public String getSid() {
+ return mHomeSystemId;
+ }
+
+ public String getNid() {
+ return mHomeNetworkId;
+ }
+
+ public String getPrlVersion() {
+ return mPrlVersion;
+ }
+
+ @Override
+ public boolean isProvisioned() {
+ // Look for MDN and MIN field to determine if the SIM is provisioned.
+ if ((mMdn != null) && (mMin != null)) return true;
+
+ return false;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 6bd2d09..c0bfd23 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -94,7 +94,7 @@
/** {@inheritDoc} */
@Override
- protected int dispatchMessage(SmsMessageBase smsb) {
+ public int dispatchMessage(SmsMessageBase smsb) {
// If sms is null, means there was a parsing error.
if (smsb == null) {
@@ -485,19 +485,19 @@
/** {@inheritDoc} */
@Override
- protected void activateCellBroadcastSms(int activate, Message response) {
+ public void activateCellBroadcastSms(int activate, Message response) {
mCm.setCdmaBroadcastActivation((activate == 0), response);
}
/** {@inheritDoc} */
@Override
- protected void getCellBroadcastSmsConfig(Message response) {
+ public void getCellBroadcastSmsConfig(Message response) {
mCm.getCdmaBroadcastConfig(response);
}
/** {@inheritDoc} */
@Override
- protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+ public 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 0debb42..e41985e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,8 +16,6 @@
package com.android.internal.telephony.cdma;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
-
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataConnectionTracker;
@@ -61,7 +59,7 @@
/**
* {@hide}
*/
-final class CdmaServiceStateTracker extends ServiceStateTracker {
+public class CdmaServiceStateTracker extends ServiceStateTracker {
static final String LOG_TAG = "CDMA";
CDMAPhone phone;
@@ -86,10 +84,10 @@
NITZ_UPDATE_DIFF_DEFAULT);
/**
- * Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
+ * Values correspond to ServiceState.RADIO_TECHNOLOGY_ definitions.
*/
- private int networkType = 0;
- private int newNetworkType = 0;
+ protected int networkType = 0;
+ protected int newNetworkType = 0;
private boolean mCdmaRoaming = false;
private int mRoamingIndicator;
@@ -99,23 +97,21 @@
/**
* Initially assume no data connection.
*/
- private int cdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
- private int newCdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
- private int mRegistrationState = -1;
- private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
- private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
- private RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
+ protected int mDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+ protected int mNewDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+ protected int mRegistrationState = -1;
+ protected RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
/**
* Sometimes we get the NITZ time before we know what country we
* are in. Keep the time zone information from the NITZ string so
* we can fix the time zone once know the country.
*/
- private boolean mNeedFixZone = false;
+ protected boolean mNeedFixZone = false;
private int mZoneOffset;
private boolean mZoneDst;
private long mZoneTime;
- private boolean mGotCountryCode = false;
+ protected boolean mGotCountryCode = false;
String mSavedTimeZone;
long mSavedTime;
long mSavedAtTime;
@@ -133,17 +129,15 @@
/** Contains the name of the registered network in CDMA (either ONS or ERI text). */
private String curPlmn = null;
- private String mMdn;
- private int mHomeSystemId[] = null;
- private int mHomeNetworkId[] = null;
- private String mMin;
- private String mPrlVersion;
- private boolean mIsMinInfoReady = false;
+ protected String mMdn;
+ protected int mHomeSystemId[] = null;
+ protected int mHomeNetworkId[] = null;
+ protected String mMin;
+ protected String mPrlVersion;
+ protected boolean mIsMinInfoReady = false;
private boolean isEriTextLoaded = false;
- private boolean isSubscriptionFromRuim = false;
-
- private boolean mPendingRadioPowerOffAfterDataOff = false;
+ protected boolean isSubscriptionFromRuim = false;
/* Used only for debugging purposes. */
private String mRegistrationDeniedReason;
@@ -154,7 +148,7 @@
private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- Log.i("CdmaServiceStateTracker", "Auto time state changed");
+ if (DBG) log("Auto time state changed");
revertToNitzTime();
}
};
@@ -162,7 +156,7 @@
private ContentObserver mAutoTimeZoneObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- Log.i("CdmaServiceStateTracker", "Auto time zone state changed");
+ if (DBG) log("Auto time zone state changed");
revertToNitzTimeZone();
}
};
@@ -220,11 +214,11 @@
cm.unregisterForNVReady(this);
cm.unregisterForCdmaOtaProvision(this);
phone.unregisterForEriFileLoaded(this);
- phone.mRuimRecords.unregisterForRecordsLoaded(this);
+ phone.mIccRecords.unregisterForRecordsLoaded(this);
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnNITZTime(this);
- cr.unregisterContentObserver(this.mAutoTimeObserver);
- cr.unregisterContentObserver(this.mAutoTimeZoneObserver);
+ cr.unregisterContentObserver(mAutoTimeObserver);
+ cr.unregisterContentObserver(mAutoTimeZoneObserver);
}
@Override
@@ -232,57 +226,6 @@
if (DBG) log("CdmaServiceStateTracker finalized");
}
- void registerForNetworkAttach(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- networkAttachedRegistrants.add(r);
-
- if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForNetworkAttach(Handler h) {
- networkAttachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into Data attached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- cdmaDataConnectionAttachedRegistrants.add(r);
-
- if (cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForCdmaDataConnectionAttached(Handler h) {
- cdmaDataConnectionAttachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into Data detached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- cdmaDataConnectionDetachedRegistrants.add(r);
-
- if (cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForCdmaDataConnectionDetached(Handler h) {
- cdmaDataConnectionDetachedRegistrants.remove(h);
- }
-
/**
* Registration point for subscription info ready
* @param h handler to notify
@@ -310,6 +253,7 @@
switch (msg.what) {
case EVENT_RADIO_AVAILABLE:
+ if (DBG) log("handleMessage: EVENT_RADIO_AVAILABLE");
break;
case EVENT_RUIM_READY:
@@ -317,13 +261,13 @@
// unlocked. At this stage, the radio is already powered on.
isSubscriptionFromRuim = true;
if (mNeedToRegForRuimLoaded) {
- phone.mRuimRecords.registerForRecordsLoaded(this,
+ phone.mIccRecords.registerForRecordsLoaded(this,
EVENT_RUIM_RECORDS_LOADED, null);
mNeedToRegForRuimLoaded = false;
}
cm.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
- if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription.");
+ if (DBG) log("handleMessage: EVENT_RUIM_READY, Send Request getCDMASubscription.");
// Restore the previous network selection.
pollState();
@@ -337,6 +281,7 @@
// For Non-RUIM phones, the subscription information is stored in
// Non Volatile. Here when Non-Volatile is ready, we can poll the CDMA
// subscription info.
+ if (DBG) log("handleMessage: EVENT_NV_READY, Send Request getCDMASubscription.");
cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
pollState();
// Signal strength polling stops when radio is off.
@@ -401,7 +346,7 @@
networkId = Integer.parseInt(states[9]);
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing cell location data: " + ex);
+ loge("error parsing cell location data: " + ex);
}
}
@@ -428,56 +373,22 @@
String cdmaSubscription[] = (String[])ar.result;
if (cdmaSubscription != null && cdmaSubscription.length >= 5) {
mMdn = cdmaSubscription[0];
- if (cdmaSubscription[1] != null) {
- String[] sid = cdmaSubscription[1].split(",");
- mHomeSystemId = new int[sid.length];
- for (int i = 0; i < sid.length; i++) {
- try {
- mHomeSystemId[i] = Integer.parseInt(sid[i]);
- } catch (NumberFormatException ex) {
- Log.e(LOG_TAG, "error parsing system id: ", ex);
- }
- }
- }
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION SID=" + cdmaSubscription[1] );
+ parseSidNid(cdmaSubscription[1], cdmaSubscription[2]);
- if (cdmaSubscription[2] != null) {
- String[] nid = cdmaSubscription[2].split(",");
- mHomeNetworkId = new int[nid.length];
- for (int i = 0; i < nid.length; i++) {
- try {
- mHomeNetworkId[i] = Integer.parseInt(nid[i]);
- } catch (NumberFormatException ex) {
- Log.e(LOG_TAG, "error parsing network id: ", ex);
- }
- }
- }
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION NID=" + cdmaSubscription[2] );
mMin = cdmaSubscription[3];
mPrlVersion = cdmaSubscription[4];
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION MDN=" + mMdn);
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: MDN=" + mMdn);
mIsMinInfoReady = true;
- int otaspMode = getOtasp();
- int oldOtaspMode = mCurrentOtaspMode;
- mCurrentOtaspMode = otaspMode;
-
- // Notify apps subscription info is ready
- if (cdmaForSubscriptionInfoReadyRegistrants != null) {
- Log.d(LOG_TAG, "call cdmaForSubscriptionInfoReady.notifyRegistrants()");
- cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
- }
- if (oldOtaspMode != mCurrentOtaspMode) {
- Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" +
- oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
- phone.notifyOtaspChanged(mCurrentOtaspMode);
- }
+ updateOtaspState();
phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI,
null);
} else {
- Log.w(LOG_TAG,"error parsing cdmaSubscription params num="
+ if (DBG) {
+ log("GET_CDMA_SUBSCRIPTION: error parsing cdmaSubscription params num="
+ cdmaSubscription.length);
+ }
}
}
break;
@@ -532,26 +443,16 @@
if (ar.exception == null) {
ints = (int[]) ar.result;
int otaStatus = ints[0];
- if (otaStatus == phone.CDMA_OTA_PROVISION_STATUS_COMMITTED
- || otaStatus == phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
- Log.d(LOG_TAG, "Received OTA_PROGRAMMING Complete,Reload MDN ");
+ if (otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED
+ || otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
+ if (DBG) log("EVENT_OTA_PROVISION_STATUS_CHANGE: Complete, Reload MDN");
cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
}
}
break;
- case EVENT_SET_RADIO_POWER_OFF:
- synchronized(this) {
- if (mPendingRadioPowerOffAfterDataOff) {
- if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
- hangupAndPowerOff();
- mPendingRadioPowerOffAfterDataOff = false;
- }
- }
- break;
-
default:
- Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+ super.handleMessage(msg);
break;
}
}
@@ -565,51 +466,14 @@
&& cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
cm.setRadioPower(true, null);
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
- DataConnectionTracker dcTracker = phone.mDataConnection;
- if (! dcTracker.isDataConnectionAsDesired()) {
- EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
- dcTracker.getStateInString(),
- dcTracker.getAnyDataEnabled() ? 1 : 0);
- }
+ DataConnectionTracker dcTracker = phone.mDataConnectionTracker;
// If it's on and available and we want it off gracefully
- powerOffRadioSafely();
+ powerOffRadioSafely(dcTracker);
} // Otherwise, we're in the desired state
}
@Override
- protected void powerOffRadioSafely() {
- DataConnectionTracker dcTracker = phone.mDataConnection;
-
- Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
- msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
-
- synchronized (this) {
- 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 {
- Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away.");
- hangupAndPowerOff();
- }
- }
- }
- }
- }
-
- @Override
protected void updateSpnDisplay() {
// 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:
@@ -626,9 +490,10 @@
// null and not blank. But this would cause us to incorrectly display
// "No Service". Now showPlmn is set to true for any non null string.
boolean showPlmn = plmn != null;
- Log.d(LOG_TAG,
- String.format("updateSpnDisplay: changed sending intent" +
+ if (DBG) {
+ log(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, false);
@@ -647,14 +512,164 @@
}
/**
- * Handle the result of one of the pollState()-related requests
- */
+ * Determine data network type based on radio technology.
+ */
+ protected void setCdmaTechnology(int radioTechnology){
+ mNewDataConnectionState = radioTechnologyToDataServiceState(radioTechnology);
+ newSS.setRadioTechnology(radioTechnology);
+ newNetworkType = radioTechnology;
+ }
- @Override
- protected void handlePollStateResult (int what, AsyncResult ar) {
+ /**
+ * Hanlde the PollStateResult message
+ */
+ protected void handlePollStateResultMessage(int what, AsyncResult ar){
int ints[];
String states[];
+ switch (what) {
+ case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
+ states = (String[])ar.result;
+ int registrationState = 4; //[0] registrationState
+ int radioTechnology = -1; //[3] radioTechnology
+ int baseStationId = -1; //[4] baseStationId
+ //[5] baseStationLatitude
+ int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ //[6] baseStationLongitude
+ int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+ int cssIndicator = 0; //[7] init with 0, because it is treated as a boolean
+ int systemId = 0; //[8] systemId
+ int networkId = 0; //[9] networkId
+ int roamingIndicator = -1; //[10] Roaming indicator
+ int systemIsInPrl = 0; //[11] Indicates if current system is in PRL
+ int defaultRoamingIndicator = 0; //[12] Is default roaming indicator from PRL
+ int reasonForDenial = 0; //[13] Denial reason if registrationState = 3
+
+ if (states.length == 14) {
+ try {
+ if (states[0] != null) {
+ registrationState = Integer.parseInt(states[0]);
+ }
+ if (states[3] != null) {
+ radioTechnology = Integer.parseInt(states[3]);
+ }
+ if (states[4] != null) {
+ baseStationId = Integer.parseInt(states[4]);
+ }
+ if (states[5] != null) {
+ baseStationLatitude = Integer.parseInt(states[5]);
+ }
+ if (states[6] != null) {
+ baseStationLongitude = Integer.parseInt(states[6]);
+ }
+ // Some carriers only return lat-lngs of 0,0
+ if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+ baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+ }
+ if (states[7] != null) {
+ cssIndicator = Integer.parseInt(states[7]);
+ }
+ if (states[8] != null) {
+ systemId = Integer.parseInt(states[8]);
+ }
+ if (states[9] != null) {
+ networkId = Integer.parseInt(states[9]);
+ }
+ if (states[10] != null) {
+ roamingIndicator = Integer.parseInt(states[10]);
+ }
+ if (states[11] != null) {
+ systemIsInPrl = Integer.parseInt(states[11]);
+ }
+ if (states[12] != null) {
+ defaultRoamingIndicator = Integer.parseInt(states[12]);
+ }
+ if (states[13] != null) {
+ reasonForDenial = Integer.parseInt(states[13]);
+ }
+ } catch (NumberFormatException ex) {
+ loge("EVENT_POLL_STATE_REGISTRATION_CDMA: error parsing: " + ex);
+ }
+ } else {
+ throw new RuntimeException("Warning! Wrong number of parameters returned from "
+ + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
+ + states.length);
+ }
+
+ mRegistrationState = registrationState;
+ // When registration state is roaming and TSB58
+ // roaming indicator is not in the carrier-specified
+ // list of ERIs for home system, mCdmaRoaming is true.
+ mCdmaRoaming =
+ regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
+ newSS.setState (regCodeToServiceState(registrationState));
+
+ setCdmaTechnology(radioTechnology);
+
+ newSS.setCssIndicator(cssIndicator);
+ newSS.setSystemAndNetworkId(systemId, networkId);
+ mRoamingIndicator = roamingIndicator;
+ mIsInPrl = (systemIsInPrl == 0) ? false : true;
+ mDefaultRoamingIndicator = defaultRoamingIndicator;
+
+
+ // Values are -1 if not available.
+ newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
+ baseStationLongitude, systemId, networkId);
+
+ if (reasonForDenial == 0) {
+ mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
+ } else if (reasonForDenial == 1) {
+ mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
+ } else {
+ mRegistrationDeniedReason = "";
+ }
+
+ if (mRegistrationState == 3) {
+ if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
+ }
+ break;
+
+ case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
+ String opNames[] = (String[])ar.result;
+
+ if (opNames != null && opNames.length >= 3) {
+ // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
+ if ((opNames[2] == null) || (opNames[2].length() < 5)
+ || ("00000".equals(opNames[2]))) {
+ opNames[2] = SystemProperties.get(
+ CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
+ if (DBG) {
+ log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
+ " is bad. Using SystemProperties '" +
+ CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
+ "'= " + opNames[2]);
+ }
+ }
+ if (cm.getNvState().isNVReady()) {
+ // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
+ // ERI text, so here it is ignored what is coming from the modem.
+ newSS.setOperatorName(null, opNames[1], opNames[2]);
+ } else {
+ newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+ }
+ } else {
+ if (DBG) log("EVENT_POLL_STATE_OPERATOR_CDMA: error parsing opNames");
+ }
+ break;
+ default:
+ loge("handlePollStateResultMessage: RIL response handle in wrong phone!"
+ + " Expected CDMA RIL request and get GSM RIL request.");
+ break;
+ }
+ }
+
+ /**
+ * Handle the result of one of the pollState() - related requests
+ */
+ @Override
+ protected void handlePollStateResult(int what, AsyncResult ar) {
// Ignore stale requests from last poll.
if (ar.userObj != pollingContext) return;
@@ -677,158 +692,15 @@
return;
}
- if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
- err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
- Log.e(LOG_TAG,
- "RIL implementation has returned an error where it must succeed",
- ar.exception);
+ if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
+ loge("handlePollStateResult: RIL returned an error where it must succeed"
+ + ar.exception);
}
} else try {
- switch (what) {
- case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
- states = (String[])ar.result;
-
- int registrationState = 4; //[0] registrationState
- int radioTechnology = -1; //[3] radioTechnology
- int baseStationId = -1; //[4] baseStationId
- //[5] baseStationLatitude
- int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
- //[6] baseStationLongitude
- int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
- int cssIndicator = 0; //[7] init with 0, because it is treated as a boolean
- int systemId = 0; //[8] systemId
- int networkId = 0; //[9] networkId
- int roamingIndicator = -1; //[10] Roaming indicator
- int systemIsInPrl = 0; //[11] Indicates if current system is in PRL
- int defaultRoamingIndicator = 0; //[12] Is default roaming indicator from PRL
- int reasonForDenial = 0; //[13] Denial reason if registrationState = 3
-
- if (states.length == 14) {
- try {
- if (states[0] != null) {
- registrationState = Integer.parseInt(states[0]);
- }
- if (states[3] != null) {
- radioTechnology = Integer.parseInt(states[3]);
- }
- if (states[4] != null) {
- baseStationId = Integer.parseInt(states[4]);
- }
- if (states[5] != null) {
- baseStationLatitude = Integer.parseInt(states[5]);
- }
- if (states[6] != null) {
- baseStationLongitude = Integer.parseInt(states[6]);
- }
- // Some carriers only return lat-lngs of 0,0
- if (baseStationLatitude == 0 && baseStationLongitude == 0) {
- baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
- baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
- }
- if (states[7] != null) {
- cssIndicator = Integer.parseInt(states[7]);
- }
- if (states[8] != null) {
- systemId = Integer.parseInt(states[8]);
- }
- if (states[9] != null) {
- networkId = Integer.parseInt(states[9]);
- }
- if (states[10] != null) {
- roamingIndicator = Integer.parseInt(states[10]);
- }
- if (states[11] != null) {
- systemIsInPrl = Integer.parseInt(states[11]);
- }
- if (states[12] != null) {
- defaultRoamingIndicator = Integer.parseInt(states[12]);
- }
- if (states[13] != null) {
- reasonForDenial = Integer.parseInt(states[13]);
- }
- } catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
- }
- } else {
- throw new RuntimeException("Warning! Wrong number of parameters returned from "
- + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
- + states.length);
- }
-
- mRegistrationState = registrationState;
- // When registration state is roaming and TSB58
- // roaming indicator is not in the carrier-specified
- // list of ERIs for home system, mCdmaRoaming is true.
- mCdmaRoaming =
- regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
- newSS.setState (regCodeToServiceState(registrationState));
-
- this.newCdmaDataConnectionState =
- radioTechnologyToDataServiceState(radioTechnology);
- newSS.setRadioTechnology(radioTechnology);
- newNetworkType = radioTechnology;
-
- newSS.setCssIndicator(cssIndicator);
- newSS.setSystemAndNetworkId(systemId, networkId);
- mRoamingIndicator = roamingIndicator;
- mIsInPrl = (systemIsInPrl == 0) ? false : true;
- mDefaultRoamingIndicator = defaultRoamingIndicator;
-
-
- // Values are -1 if not available.
- newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
- baseStationLongitude, systemId, networkId);
-
- if (reasonForDenial == 0) {
- mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
- } else if (reasonForDenial == 1) {
- mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
- } else {
- mRegistrationDeniedReason = "";
- }
-
- if (mRegistrationState == 3) {
- if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
- }
- break;
-
- case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
- String opNames[] = (String[])ar.result;
-
- if (opNames != null && opNames.length >= 3) {
- // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
- if ((opNames[2] == null) || (opNames[2].length() < 5)
- || ("00000".equals(opNames[2]))) {
- opNames[2] = SystemProperties.get(
- CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
- if (DBG) {
- log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
- " is bad. Using SystemProperties '" +
- CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
- "'= " + opNames[2]);
- }
- }
- if (cm.getRadioState().isNVReady()) {
- // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
- // ERI text, so here it is ignored what is coming from the modem.
- newSS.setOperatorName(null, opNames[1], opNames[2]);
- } else {
- newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
- }
- } else {
- Log.w(LOG_TAG, "error parsing opNames");
- }
- break;
-
- default:
- Log.e(LOG_TAG, "RIL response handle in wrong phone!"
- + " Expected CDMA RIL request and get GSM RIL request.");
- break;
- }
-
+ handlePollStateResultMessage(what, ar);
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "Exception while polling service state. "
- + "Probably malformed RIL response.", ex);
+ loge("handlePollStateResult: Exception while polling service state. "
+ + "Probably malformed RIL response." + ex);
}
pollingContext[0]--;
@@ -896,9 +768,8 @@
}
- private void setSignalStrengthDefaultValues() {
- mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, false);
+ protected void setSignalStrengthDefaultValues() {
+ mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, false);
}
/**
@@ -909,7 +780,7 @@
* and start over again if the radio notifies us that some
* event has changed
*/
- private void
+ protected void
pollState() {
pollingContext = new int[1];
pollingContext[0] = 0;
@@ -936,7 +807,7 @@
case SIM_NOT_READY:
case SIM_LOCKED_OR_ABSENT:
case SIM_READY:
- log("Radio Technology Change ongoing, setting SS to off");
+ if (DBG) log("Radio Technology Change ongoing, setting SS to off");
newSS.setStateOff();
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
@@ -964,37 +835,7 @@
}
}
- private static String networkTypeToString(int type) {
- String ret = "unknown";
-
- switch (type) {
- case DATA_ACCESS_CDMA_IS95A:
- case DATA_ACCESS_CDMA_IS95B:
- ret = "CDMA";
- break;
- case DATA_ACCESS_CDMA_1xRTT:
- ret = "CDMA - 1xRTT";
- break;
- case DATA_ACCESS_CDMA_EvDo_0:
- ret = "CDMA - EvDo rev. 0";
- break;
- case DATA_ACCESS_CDMA_EvDo_A:
- ret = "CDMA - EvDo rev. A";
- break;
- case DATA_ACCESS_CDMA_EvDo_B:
- ret = "CDMA - EvDo rev. B";
- break;
- default:
- if (DBG) {
- Log.e(LOG_TAG, "Wrong network. Can not return a string.");
- }
- break;
- }
-
- return ret;
- }
-
- private void fixTimeZone(String isoCountryCode) {
+ protected void fixTimeZone(String isoCountryCode) {
TimeZone zone = null;
// If the offset is (0, false) and the time zone property
// is set, use the time zone property rather than GMT.
@@ -1031,8 +872,8 @@
}
}
- private void pollStateDone() {
- if (DBG) log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]");
+ protected void pollStateDone() {
+ if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
boolean hasRegistered =
ss.getState() != ServiceState.STATE_IN_SERVICE
@@ -1043,15 +884,15 @@
&& newSS.getState() != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionAttached =
- this.cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState == ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState != ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionDetached =
- this.cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState != ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState == ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionChanged =
- cdmaDataConnectionState != newCdmaDataConnectionState;
+ mDataConnectionState != mNewDataConnectionState;
boolean hasNetworkTypeChanged = networkType != newNetworkType;
@@ -1065,10 +906,10 @@
// Add an event log when connection state changes
if (ss.getState() != newSS.getState() ||
- cdmaDataConnectionState != newCdmaDataConnectionState) {
+ mDataConnectionState != mNewDataConnectionState) {
EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE,
- ss.getState(), cdmaDataConnectionState,
- newSS.getState(), newCdmaDataConnectionState);
+ ss.getState(), mDataConnectionState,
+ newSS.getState(), mNewDataConnectionState);
}
ServiceState tss;
@@ -1082,7 +923,7 @@
cellLoc = newCellLoc;
newCellLoc = tcl;
- cdmaDataConnectionState = newCdmaDataConnectionState;
+ mDataConnectionState = mNewDataConnectionState;
networkType = newNetworkType;
// this new state has been applied - forget it until we get a new new state
newNetworkType = 0;
@@ -1091,11 +932,11 @@
if (hasNetworkTypeChanged) {
phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
- networkTypeToString(networkType));
+ ServiceState.radioTechnologyToString(networkType));
}
if (hasRegistered) {
- networkAttachedRegistrants.notifyRegistrants();
+ mNetworkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
@@ -1110,7 +951,7 @@
eriText = phone.getContext().getText(
com.android.internal.R.string.roamingTextSearching).toString();
}
- ss.setCdmaEriText(eriText);
+ ss.setOperatorAlphaLong(eriText);
}
String operatorNumeric;
@@ -1129,9 +970,9 @@
isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(
operatorNumeric.substring(0,3)));
} catch ( NumberFormatException ex){
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("pollStateDone: countryCodeForMcc error" + ex);
} catch ( StringIndexOutOfBoundsException ex) {
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("pollStateDone: countryCodeForMcc error" + ex);
}
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
@@ -1150,11 +991,11 @@
}
if (hasCdmaDataConnectionAttached) {
- cdmaDataConnectionAttachedRegistrants.notifyRegistrants();
+ mAttachedRegistrants.notifyRegistrants();
}
if (hasCdmaDataConnectionDetached) {
- cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
+ mDetachedRegistrants.notifyRegistrants();
}
if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
@@ -1162,11 +1003,11 @@
}
if (hasRoamingOn) {
- roamingOnRegistrants.notifyRegistrants();
+ mRoamingOnRegistrants.notifyRegistrants();
}
if (hasRoamingOff) {
- roamingOffRegistrants.notifyRegistrants();
+ mRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
@@ -1213,7 +1054,7 @@
* This code should probably be hoisted to the base class so
* the fix, when added, works for both.
*/
- private void
+ protected void
queueNextSignalStrengthPoll() {
if (dontPollSignalStrength || (cm.getRadioState().isGsm())) {
// The radio is telling us about signal strength changes
@@ -1234,7 +1075,7 @@
* send signal-strength-changed notification if changed
* Called both for solicited and unsolicited signal strength updates
*/
- private void
+ protected void
onSignalStrengthResult(AsyncResult ar) {
SignalStrength oldSignalStrength = mSignalStrength;
@@ -1253,19 +1094,19 @@
//log(String.format("onSignalStrengthResult cdmaDbm=%d cdmaEcio=%d evdoRssi=%d evdoEcio=%d evdoSnr=%d",
// cdmaDbm, cdmaEcio, evdoRssi, evdoEcio, evdoSnr));
mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio,
- evdoRssi, evdoEcio, evdoSnr, -1, -1, -1, -1, -1, false);
+ evdoRssi, evdoEcio, evdoSnr, false);
}
try {
phone.notifySignalStrength();
} catch (NullPointerException ex) {
- log("onSignalStrengthResult() Phone already destroyed: " + ex
+ loge("onSignalStrengthResult() Phone already destroyed: " + ex
+ "SignalStrength not notified");
}
}
- private int radioTechnologyToDataServiceState(int code) {
+ protected int radioTechnologyToDataServiceState(int code) {
int retVal = ServiceState.STATE_OUT_OF_SERVICE;
switch(code) {
case 0:
@@ -1279,17 +1120,18 @@
case 7: // RADIO_TECHNOLOGY_EVDO_0
case 8: // RADIO_TECHNOLOGY_EVDO_A
case 12: // RADIO_TECHNOLOGY_EVDO_B
+ case 13: // RADIO_TECHNOLOGY_EHRPD
retVal = ServiceState.STATE_IN_SERVICE;
break;
default:
- Log.e(LOG_TAG, "Wrong radioTechnology code.");
+ loge("radioTechnologyToDataServiceState: Wrong radioTechnology code.");
break;
}
return(retVal);
}
/** code is registration state 0-5 from TS 27.007 7.2 */
- private int
+ protected int
regCodeToServiceState(int code) {
switch (code) {
case 0: // Not searching and not registered
@@ -1304,18 +1146,13 @@
return ServiceState.STATE_IN_SERVICE;
default:
- Log.w(LOG_TAG, "unexpected service state " + code);
+ loge("regCodeToServiceState: unexpected service state " + code);
return ServiceState.STATE_OUT_OF_SERVICE;
}
}
- /**
- * @return The current CDMA data connection state. ServiceState.RADIO_TECHNOLOGY_1xRTT or
- * ServiceState.RADIO_TECHNOLOGY_EVDO is the same as "attached" and
- * ServiceState.RADIO_TECHNOLOGY_UNKNOWN is the same as detached.
- */
- /*package*/ int getCurrentCdmaDataConnectionState() {
- return cdmaDataConnectionState;
+ public int getCurrentDataConnectionState() {
+ return mDataConnectionState;
}
/**
@@ -1388,8 +1225,10 @@
// tz is in number of quarter-hours
long start = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime +
+ if (DBG) {
+ log("NITZ: " + nitz + "," + nitzReceiveTime +
" start=" + start + " delay=" + (start - nitzReceiveTime));
+ }
try {
/* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
@@ -1486,7 +1325,7 @@
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
- Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
+ if (DBG) log("NITZ: Not setting clock because gsm.ignore-nitz is set");
return;
}
@@ -1501,17 +1340,21 @@
if (millisSinceNitzReceived < 0) {
// Sanity check: something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ if (DBG) {
+ log("NITZ: not setting time, clock has rolled "
+ "backwards since NITZ time was received, "
+ nitz);
+ }
return;
}
if (millisSinceNitzReceived > Integer.MAX_VALUE) {
// If the time is this far off, something is wrong > 24 days!
- Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ if (DBG) {
+ log("NITZ: not setting time, processing has taken "
+ (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ " days");
+ }
return;
}
@@ -1531,14 +1374,18 @@
if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)
|| (Math.abs(gained) > nitzUpdateDiff)) {
- Log.i(LOG_TAG, "NITZ: Auto updating time of day to " + c.getTime()
+ if (DBG) {
+ log("NITZ: Auto updating time of day to " + c.getTime()
+ " NITZ receive delay=" + millisSinceNitzReceived
+ "ms gained=" + gained + "ms from " + nitz);
+ }
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
} else {
- Log.i(LOG_TAG, "NITZ: ignore, a previous update was "
+ if (DBG) {
+ log("NITZ: ignore, a previous update was "
+ timeSinceLastUpdate + "ms ago and gained=" + gained + "ms");
+ }
return;
}
}
@@ -1546,17 +1393,17 @@
/**
* Update properties and save the time we did the update
*/
- Log.i(LOG_TAG, "NITZ: update nitz time property");
+ if (DBG) log("NITZ: update nitz time property");
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
mSavedTime = c.getTimeInMillis();
mSavedAtTime = SystemClock.elapsedRealtime();
} finally {
long end = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ if (DBG) log("NITZ: end=" + end + " dur=" + (end - start));
mWakeLock.release();
}
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
+ loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
}
}
@@ -1614,8 +1461,9 @@
if (Settings.System.getInt(cr, Settings.System.AUTO_TIME, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedTime
- + " mSavedAtTime=" + mSavedAtTime);
+ if (DBG) {
+ log("revertToNitzTime: mSavedTime=" + mSavedTime + " mSavedAtTime=" + mSavedAtTime);
+ }
if (mSavedTime != 0 && mSavedAtTime != 0) {
setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
@@ -1627,13 +1475,13 @@
Settings.System.AUTO_TIME_ZONE, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
+ if (DBG) log("revertToNitzTimeZone: tz='" + mSavedTimeZone);
if (mSavedTimeZone != null) {
setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
}
}
- private boolean isSidsAllZeros() {
+ protected boolean isSidsAllZeros() {
if (mHomeSystemId != null) {
for (int i=0; i < mHomeSystemId.length; i++) {
if (mHomeSystemId[i] != 0) {
@@ -1662,7 +1510,7 @@
* @return true if phone is camping on a technology
* that could support voice and data simultaneously.
*/
- boolean isConcurrentVoiceAndData() {
+ public boolean isConcurrentVoiceAndDataAllowed() {
// Note: it needs to be confirmed which CDMA network types
// can support voice and data calls concurrently.
// For the time-being, the return value will be false.
@@ -1707,30 +1555,12 @@
}
/**
- * process the pending request to turn radio off after data is disconnected
- *
- * return true if there is pending request to process; false otherwise.
- */
- public boolean processPendingRadioPowerOffAfterDataOff() {
- synchronized(this) {
- if (mPendingRadioPowerOffAfterDataOff) {
- if (DBG) log("Process pending request to turn radio off.");
- removeMessages(EVENT_SET_RADIO_POWER_OFF);
- hangupAndPowerOff();
- mPendingRadioPowerOffAfterDataOff = false;
- return true;
- }
- return false;
- }
- }
-
- /**
* 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 + "'");
+ if (DBG) log("getOtasp: bad mMin='" + mMin + "'");
provisioningState = OTASP_UNKNOWN;
} else {
if ((mMin.equals(UNACTIVATED_MIN_VALUE)
@@ -1741,20 +1571,73 @@
provisioningState = OTASP_NOT_NEEDED;
}
}
- if (DBG) Log.d(LOG_TAG, "getOtasp: state=" + provisioningState);
+ if (DBG) log("getOtasp: state=" + provisioningState);
return provisioningState;
}
@Override
- protected void log(String s) {
- Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
- }
-
- private void hangupAndPowerOff() {
+ protected void hangupAndPowerOff() {
// hang up all active voice calls
phone.mCT.ringingCall.hangupIfAlive();
phone.mCT.backgroundCall.hangupIfAlive();
phone.mCT.foregroundCall.hangupIfAlive();
cm.setRadioPower(false, null);
}
+
+ protected void parseSidNid (String sidStr, String nidStr) {
+ if (sidStr != null) {
+ String[] sid = sidStr.split(",");
+ mHomeSystemId = new int[sid.length];
+ for (int i = 0; i < sid.length; i++) {
+ try {
+ mHomeSystemId[i] = Integer.parseInt(sid[i]);
+ } catch (NumberFormatException ex) {
+ loge("error parsing system id: " + ex);
+ }
+ }
+ }
+ if (DBG) log("CDMA_SUBSCRIPTION: SID=" + sidStr);
+
+ if (nidStr != null) {
+ String[] nid = nidStr.split(",");
+ mHomeNetworkId = new int[nid.length];
+ for (int i = 0; i < nid.length; i++) {
+ try {
+ mHomeNetworkId[i] = Integer.parseInt(nid[i]);
+ } catch (NumberFormatException ex) {
+ loge("CDMA_SUBSCRIPTION: error parsing network id: " + ex);
+ }
+ }
+ }
+ if (DBG) log("CDMA_SUBSCRIPTION: NID=" + nidStr);
+ }
+
+ protected void updateOtaspState() {
+ int otaspMode = getOtasp();
+ int oldOtaspMode = mCurrentOtaspMode;
+ mCurrentOtaspMode = otaspMode;
+
+ // Notify apps subscription info is ready
+ if (cdmaForSubscriptionInfoReadyRegistrants != null) {
+ if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()");
+ cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
+ }
+ if (oldOtaspMode != mCurrentOtaspMode) {
+ if (DBG) {
+ log("CDMA_SUBSCRIPTION: call notifyOtaspChanged old otaspMode=" +
+ oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
+ }
+ phone.notifyOtaspChanged(mCurrentOtaspMode);
+ }
+ }
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[CdmaSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaSST] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimCard.java b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
index 734badd..11f44d4 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
@@ -25,8 +25,8 @@
*/
public final class RuimCard extends IccCard {
- RuimCard(CDMAPhone phone) {
- super(phone, "CDMA", true);
+ RuimCard(CDMAPhone phone, String LOG_TAG, boolean dbg) {
+ super(phone, LOG_TAG, dbg);
mPhone.mCM.registerForRUIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mPhone.mCM.registerForRUIMReady(mHandler, EVENT_ICC_READY, null);
@@ -35,6 +35,7 @@
@Override
public void dispose() {
+ super.dispose();
//Unregister for all events
mPhone.mCM.unregisterForRUIMLockedOrAbsent(mHandler);
mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
@@ -43,7 +44,7 @@
@Override
public String getServiceProviderName () {
- return ((CDMAPhone)mPhone).mRuimRecords.getServiceProviderName();
+ return mPhone.mIccRecords.getServiceProviderName();
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
index 6e12f24a..ce33066 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
@@ -32,7 +32,7 @@
public RuimPhoneBookInterfaceManager(CDMAPhone phone) {
super(phone);
- adnCache = phone.mRuimRecords.getAdnCache();
+ adnCache = phone.mIccRecords.getAdnCache();
//NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index 87b0c60..719eff3 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -87,18 +87,19 @@
p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
// NOTE the EVENT_SMS_ON_RUIM is not registered
- p.mCM.setOnIccRefresh(this, EVENT_RUIM_REFRESH, null);
+ p.mCM.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
// Start off by setting empty state
onRadioOffOrNotAvailable();
}
+ @Override
public void dispose() {
//Unregister for all events
phone.mCM.unregisterForRUIMReady(this);
phone.mCM.unregisterForOffOrNotAvailable( this);
- phone.mCM.unSetOnIccRefresh(this);
+ phone.mCM.unregisterForIccRefresh(this);
}
@Override
@@ -293,7 +294,7 @@
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- ((CDMAPhone) phone).mRuimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
RuimCard.INTENT_VALUE_ICC_LOADED, null);
}
@@ -302,7 +303,7 @@
READY is sent before IMSI ready
*/
- ((CDMAPhone) phone).mRuimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
RuimCard.INTENT_VALUE_ICC_READY, null);
fetchRuimRecords();
@@ -324,8 +325,13 @@
// Further records that can be inserted are Operator/OEM dependent
}
+ /**
+ * {@inheritDoc}
+ *
+ * No Display rule for RUIMs yet.
+ */
@Override
- protected int getDisplayRule(String plmn) {
+ public int getDisplayRule(String plmn) {
// TODO together with spn
return 0;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
old mode 100644
new mode 100755
index cf06dab..7a45e15
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -34,6 +34,9 @@
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.BitwiseOutputStream;
+import android.content.res.Resources;
+
+
/**
* An object to encode and decode CDMA SMS bearer data.
@@ -582,7 +585,6 @@
uData.payload = new byte[0];
uData.numFields = 0;
} else {
- uData.payload = uData.payload;
uData.numFields = uData.payload.length;
}
} else {
@@ -910,6 +912,16 @@
return true;
}
+ private static String decodeUtf8(byte[] data, int offset, int numFields)
+ throws CodingException
+ {
+ try {
+ return new String(data, offset, numFields, "UTF-8");
+ } catch (java.io.UnsupportedEncodingException ex) {
+ throw new CodingException("UTF-8 decode failed: " + ex);
+ }
+ }
+
private static String decodeUtf16(byte[] data, int offset, int numFields)
throws CodingException
{
@@ -994,9 +1006,15 @@
}
switch (userData.msgEncoding) {
case UserData.ENCODING_OCTET:
+ /*
+ * Octet decoding depends on the carrier service.
+ */
+ boolean decodingtypeUTF8 = Resources.getSystem()
+ .getBoolean(com.android.internal.R.bool.config_sms_utf8_support);
+
// Strip off any padding bytes, meaning any differences between the length of the
- // array and the target length specified by numFields. This is to avoid any confusion
- // by code elsewhere that only considers the payload array length.
+ // array and the target length specified by numFields. This is to avoid any
+ // confusion by code elsewhere that only considers the payload array length.
byte[] payload = new byte[userData.numFields];
int copyLen = userData.numFields < userData.payload.length
? userData.numFields : userData.payload.length;
@@ -1004,9 +1022,13 @@
System.arraycopy(userData.payload, 0, payload, 0, copyLen);
userData.payload = payload;
- // There are many devices in the market that send 8bit text sms (latin encoded) as
- // octet encoded.
- userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
+ if (!decodingtypeUTF8) {
+ // There are many devices in the market that send 8bit text sms (latin encoded) as
+ // octet encoded.
+ userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
+ } else {
+ userData.payloadStr = decodeUtf8(userData.payload, offset, userData.numFields);
+ }
break;
case UserData.ENCODING_IA5:
case UserData.ENCODING_7BIT_ASCII:
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index c17197e..275c8fe 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -33,6 +33,7 @@
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import com.android.internal.telephony.CallTracker;
import android.text.TextUtils;
import android.util.Log;
@@ -72,6 +73,7 @@
import com.android.internal.telephony.UUSInfo;
import com.android.internal.telephony.test.SimulatedRadioControl;
import com.android.internal.telephony.IccVmNotSupportedException;
+import com.android.internal.telephony.ServiceStateTracker;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -100,9 +102,6 @@
// Instance Variables
GsmCallTracker mCT;
GsmServiceStateTracker mSST;
- GsmSMSDispatcher mSMS;
- SIMRecords mSIMRecords;
- SimCard mSimCard;
CatService mStkService;
ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
@@ -143,24 +142,23 @@
mSST = new GsmServiceStateTracker (this);
mSMS = new GsmSMSDispatcher(this);
mIccFileHandler = new SIMFileHandler(this);
- mSIMRecords = new SIMRecords(this);
- mDataConnection = new GsmDataConnectionTracker (this);
- mSimCard = new SimCard(this);
+ mIccRecords = new SIMRecords(this);
+ mDataConnectionTracker = new GsmDataConnectionTracker (this);
+ mIccCard = new SimCard(this);
if (!unitTestMode) {
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
}
- mStkService = CatService.getInstance(mCM, mSIMRecords, mContext,
- (SIMFileHandler)mIccFileHandler, mSimCard);
+ mStkService = CatService.getInstance(mCM, mIccRecords, mContext, mIccFileHandler, mIccCard);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
- mSIMRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
+ mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(this, EVENT_RADIO_ON, null);
mCM.setOnUSSD(this, EVENT_USSD, null);
mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
- mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
+ mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
if (false) {
try {
@@ -207,10 +205,10 @@
//Unregister from all former registered events
mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
- mSIMRecords.unregisterForRecordsLoaded(this); //EVENT_SIM_RECORDS_LOADED
+ mIccRecords.unregisterForRecordsLoaded(this); //EVENT_SIM_RECORDS_LOADED
mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(this); //EVENT_RADIO_ON
- mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
+ mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnUSSD(this);
mCM.unSetOnSuppServiceNotification(this);
@@ -219,11 +217,11 @@
//Force all referenced classes to unregister their former registered events
mStkService.dispose();
mCT.dispose();
- mDataConnection.dispose();
+ mDataConnectionTracker.dispose();
mSST.dispose();
mIccFileHandler.dispose(); // instance of SimFileHandler
- mSIMRecords.dispose();
- mSimCard.dispose();
+ mIccRecords.dispose();
+ mIccCard.dispose();
mSimPhoneBookIntManager.dispose();
mSimSmsIntManager.dispose();
mSubInfo.dispose();
@@ -237,10 +235,10 @@
this.mSimSmsIntManager = null;
this.mSMS = null;
this.mSubInfo = null;
- this.mSIMRecords = null;
+ this.mIccRecords = null;
this.mIccFileHandler = null;
- this.mSimCard = null;
- this.mDataConnection = null;
+ this.mIccCard = null;
+ this.mDataConnectionTracker = null;
this.mCT = null;
this.mSST = null;
}
@@ -275,12 +273,12 @@
return mSST.mSignalStrength;
}
- public boolean getMessageWaitingIndicator() {
- return mSIMRecords.getVoiceMessageWaiting();
+ public CallTracker getCallTracker() {
+ return mCT;
}
- public boolean getCallForwardingIndicator() {
- return mSIMRecords.getVoiceCallForwardingFlag();
+ public ServiceStateTracker getServiceStateTracker() {
+ return mSST;
}
public List<? extends MmiCode>
@@ -301,11 +299,14 @@
// 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 ||
- mDataConnection.isApnTypeActive(apnType) == false) {
+ } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false ||
+ mDataConnectionTracker.isApnTypeActive(apnType) == false) {
+ //TODO: isApnTypeActive() is just checking whether ApnContext holds
+ // Dataconnection or not. Checking each ApnState below should
+ // provide the same state. Calling isApnTypeActive() can be removed.
ret = DataState.DISCONNECTED;
} else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
- switch (mDataConnection.getState()) {
+ switch (mDataConnectionTracker.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
@@ -314,7 +315,7 @@
case CONNECTED:
case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData()) {
+ && !mSST.isConcurrentVoiceAndDataAllowed()) {
ret = DataState.SUSPENDED;
} else {
ret = DataState.CONNECTED;
@@ -336,7 +337,7 @@
DataActivityState ret = DataActivityState.NONE;
if (mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE) {
- switch (mDataConnection.getActivity()) {
+ switch (mDataConnectionTracker.getActivity()) {
case DATAIN:
ret = DataActivityState.DATAIN;
break;
@@ -404,7 +405,7 @@
mNotifier.notifySignalStrength(this);
}
- /*package*/ void
+ public void
notifyDataConnectionFailed(String reason, String apnType) {
mNotifier.notifyDataConnectionFailed(this, reason, apnType);
}
@@ -412,7 +413,7 @@
/*package*/ void
updateMessageWaitingIndicator(boolean mwi) {
// this also calls notifyMessageWaitingIndicator()
- mSIMRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
+ mIccRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
}
public void
@@ -813,7 +814,7 @@
public String getVoiceMailNumber() {
// Read from the SIM. If its null, try reading from the shared preference area.
- String number = mSIMRecords.getVoiceMailNumber();
+ String number = mIccRecords.getVoiceMailNumber();
if (TextUtils.isEmpty(number)) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
number = sp.getString(VM_NUMBER, null);
@@ -836,7 +837,7 @@
public String getVoiceMailAlphaTag() {
String ret;
- ret = mSIMRecords.getVoiceMailAlphaTag();
+ ret = mIccRecords.getVoiceMailAlphaTag();
if (ret == null || ret.length() == 0) {
return mContext.getText(
@@ -865,23 +866,19 @@
}
public String getSubscriberId() {
- return mSIMRecords.imsi;
- }
-
- public String getIccSerialNumber() {
- return mSIMRecords.iccid;
+ return mIccRecords.getIMSI();
}
public String getLine1Number() {
- return mSIMRecords.getMsisdnNumber();
+ return mIccRecords.getMsisdnNumber();
}
public String getLine1AlphaTag() {
- return mSIMRecords.getMsisdnAlphaTag();
+ return mIccRecords.getMsisdnAlphaTag();
}
public void setLine1Number(String alphaTag, String number, Message onComplete) {
- mSIMRecords.setMsisdnNumber(alphaTag, number, onComplete);
+ mIccRecords.setMsisdnNumber(alphaTag, number, onComplete);
}
public void setVoiceMailNumber(String alphaTag,
@@ -891,7 +888,7 @@
Message resp;
mVmNumber = voiceMailNumber;
resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
- mSIMRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
+ mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
@@ -981,15 +978,6 @@
mCM.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
}
- public boolean
- getIccRecordsLoaded() {
- return mSIMRecords.getRecordsLoaded();
- }
-
- public IccCard getIccCard() {
- return mSimCard;
- }
-
public void
getAvailableNetworks(Message response) {
mCM.getAvailableNetworks(response);
@@ -1062,10 +1050,6 @@
mCM.getDataCallList(response);
}
- public List<DataConnection> getCurrentDataConnectionList () {
- return mDataConnection.getAllDataConnections();
- }
-
public void updateServiceLocation() {
mSST.enableSingleLocationUpdate();
}
@@ -1079,11 +1063,11 @@
}
public boolean getDataRoamingEnabled() {
- return mDataConnection.getDataOnRoamingEnabled();
+ return mDataConnectionTracker.getDataOnRoamingEnabled();
}
public void setDataRoamingEnabled(boolean enable) {
- mDataConnection.setDataOnRoamingEnabled(enable);
+ mDataConnectionTracker.setDataOnRoamingEnabled(enable);
}
/**
@@ -1273,7 +1257,7 @@
case EVENT_SET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
- mSIMRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1);
+ mIccRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
@@ -1337,11 +1321,11 @@
* @return true for success; false otherwise.
*/
boolean updateCurrentCarrierInProvider() {
- if (mSIMRecords != null) {
+ if (mIccRecords != null) {
try {
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
- map.put(Telephony.Carriers.NUMERIC, mSIMRecords.getSIMOperatorNumeric());
+ map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric());
mContext.getContentResolver().insert(uri, map);
return true;
} catch (SQLException e) {
@@ -1406,11 +1390,11 @@
if (infos == null || infos.length == 0) {
// Assume the default is not active
// Set unconditional CFF in SIM to false
- mSIMRecords.setVoiceCallForwardingFlag(1, false);
+ mIccRecords.setVoiceCallForwardingFlag(1, false);
} else {
for (int i = 0, s = infos.length; i < s; i++) {
if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
- mSIMRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1));
+ mIccRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1));
// should only have the one
break;
}
@@ -1459,6 +1443,6 @@
}
public boolean isCspPlmnEnabled() {
- return mSIMRecords.isCspPlmnEnabled();
+ return mIccRecords.isCspPlmnEnabled();
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index 7dc2504..0870d5b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -374,11 +374,11 @@
} else if (phone.getIccCard().getState() != SimCard.State.READY) {
return DisconnectCause.ICC_ERROR;
} else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
- if (phone.mSST.rs.isCsRestricted()) {
+ if (phone.mSST.mRestrictedState.isCsRestricted()) {
return DisconnectCause.CS_RESTRICTED;
- } else if (phone.mSST.rs.isCsEmergencyRestricted()) {
+ } else if (phone.mSST.mRestrictedState.isCsEmergencyRestricted()) {
return DisconnectCause.CS_RESTRICTED_EMERGENCY;
- } else if (phone.mSST.rs.isCsNormalRestricted()) {
+ } else if (phone.mSST.mRestrictedState.isCsNormalRestricted()) {
return DisconnectCause.CS_RESTRICTED_NORMAL;
} else {
return DisconnectCause.ERROR_UNSPECIFIED;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 4689b2d..9695344 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -19,10 +19,11 @@
import android.os.Message;
import android.util.Log;
import android.util.Patterns;
+import android.text.TextUtils;
-import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
@@ -34,11 +35,11 @@
private static final String LOG_TAG = "GSM";
//***** Instance Variables
- private ApnSetting apn;
-
+ protected int mProfileId = RILConstants.DATA_PROFILE_DEFAULT;
+ protected String mActiveApnType = Phone.APN_TYPE_DEFAULT;
//***** Constructor
- private GsmDataConnection(GSMPhone phone, String name, RetryManager rm) {
- super(phone, name, rm);
+ private GsmDataConnection(PhoneBase phone, String name, int id, RetryManager rm) {
+ super(phone, name, id, rm);
}
/**
@@ -49,15 +50,13 @@
* @param rm the RetryManager
* @return GsmDataConnection that was created.
*/
- static GsmDataConnection makeDataConnection(GSMPhone phone, int id, RetryManager rm) {
+ static GsmDataConnection makeDataConnection(PhoneBase phone, int id, RetryManager rm) {
synchronized (mCountLock) {
mCount += 1;
}
- GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount, rm);
+ GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDC-" + mCount, id, rm);
gsmDc.start();
if (DBG) gsmDc.log("Made " + gsmDc.getName());
- gsmDc.mId = id;
- gsmDc.mRetryMgr = rm;
return gsmDc;
}
@@ -71,13 +70,13 @@
@Override
protected
void onConnect(ConnectionParams cp) {
- apn = cp.apn;
+ mApn = cp.apn;
- if (DBG) log("Connecting to carrier: '" + apn.carrier
- + "' APN: '" + apn.apn
- + "' proxy: '" + apn.proxy + "' port: '" + apn.port);
+ if (DBG) log("Connecting to carrier: '" + mApn.carrier
+ + "' APN: '" + mApn.apn
+ + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
- setHttpProxy (apn.proxy, apn.port);
+ setHttpProxy (mApn.proxy, mApn.port);
createTime = -1;
lastFailTime = -1;
@@ -87,35 +86,42 @@
Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
msg.obj = cp;
- int authType = apn.authType;
+ int authType = mApn.authType;
if (authType == -1) {
- authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
+ authType = (mApn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
RILConstants.SETUP_DATA_AUTH_NONE;
}
String protocol;
if (phone.getServiceState().getRoaming()) {
- protocol = apn.roamingProtocol;
+ protocol = mApn.roamingProtocol;
} else {
- protocol = apn.protocol;
+ protocol = mApn.protocol;
}
phone.mCM.setupDataCall(
- Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
- Integer.toString(RILConstants.DATA_PROFILE_DEFAULT),
- apn.apn, apn.user, apn.password, Integer.toString(authType),
+ Integer.toString(getRadioTechnology(RILConstants.SETUP_DATA_TECH_GSM)),
+ Integer.toString(mProfileId),
+ mApn.apn, mApn.user, mApn.password,
+ Integer.toString(authType),
protocol, msg);
}
- @Override
- protected void clearSettings() {
- super.clearSettings();
- apn = null;
+ public void setProfileId(int profileId) {
+ mProfileId = profileId;
+ }
+
+ public int getProfileId() {
+ return mProfileId;
+ }
+
+ public void setActiveApnType(String apnType) {
+ mActiveApnType = apnType;
}
@Override
public String toString() {
- return "State=" + getCurrentState().getName() + " Apn=" + apn +
+ return "State=" + getCurrentState().getName() + " Apn=" + mApn +
" create=" + createTime + " lastFail=" + lastFailTime +
" lastFailCause=" + lastFailCause;
}
@@ -123,17 +129,18 @@
@Override
protected boolean isDnsOk(String[] domainNameServers) {
if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
- && !((GSMPhone) phone).isDnsCheckDisabled()) {
+ && !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
// if Proxy is an IP-address.
// Otherwise, the default APN will not be restored anymore.
- if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
- || !isIpAddress(apn.mmsProxy)) {
+ if (!mApn.types[0].equals(Phone.APN_TYPE_MMS)
+ || !isIpAddress(mApn.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)));
+ mApn.types[0], Phone.APN_TYPE_MMS, mApn.mmsProxy,
+ isIpAddress(mApn.mmsProxy)));
return false;
}
}
@@ -145,27 +152,41 @@
Log.d(LOG_TAG, "[" + getName() + "] " + s);
}
- public ApnSetting getApn() {
- return this.apn;
- }
-
private void setHttpProxy(String httpProxy, String httpPort) {
- if (httpProxy == null || httpProxy.length() == 0) {
- phone.setSystemProperty("net.gprs.http-proxy", null);
- return;
- }
- if (httpPort == null || httpPort.length() == 0) {
- httpPort = "8080"; // Default to port 8080
- }
+ if (DBG) log("set http proxy for"
+ + "' APN: '" + mActiveApnType
+ + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
+ if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) {
+ if (httpProxy == null || httpProxy.length() == 0) {
+ phone.setSystemProperty("net.gprs.http-proxy", null);
+ return;
+ }
- phone.setSystemProperty("net.gprs.http-proxy",
- "http://" + httpProxy + ":" + httpPort + "/");
+ if (httpPort == null || httpPort.length() == 0) {
+ httpPort = "8080"; // Default to port 8080
+ }
+
+ phone.setSystemProperty("net.gprs.http-proxy",
+ "http://" + httpProxy + ":" + httpPort + "/");
+ } else {
+ if (httpProxy == null || httpProxy.length() == 0) {
+ phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null);
+ return;
+ }
+
+ if (httpPort == null || httpPort.length() == 0) {
+ httpPort = "8080"; // Default to port 8080
+ }
+
+ phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType,
+ "http://" + httpProxy + ":" + httpPort + "/");
+ }
}
private boolean isIpAddress(String address) {
if (address == null) return false;
- return Patterns.IP_ADDRESS.matcher(apn.mmsProxy).matches();
+ return Patterns.IP_ADDRESS.matcher(address).matches();
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index c57f2f1..dcde71a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -22,38 +22,54 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.net.ConnectivityManager;
import android.net.ProxyProperties;
import android.net.TrafficStats;
import android.net.Uri;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkConfig;
import android.os.AsyncResult;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Telephony;
+import android.telephony.CellLocation;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
+import android.preference.PreferenceManager;
import com.android.internal.R;
+import com.android.internal.telephony.ApnContext;
import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.AsyncChannel;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
import java.util.HashMap;
/**
@@ -62,7 +78,6 @@
public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected final String LOG_TAG = "GSM";
- private GSMPhone mGsmPhone;
/**
* Handles changes to the APN db.
*/
@@ -86,70 +101,63 @@
// call reRegisterNetwork, or pingTest succeeds.
private int mPdpResetCount = 0;
- /** Delay between APN attempts */
- protected static final int APN_DELAY_MILLIS = 5000;
+ // Recovery action taken in case of data stall
+ enum RecoveryAction {REREGISTER, RADIO_RESTART, RADIO_RESET};
+ private RecoveryAction mRecoveryAction = RecoveryAction.REREGISTER;
- //useful for debugging
- boolean mFailNextConnect = false;
-
- /**
- * allApns holds all apns for this sim spn, retrieved from
- * the Carrier DB.
- *
- * Create once after simcard info is loaded
- */
- 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> mWaitingApns = null;
- private int mWaitingApnsPermanentFailureCountDown = 0;
- private ApnSetting mPreferredApn = null;
-
- /** The DataConnection being setup */
- private GsmDataConnection mPendingDataConnection;
-
- /** 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
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_TYPE = "type";
static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
static final String APN_ID = "apn_id";
private boolean canSetPreferApn = false;
+ private boolean mRadioAvailable = false;
+
+ @Override
+ protected void onActionIntentReconnectAlarm(Intent intent) {
+ if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
+
+ String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+ String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
+ ApnContext apnContext = mApnContexts.get(type);
+ if (apnContext != null) {
+ apnContext.setReason(reason);
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ }
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
+ }
+ }
/** Watches for changes to the APN db. */
private ApnChangeObserver mApnObserver;
//***** Constructor
- GsmDataConnectionTracker(GSMPhone p) {
+ public GsmDataConnectionTracker(PhoneBase 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);
+ p.mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
- p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
- p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
- p.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
- p.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
- p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
- p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
- p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
- p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
+ p.getCallTracker().registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+ p.getCallTracker().registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+ p.getServiceStateTracker().registerForDataConnectionAttached(this,
+ EVENT_DATA_CONNECTION_ATTACHED, null);
+ p.getServiceStateTracker().registerForDataConnectionDetached(this,
+ EVENT_DATA_CONNECTION_DETACHED, null);
+ p.getServiceStateTracker().registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+ p.getServiceStateTracker().registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+ p.getServiceStateTracker().registerForPsRestrictedEnabled(this,
+ EVENT_PS_RESTRICT_ENABLED, null);
+ p.getServiceStateTracker().registerForPsRestrictedDisabled(this,
+ EVENT_PS_RESTRICT_DISABLED, null);
mDataConnectionTracker = this;
mResolver = mPhone.getContext().getContentResolver();
@@ -158,35 +166,68 @@
p.getContext().getContentResolver().registerContentObserver(
Telephony.Carriers.CONTENT_URI, true, mApnObserver);
- /** Create the default connection */
- createDataConnection(Phone.APN_TYPE_DEFAULT);
+ mApnContexts = new ConcurrentHashMap<String, ApnContext>();
+ initApnContextsAndDataConnection();
broadcastMessenger();
}
@Override
public void dispose() {
+ cleanUpAllConnections(false, null);
+
super.dispose();
//Unregister for all events
mPhone.mCM.unregisterForAvailable(this);
mPhone.mCM.unregisterForOffOrNotAvailable(this);
- mGsmPhone.mSIMRecords.unregisterForRecordsLoaded(this);
+ mPhone.mIccRecords.unregisterForRecordsLoaded(this);
mPhone.mCM.unregisterForDataNetworkStateChanged(this);
- mGsmPhone.mCT.unregisterForVoiceCallEnded(this);
- mGsmPhone.mCT.unregisterForVoiceCallStarted(this);
- mGsmPhone.mSST.unregisterForGprsAttached(this);
- mGsmPhone.mSST.unregisterForGprsDetached(this);
- mGsmPhone.mSST.unregisterForRoamingOn(this);
- mGsmPhone.mSST.unregisterForRoamingOff(this);
- mGsmPhone.mSST.unregisterForPsRestrictedEnabled(this);
- mGsmPhone.mSST.unregisterForPsRestrictedDisabled(this);
+ mPhone.getCallTracker().unregisterForVoiceCallEnded(this);
+ mPhone.getCallTracker().unregisterForVoiceCallStarted(this);
+ mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(this);
+ mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(this);
+ mPhone.getServiceStateTracker().unregisterForRoamingOn(this);
+ mPhone.getServiceStateTracker().unregisterForRoamingOff(this);
+ mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this);
+ mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
mPhone.getContext().getContentResolver().unregisterContentObserver(this.mApnObserver);
+ mApnContexts.clear();
destroyDataConnections();
}
@Override
+ public boolean isApnTypeActive(String type) {
+ ApnContext apnContext = mApnContexts.get(type);
+ if (apnContext == null) return false;
+
+ return (apnContext.getDataConnection() != null);
+ }
+
+ @Override
+ protected boolean isDataPossible(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null) {
+ return false;
+ }
+ boolean apnContextIsEnabled = apnContext.isEnabled();
+ State apnContextState = apnContext.getState();
+ boolean apnTypePossible = !(apnContextIsEnabled &&
+ (apnContextState == State.FAILED));
+ boolean dataAllowed = isDataAllowed();
+ boolean possible = dataAllowed && apnTypePossible;
+
+ if (DBG) {
+ log(String.format("isDataPossible(%s): possible=%b isDataAllowed=%b " +
+ "apnTypePossible=%b apnContextisEnabled=%b apnContextState()=%s",
+ apnType, possible, dataAllowed, apnTypePossible,
+ apnContextIsEnabled, apnContextState));
+ }
+ return possible;
+ }
+
+ @Override
protected void finalize() {
if(DBG) log("finalize");
}
@@ -196,47 +237,262 @@
return INTENT_RECONNECT_ALARM;
}
+ private ApnContext addApnContext(String type) {
+ ApnContext apnContext = new ApnContext(type, LOG_TAG);
+ apnContext.setDependencyMet(false);
+ mApnContexts.put(type, apnContext);
+ return apnContext;
+ }
+
+ protected void initApnContextsAndDataConnection() {
+ boolean defaultEnabled = SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP, true);
+ // Load device network attributes from resources
+ String[] networkConfigStrings = mPhone.getContext().getResources().getStringArray(
+ com.android.internal.R.array.networkAttributes);
+ for (String networkConfigString : networkConfigStrings) {
+ NetworkConfig networkConfig = new NetworkConfig(networkConfigString);
+ ApnContext apnContext = null;
+
+ switch (networkConfig.type) {
+ case ConnectivityManager.TYPE_MOBILE:
+ apnContext = addApnContext(Phone.APN_TYPE_DEFAULT);
+ apnContext.setEnabled(defaultEnabled);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_MMS:
+ apnContext = addApnContext(Phone.APN_TYPE_MMS);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_SUPL:
+ apnContext = addApnContext(Phone.APN_TYPE_SUPL);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_DUN:
+ apnContext = addApnContext(Phone.APN_TYPE_DUN);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ apnContext = addApnContext(Phone.APN_TYPE_HIPRI);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_FOTA:
+ apnContext = addApnContext(Phone.APN_TYPE_FOTA);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_IMS:
+ apnContext = addApnContext(Phone.APN_TYPE_IMS);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_CBS:
+ apnContext = addApnContext(Phone.APN_TYPE_CBS);
+ break;
+ default:
+ // skip unknown types
+ continue;
+ }
+ if (apnContext != null) {
+ // set the prop, but also apply the newly set enabled and dependency values
+ onSetDependencyMet(apnContext.getApnType(), networkConfig.dependencyMet);
+ }
+ }
+ }
+
@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;
+ protected LinkProperties getLinkProperties(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext != null) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac != null) {
+ if (DBG) log("return link properites for " + apnType);
+ return dcac.getLinkPropertiesSync();
+ }
+ }
+ if (DBG) log("return new LinkProperties");
+ return new LinkProperties();
+ }
+
+ @Override
+ protected LinkCapabilities getLinkCapabilities(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext!=null) {
+ DataConnectionAc dataConnectionAc = apnContext.getDataConnectionAc();
+ if (dataConnectionAc != null) {
+ if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType);
+ return dataConnectionAc.getLinkCapabilitiesSync();
+ }
+ }
+ if (DBG) log("return new LinkCapabilities");
+ return new LinkCapabilities();
+ }
+
+ @Override
+ // Return all active apn types
+ public String[] getActiveApnTypes() {
+ if (DBG) log("get all active apn types");
+ ArrayList<String> result = new ArrayList<String>();
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ result.add(apnContext.getApnType());
+ }
}
- if (mState == State.FAILED) {
- if (mWaitingApns != null)
- mWaitingApns.clear(); // when tear down the connection and set to IDLE
+ return (String[])result.toArray(new String[0]);
+ }
+
+ @Override
+ // Return active apn of specific apn type
+ public String getActiveApnString(String apnType) {
+ if (DBG) log( "get active apn string for type:" + apnType);
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext != null) {
+ ApnSetting apnSetting = apnContext.getApnSetting();
+ if (apnSetting != null) {
+ return apnSetting.apn;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isApnTypeEnabled(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null) {
+ return false;
+ }
+ return apnContext.isEnabled();
+ }
+
+ @Override
+ protected void setState(State s) {
+ if (DBG) log("setState should not be used in GSM" + s);
+ }
+
+ // Return state of specific apn type
+ @Override
+ public State getState(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext != null) {
+ return apnContext.getState();
+ }
+ return State.FAILED;
+ }
+
+ // Return state of overall
+ public State getOverallState() {
+ boolean isConnecting = false;
+ boolean isFailed = true; // All enabled Apns should be FAILED.
+ boolean isAnyEnabled = false;
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isEnabled()) {
+ isAnyEnabled = true;
+ switch (apnContext.getState()) {
+ case CONNECTED:
+ case DISCONNECTING:
+ if (DBG) log("overall state is CONNECTED");
+ return State.CONNECTED;
+ case CONNECTING:
+ case INITING:
+ isConnecting = true;
+ isFailed = false;
+ break;
+ case IDLE:
+ case SCANNING:
+ isFailed = false;
+ break;
+ }
+ }
+ }
+
+ if (!isAnyEnabled) { // Nothing enabled. return IDLE.
+ if (DBG) log( "overall state is IDLE");
+ return State.IDLE;
+ }
+
+ if (isConnecting) {
+ if (DBG) log( "overall state is CONNECTING");
+ return State.CONNECTING;
+ } else if (!isFailed) {
+ if (DBG) log( "overall state is IDLE");
+ return State.IDLE;
+ } else {
+ if (DBG) log( "overall state is FAILED");
+ return State.FAILED;
}
}
/**
- * The data connection is expected to be setup while device
- * 1. has sim card
- * 2. registered to gprs service
- * 3. user doesn't explicitly disable data service
- * 4. wifi is not on
+ * Ensure that we are connected to an APN of the specified type.
*
- * @return false while no data connection if all above requirements are met.
+ * @param type the APN type
+ * @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.
*/
@Override
- public boolean isDataConnectionAsDesired() {
- boolean roaming = mPhone.getServiceState().getRoaming();
-
- if (mGsmPhone.mSIMRecords.getRecordsLoaded() &&
- mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
- (!roaming || getDataOnRoamingEnabled()) &&
- !mIsWifiConnected &&
- !mIsPsRestricted ) {
- return (mState == State.CONNECTED);
+ public synchronized int enableApnType(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null || !isApnTypeAvailable(apnType)) {
+ if (DBG) log("enableApnType: " + apnType + " is type not available");
+ return Phone.APN_TYPE_NOT_AVAILABLE;
}
- return true;
+
+ // If already active, return
+ if (DBG) log("enableApnType: " + apnType + " mState(" + apnContext.getState() + ")");
+
+ if (apnContext.getState() == State.CONNECTED) {
+ if (DBG) log("enableApnType: return APN_ALREADY_ACTIVE");
+ return Phone.APN_ALREADY_ACTIVE;
+ }
+ setEnabled(apnTypeToId(apnType), true);
+ if (DBG) {
+ log("enableApnType: new apn request for type " + apnType +
+ " return APN_REQUEST_STARTED");
+ }
+ return Phone.APN_REQUEST_STARTED;
+ }
+
+ // A new APN has gone active and needs to send events to catch up with the
+ // current condition
+ private void notifyApnIdUpToCurrent(String reason, ApnContext apnContext, String type) {
+ switch (apnContext.getState()) {
+ case IDLE:
+ case INITING:
+ break;
+ case CONNECTING:
+ case SCANNING:
+ mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTING);
+ break;
+ case CONNECTED:
+ case DISCONNECTING:
+ mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTING);
+ mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTED);
+ break;
+ }
+ }
+
+ @Override
+ public synchronized int disableApnType(String type) {
+ if (DBG) log("disableApnType:" + type);
+ ApnContext apnContext = mApnContexts.get(type);
+
+ if (apnContext != null) {
+ setEnabled(apnTypeToId(type), false);
+ if (apnContext.getState() != State.IDLE && apnContext.getState() != State.FAILED) {
+ if (DBG) log("diableApnType: return APN_REQUEST_STARTED");
+ return Phone.APN_REQUEST_STARTED;
+ } else {
+ if (DBG) log("disableApnType: return APN_ALREADY_INACTIVE");
+ return Phone.APN_ALREADY_INACTIVE;
+ }
+
+ } else {
+ if (DBG) {
+ log("disableApnType: no apn context was found, return APN_REQUEST_FAILED");
+ }
+ return Phone.APN_REQUEST_FAILED;
+ }
}
@Override
protected boolean isApnTypeAvailable(String type) {
- if (type.equals(Phone.APN_TYPE_DUN)) {
- return (fetchDunApn() != null);
+ if (type.equals(Phone.APN_TYPE_DUN) && fetchDunApn() != null) {
+ return true;
}
if (mAllApns != null) {
@@ -249,41 +505,63 @@
return false;
}
+ /**
+ * Report on whether data connectivity is enabled for any APN.
+ * @return {@code false} if data connectivity has been explicitly disabled,
+ * {@code true} otherwise.
+ */
+ @Override
+ public synchronized boolean getAnyDataEnabled() {
+ if (!(mInternalDataEnabled && mDataEnabled)) return false;
+ for (ApnContext apnContext : mApnContexts.values()) {
+ // Make sure we dont have a context that going down
+ // and is explicitly disabled.
+ if (isDataAllowed(apnContext)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isDataAllowed(ApnContext apnContext) {
+ return apnContext.isReady() && isDataAllowed();
+ }
+
//****** Called from ServiceStateTracker
/**
* Invoked when ServiceStateTracker observes a transition from GPRS
* attach to detach.
*/
- protected void onGprsDetached() {
+ protected void onDataConnectionDetached() {
/*
* We presently believe it is unnecessary to tear down the PDP context
* when GPRS detaches, but we should stop the network polling.
*/
+ if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
stopNetStatPoll();
- notifyDataConnection(Phone.REASON_GPRS_DETACHED);
+ notifyDataConnection(Phone.REASON_DATA_DETACHED);
}
- private void onGprsAttached() {
- if (mState == State.CONNECTED) {
+ private void onDataConnectionAttached() {
+ if (DBG) log("onDataConnectionAttached");
+ if (getOverallState() == State.CONNECTED) {
+ if (DBG) log("onDataConnectionAttached: start polling notify attached");
startNetStatPoll();
- notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
- } else {
- if (mState == State.FAILED) {
- cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
- mRetryMgr.resetRetryCount();
- }
- trySetupData(Phone.REASON_GPRS_ATTACHED);
+ notifyDataConnection(Phone.REASON_DATA_ATTACHED);
}
+
+ setupDataOnReadyApns(Phone.REASON_DATA_ATTACHED);
}
@Override
protected boolean isDataAllowed() {
- int gprsState = mGsmPhone.mSST.getCurrentGprsState();
- boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
+ int gprsState = mPhone.getServiceStateTracker().getCurrentDataConnectionState();
+ boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
boolean allowed =
(gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
- mGsmPhone.mSIMRecords.getRecordsLoaded() &&
+ mPhone.mIccRecords.getRecordsLoaded() &&
+ mPhone.mIccRecords.isProvisioned() &&
mPhone.getState() == Phone.State.IDLE &&
mInternalDataEnabled &&
(!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
@@ -294,7 +572,8 @@
if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
reason += " - gprs= " + gprsState;
}
- if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
+ if (!mPhone.mIccRecords.getRecordsLoaded()) reason += " - SIM not loaded";
+ if (!mPhone.mIccRecords.isProvisioned()) reason += " - SIM not provisioned";
if (mPhone.getState() != Phone.State.IDLE) {
reason += " - PhoneState= " + mPhone.getState();
}
@@ -304,97 +583,219 @@
}
if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
if (!desiredPowerState) reason += " - desiredPowerState= false";
- log("Data not allowed due to" + reason);
+ if (DBG) log("isDataAllowed: not allowed due to" + reason);
}
return allowed;
}
- private boolean trySetupData(String reason) {
- if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
+ private void setupDataOnReadyApns(String reason) {
+ // Only check for default APN state
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ if (apnContext.getState() == State.FAILED) {
+ cleanApnContextBeforeRestart(apnContext);
+ if (apnContext.getDataConnection() != null) {
+ apnContext.getDataConnection().resetRetryCount();
+ }
+ }
+ // Do not start ApnContext in SCANNING state
+ // FAILED state must be reset to IDLE by now
+ if (apnContext.getState() == State.IDLE) {
+ apnContext.setReason(reason);
+ trySetupData(apnContext);
+ }
+ }
+ }
+ }
- log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+ private boolean trySetupData(String reason, String type) {
+ if (DBG) {
+ log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason)
+ + " isPsRestricted=" + mIsPsRestricted);
+ }
+
+ if (type == null) {
+ type = Phone.APN_TYPE_DEFAULT;
+ }
+
+ ApnContext apnContext = mApnContexts.get(type);
+
+ if (apnContext == null ){
+ if (DBG) log("trySetupData new apn context for type:" + type);
+ apnContext = new ApnContext(type, LOG_TAG);
+ mApnContexts.put(type, apnContext);
+ }
+ apnContext.setReason(reason);
+
+ return trySetupData(apnContext);
+ }
+
+ private boolean trySetupData(ApnContext apnContext) {
+ if (DBG) {
+ log("trySetupData for type:" + apnContext.getApnType() +
+ " due to " + apnContext.getReason());
+ log("trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+ }
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
- setState(State.CONNECTED);
- notifyDataConnection(reason);
+ apnContext.setState(State.CONNECTED);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
- log("(fix?) We're on the simulator; assuming data is connected");
+ log("trySetupData: (fix?) We're on the simulator; assuming data is connected");
return true;
}
- int gprsState = mGsmPhone.mSST.getCurrentGprsState();
- boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
+ boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
- if (((mState == State.IDLE) || (mState == State.SCANNING)) &&
- isDataAllowed() && getAnyDataEnabled()) {
+ if ((apnContext.getState() == State.IDLE || apnContext.getState() == State.SCANNING) &&
+ isDataAllowed(apnContext) && 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);
+ if (apnContext.getState() == State.IDLE) {
+ ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
+ if (waitingApns.isEmpty()) {
+ if (DBG) log("trySetupData: No APN found");
+ notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
+ notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false;
} else {
- log ("Create from allApns : " + apnListToString(mAllApns));
+ apnContext.setWaitingApns(waitingApns);
+ if (DBG) {
+ log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
+ }
}
}
if (DBG) {
- log ("Setup waitngApns : " + apnListToString(mWaitingApns));
+ log ("Setup watingApns : " + apnListToString(apnContext.getWaitingApns()));
}
- boolean retValue = setupData(reason);
- notifyOffApnsOfAvailability(reason, retValue);
+ // apnContext.setReason(apnContext.getReason());
+ boolean retValue = setupData(apnContext);
+ notifyOffApnsOfAvailability(apnContext.getReason(), retValue);
return retValue;
} else {
- notifyOffApnsOfAvailability(reason, false);
+ // TODO: check the condition.
+ if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)
+ && (apnContext.getState() == State.IDLE
+ || apnContext.getState() == State.SCANNING))
+ mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+ notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false;
}
}
+ @Override
+ // 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 (ApnContext apnContext : mApnContexts.values()) {
+ if (!apnContext.isReady()) {
+ if (DBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
+ mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
+ apnContext.getApnType(),
+ Phone.DataState.DISCONNECTED);
+ }
+ }
+ }
+
+ /**
+ * 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.
+ */
+ protected void cleanUpAllConnections(boolean tearDown, String reason) {
+ if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason);
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ apnContext.setReason(reason);
+ cleanUpConnection(tearDown, apnContext);
+ }
+
+ stopNetStatPoll();
+ // TODO: Do we need mRequestedApnType?
+ mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+ }
+
/**
* Cleanup all connections.
*
* TODO: Cleanup only a specified connection passed as a parameter.
+ * Also, make sure when you clean up a conn, if it is last apply
+ * logic as though it is cleanupAllConnections
*
* @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);
+
+ @Override
+ protected void onCleanUpAllConnections(String cause) {
+ cleanUpAllConnections(true, cause);
+ }
+
+ private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
+
+ if (apnContext == null) {
+ if (DBG) log("cleanUpConnection: apn context is null");
+ return;
+ }
+
+ if (DBG) {
+ log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
+ }
+ if (tearDown && cleanApnContextBeforeRestart(apnContext)) {
+ // if the request is tearDown and ApnContext does not hold an active connection,
+ // we're ok to return here.
+ return;
+ }
+
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (tearDown && (dcac != null)) {
+ if (DBG) log("cleanUpConnection: tearing down");
+ Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+ apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+ apnContext.setState(State.DISCONNECTING);
+ } else {
+ if (dcac != null) dcac.resetSync();
+ apnContext.setState(State.IDLE);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+ }
+ }
+
+ /**
+ * @param APNContext to clean
+ * @return true if ApnContext is not connected anymore.
+ * false if ApnContext still holds a connection.
+ */
+ private boolean cleanApnContextBeforeRestart(ApnContext apnContext) {
+ if (apnContext == null) return true;
// Clear the reconnect alarm, if set.
- if (mReconnectIntent != null) {
+ if (apnContext.getReconnectIntent() != null) {
AlarmManager am =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- am.cancel(mReconnectIntent);
- mReconnectIntent = null;
+ am.cancel(apnContext.getReconnectIntent());
+ apnContext.setReconnectIntent(null);
}
- setState(State.DISCONNECTING);
-
- boolean notificationDeferred = false;
- for (DataConnection conn : mDataConnections.values()) {
- if (tearDown) {
- if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
- conn.getDataConnectionId(), 0, reason));
- notificationDeferred = true;
- } else {
- if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
- conn.resetSynchronously();
- notificationDeferred = false;
- }
+ if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
+ if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
+ return true;
}
- stopNetStatPoll();
- if (!notificationDeferred) {
- if (DBG) log("cleanupConnection: !notificationDeferred");
- gotoIdleAndNotifyDataConnection(reason);
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ return true;
}
+ return false;
}
/**
@@ -439,162 +840,255 @@
result.add(apn);
} while (cursor.moveToNext());
}
+ if (DBG) log("createApnList: X result=" + result);
return result;
}
private GsmDataConnection findFreeDataConnection() {
- for (DataConnection dc : mDataConnections.values()) {
- if (dc.isInactive()) {
- log("found free GsmDataConnection");
- return (GsmDataConnection) dc;
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.isInactiveSync()) {
+ log("findFreeDataConnection: found free GsmDataConnection");
+ return (GsmDataConnection) dcac.dataConnection;
}
}
- log("NO free GsmDataConnection");
+ log("findFreeDataConnection: NO free GsmDataConnection");
return null;
}
- private boolean setupData(String reason) {
- ApnSetting apn;
- GsmDataConnection gdc;
+ protected GsmDataConnection findReadyDataConnection(ApnSetting apn) {
+ if (DBG)
+ log("findReadyDataConnection: apn string <" +
+ (apn!=null?(apn.toString()):"null") +">");
+ if (apn == null) {
+ return null;
+ }
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ ApnSetting apnSetting = dcac.getApnSettingSync();
+ if (DBG) {
+ log("findReadyDataConnection: dc apn string <" +
+ (apnSetting != null ? (apnSetting.toString()) : "null") + ">");
+ }
+ if ((apnSetting != null) && TextUtils.equals(apnSetting.toString(), apn.toString())) {
+ return (GsmDataConnection) dcac.dataConnection;
+ }
+ }
+ return null;
+ }
- apn = getNextApn();
- if (apn == null) return false;
- gdc = findFreeDataConnection();
- if (gdc == null) {
- if (DBG) log("setupData: No free GsmDataConnection found!");
+
+ private boolean setupData(ApnContext apnContext) {
+ if (DBG) log("setupData: apnContext=" + apnContext);
+ ApnSetting apn;
+ GsmDataConnection dc;
+
+ int profileId = getApnProfileID(apnContext.getApnType());
+ apn = apnContext.getNextWaitingApn();
+ if (apn == null) {
+ if (DBG) log("setupData: return for no apn found!");
return false;
}
- mActiveApn = apn;
- mPendingDataConnection = gdc;
+
+ // First, check to see if ApnContext already has DC.
+ // This could happen if the retries are currently engaged.
+ dc = (GsmDataConnection)apnContext.getDataConnection();
+
+ if (dc == null) {
+
+ dc = (GsmDataConnection) checkForConnectionForApnContext(apnContext);
+
+ if (dc == null) {
+ dc = findReadyDataConnection(apn);
+ }
+
+ if (dc == null) {
+ if (DBG) log("setupData: No ready GsmDataConnection found!");
+ // TODO: When allocating you are mapping type to id. If more than 1 free,
+ // then could findFreeDataConnection get the wrong one??
+ dc = findFreeDataConnection();
+ }
+
+ if (dc == null) {
+ dc = createDataConnection();
+ }
+
+ if (dc == null) {
+ if (DBG) log("setupData: No free GsmDataConnection found!");
+ return false;
+ }
+
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId());
+ dc.setProfileId( profileId );
+ dc.setActiveApnType(apnContext.getApnType());
+ int refCount = dcac.getRefCountSync();
+ if (DBG) log("setupData: init dc and apnContext refCount=" + refCount);
+
+ // configure retry count if no other Apn is using the same connection.
+ if (refCount == 0) {
+ configureRetry(dc, apnContext.getApnType());
+ }
+ apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId()));
+ apnContext.setApnSetting(apn);
+ apnContext.setDataConnection(dc);
+ }
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
- msg.obj = reason;
- gdc.connect(msg, apn);
+ msg.obj = apnContext;
+ dc.bringUp(msg, apn);
- setState(State.INITING);
- notifyDataConnection(reason);
+ apnContext.setState(State.INITING);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ if (DBG) log("setupData: initing!");
return true;
}
- 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 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;
- }
- }
-
- return false;
- }
-
/**
* Handles changes to the APN database.
*/
private void onApnChanged() {
+ // TODO: How to handle when multiple APNs are active?
boolean isConnected;
- isConnected = (mState != State.IDLE && mState != State.FAILED);
+ ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+ isConnected = (defaultApnContext.getState() != State.IDLE
+ && defaultApnContext.getState() != State.FAILED);
- // The "current" may no longer be valid. MMS depends on this to send properly.
- mGsmPhone.updateCurrentCarrierInProvider();
+ if (mPhone instanceof GSMPhone) {
+ // The "current" may no longer be valid. MMS depends on this to send properly. TBD
+ ((GSMPhone)mPhone).updateCurrentCarrierInProvider();
+ }
// TODO: It'd be nice to only do this if the changed entrie(s)
// match the current operator.
+ if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
createAllApnList();
- if (mState != State.DISCONNECTING) {
- cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
- if (!isConnected) {
- // reset reconnect timer
- mRetryMgr.resetRetryCount();
- mReregisterOnReconnectFailure = false;
- trySetupData(Phone.REASON_APN_CHANGED);
- }
+ cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED);
+ if (!isConnected) {
+ setupDataOnReadyApns(Phone.REASON_APN_CHANGED);
}
}
/**
- * @param explicitPoll if true, indicates that *we* polled for this
- * update while state == CONNECTED rather than having it delivered
- * via an unsolicited response (which could have happened at any
- * previous state
+ * @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
+ * or RIL_UNSOL_DATA_CALL_LIST_CHANGED
*/
- private void onDataStateChanged (AsyncResult ar, boolean explicitPoll) {
+ private void onDataStateChanged (AsyncResult ar) {
ArrayList<DataCallState> dataCallStates;
+ if (DBG) log("onDataStateChanged(ar): E");
dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
// of that sort. If so, the whole connection is going
// to come down soon anyway
+ if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return;
}
- 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 (!dataCallStatesHasCID(dataCallStates, mCidActive)) {
- // It looks like the PDP context has deactivated.
- // Tear everything down and try to reconnect.
+ // Create a hash map to store the dataCallState of each call id
+ // TODO: Depends on how frequent the DATA_CALL_LIST got updated,
+ // may cache response to reduce comparison.
+ HashMap<Integer, DataCallState> response;
+ response = new HashMap<Integer, DataCallState>();
+ if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
+ for (DataCallState dc : dataCallStates) {
+ response.put(dc.cid, dc);
+ if (DBG) log("onDataStateChanged(ar): " + dc.cid + ": " + dc.toString());
+ }
- log("PDP connection has dropped. Reconnecting");
-
- // Add an event log when the network drops PDP
- 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 (!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
- mPhone.mCM.getPDPContextList(
- this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
- } else {
- log("PDP connection has dropped (active=false case). "
- + " Reconnecting");
-
- // Log the network drop on the event log.
- GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
- loc != null ? loc.getCid() : -1,
- TelephonyManager.getDefault().getNetworkType());
-
- cleanUpConnection(true, null);
+ // For each connected apn, check if there is a matched active
+ // data call state, which has the same link properties.
+ if (DBG) log(" ApnContext size=" + mApnContexts.values().size());
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (DBG){
+ log("onDataStateChanged(ar): " + apnContext.toString());
+ if (apnContext.getDataConnection() != null) {
+ log("onDataStateChanged(ar): " + apnContext.getDataConnection().toString());
}
}
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ continue;
+ }
+ int connectionId = dcac.getCidSync();
+
+ if (apnContext.getState() == 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 de-activated one.
+ if (response.containsKey(connectionId)) {
+ DataCallState newState = response.get(connectionId);
+ if (DBG) log("onDataStateChanged(ar): Found ConnId=" + connectionId
+ + " newState=" + newState.toString());
+ if (newState.active != 0) {
+ boolean resetConnection;
+ switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
+ case NONE:
+ if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
+ resetConnection = false;
+ break;
+ case CHANGED:
+ if (DBG) log("onDataStateChanged(ar): Found and changed, notify");
+ mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
+ apnContext.getApnType());
+ // Temporary hack, at this time a transition from CDMA -> Global
+ // fails so we'll hope for the best and not reset the connection.
+ // @see bug/4455071
+ if (SystemProperties.getBoolean("telephony.ignore-state-changes",
+ true)) {
+ log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
+ resetConnection = false;
+ } else {
+ // Things changed so reset connection, when hack is removed
+ // this is the normal path.
+ log("onDataStateChanged(ar): changed so resetting connection");
+ resetConnection = true;
+ }
+ break;
+ case RESET:
+ default:
+ if (DBG) log("onDataStateChanged(ar): an error, reset connection");
+ resetConnection = true;
+ break;
+ }
+ if (resetConnection == false) continue;
+ }
+ }
+
+ if (DBG) log("onDataStateChanged(ar): reset connection.");
+
+ // Add an event log when the network drops PDP
+ int cid = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
+ TelephonyManager.getDefault().getNetworkType());
+
+ cleanUpConnection(true, apnContext);
+ }
}
+
+ if (DBG) log("onDataStateChanged(ar): X");
}
- private void notifyDefaultData(String reason) {
- setState(State.CONNECTED);
- notifyDataConnection(reason);
+ private void notifyDefaultData(ApnContext apnContext) {
+ if (DBG) {
+ log("notifyDefaultData: type=" + apnContext.getApnType()
+ + ", reason:" + apnContext.getReason());
+ }
+ apnContext.setState(State.CONNECTED);
+ // setState(State.CONNECTED);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
startNetStatPoll();
// reset reconnect timer
- mRetryMgr.resetRetryCount();
- mReregisterOnReconnectFailure = false;
+ apnContext.getDataConnection().resetRetryCount();
}
- private void gotoIdleAndNotifyDataConnection(String reason) {
+ // TODO: For multiple Active APNs not exactly sure how to do this.
+ protected void gotoIdleAndNotifyDataConnection(String reason) {
if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
- setState(State.IDLE);
notifyDataConnection(reason);
mActiveApn = null;
}
@@ -608,28 +1102,60 @@
}
private void doRecovery() {
- if (mState == State.CONNECTED) {
+ if (getOverallState() == 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, mSentSinceLastRecv);
- cleanUpConnection(true, Phone.REASON_PDP_RESET);
+ if (DBG) log("doRecovery() cleanup all connections mPdpResetCount < max");
+ cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
} else {
mPdpResetCount = 0;
- EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
- mGsmPhone.mSST.reRegisterNetwork(null);
+ switch (mRecoveryAction) {
+ case REREGISTER:
+ EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
+ if (DBG) log("doRecovery() re-register getting preferred network type");
+ mPhone.getServiceStateTracker().reRegisterNetwork(null);
+ mRecoveryAction = RecoveryAction.RADIO_RESTART;
+ break;
+ case RADIO_RESTART:
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
+ if (DBG) log("restarting radio");
+ mRecoveryAction = RecoveryAction.RADIO_RESET;
+ restartRadio();
+ break;
+ case RADIO_RESET:
+ // This is in case radio restart has not recovered the data.
+ // It will set an additional "gsm.radioreset" property to tell
+ // RIL or system to take further action.
+ // The implementation of hard reset recovery action is up to OEM product.
+ // Once gsm.radioreset property is consumed, it is expected to set back
+ // to false by RIL.
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1);
+ if (DBG) log("restarting radio with reset indication");
+ SystemProperties.set("gsm.radioreset", "true");
+ // give 1 sec so property change can be notified.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {}
+ restartRadio();
+ break;
+ default:
+ throw new RuntimeException("doRecovery: Invalid mRecoveryAction " +
+ mRecoveryAction);
+ }
}
- // TODO: Add increasingly drastic recovery steps, eg,
- // reset the radio, reset the device.
+ } else {
+ if (DBG) log("doRecovery(): ignore, we're not connected");
}
}
@Override
protected void startNetStatPoll() {
- if (mState == State.CONNECTED && mNetStatPollEnabled == false) {
- log("[DataConnection] Start poll NetStat");
+ if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) {
+ if (DBG) log("startNetStatPoll");
resetPollStats();
mNetStatPollEnabled = true;
mPollNetStat.run();
@@ -640,14 +1166,14 @@
protected void stopNetStatPoll() {
mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat);
- log("[DataConnection] Stop poll NetStat");
+ if (DBG) log("stopNetStatPoll");
}
@Override
protected void restartRadio() {
- log("************TURN OFF RADIO**************");
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
- mGsmPhone.mSST.powerOffRadioSafely();
+ if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
+ cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
+ mPhone.getServiceStateTracker().powerOffRadioSafely(this);
/* 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
@@ -672,10 +1198,30 @@
preTxPkts = mTxPkts;
preRxPkts = mRxPkts;
- mTxPkts = TrafficStats.getMobileTxPackets();
- mRxPkts = TrafficStats.getMobileRxPackets();
+ long txSum = 0, rxSum = 0;
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.getState() == State.CONNECTED) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) continue;
- //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+ LinkProperties linkProp = dcac.getLinkPropertiesSync();
+ if (linkProp == null) continue;
+
+ String iface = linkProp.getInterfaceName();
+
+ if (iface != null) {
+ long stats = TrafficStats.getTxPackets(iface);
+ if (stats > 0) txSum += stats;
+ stats = TrafficStats.getRxPackets(iface);
+ if (stats > 0) rxSum += stats;
+ }
+ }
+ }
+
+ mTxPkts = txSum;
+ mRxPkts = rxSum;
+
+ // log("tx " + mTxPkts + " rx " + mRxPkts);
if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
sent = mTxPkts - preTxPkts;
@@ -685,6 +1231,7 @@
mSentSinceLastRecv = 0;
newActivity = Activity.DATAINANDOUT;
mPdpResetCount = 0;
+ mRecoveryAction = RecoveryAction.REREGISTER;
} else if (sent > 0 && received == 0) {
if (mPhone.getState() == Phone.State.IDLE) {
mSentSinceLastRecv += sent;
@@ -696,6 +1243,7 @@
mSentSinceLastRecv = 0;
newActivity = Activity.DATAIN;
mPdpResetCount = 0;
+ mRecoveryAction = RecoveryAction.REREGISTER;
} else if (sent == 0 && received == 0) {
newActivity = Activity.NONE;
} else {
@@ -726,8 +1274,8 @@
if (mNoRecvPollCount < noRecvPollLimit) {
// 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");
- mPhone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+ if (DBG) log("Polling: no DATAIN in a while; polling PDP");
+ mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED));
mNoRecvPollCount++;
@@ -736,9 +1284,9 @@
Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
- if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
+ if (DBG) log("Polling: Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received start recovery process");
- stopNetStatPoll();
+ mNoRecvPollCount = 0;
sendMessage(obtainMessage(EVENT_START_RECOVERY));
}
} else {
@@ -784,122 +1332,217 @@
return retry;
}
- private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
- 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.
- notifyDataConnection(Phone.REASON_APN_FAILED);
- onEnableApn(apnTypeToId(mRequestedApnType), DISABLED);
+ private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
+ if (apnContext == null) {
+ loge("reconnectAfterFail: apnContext == null, impossible");
+ return;
+ }
+ if ((apnContext.getState() == State.FAILED) &&
+ (apnContext.getDataConnection() != null)) {
+ if (!apnContext.getDataConnection().isRetryNeeded()) {
+ if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
+ mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
return;
}
if (mReregisterOnReconnectFailure) {
- // We've re-registered once now just retry forever.
- mRetryMgr.retryForeverUsingLastTimeout();
+ // We've re-registerd once now just retry forever.
+ apnContext.getDataConnection().retryForeverUsingLastTimeout();
} else {
- // Try to re-register to the network.
- log("PDP activate failed, Reregistering to the network");
+ // Try to Re-register to the network.
+ if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
mReregisterOnReconnectFailure = true;
- mGsmPhone.mSST.reRegisterNetwork(null);
- mRetryMgr.resetRetryCount();
+ mPhone.getServiceStateTracker().reRegisterNetwork(null);
+ apnContext.getDataConnection().resetRetryCount();
return;
}
}
- int nextReconnectDelay = mRetryMgr.getRetryTimer();
- log("PDP activate failed. Scheduling next attempt for "
- + (nextReconnectDelay / 1000) + "s");
-
- AlarmManager am =
- (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(
- mPhone.getContext(), 0, intent, 0);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + nextReconnectDelay,
- mReconnectIntent);
-
- mRetryMgr.increaseRetryCount();
+ int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+ startAlarmForReconnect(nextReconnectDelay, apnContext);
+ apnContext.getDataConnection().increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
- log("NOT Posting GPRS Unavailable notification "
+ if (DBG) {
+ log("reconnectAfterFail: NOT Posting GPRS Unavailable notification "
+ "-- likely transient error");
+ }
} else {
- notifyNoData(lastFailCauseCode);
+ notifyNoData(lastFailCauseCode, apnContext);
}
}
}
- private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode) {
- setState(State.FAILED);
+ private void startAlarmForReconnect(int delay, ApnContext apnContext) {
+
+ if (DBG) {
+ log("Schedule alarm for reconnect: activate failed. Scheduling next attempt for "
+ + (delay / 1000) + "s");
+ }
+
+ AlarmManager am =
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+
+ // TODO : Register the receiver only once maybe in baseclass.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
+ mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
+ Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
+ apnContext.setReconnectIntent(PendingIntent.getBroadcast (
+ mPhone.getContext(), 0, intent, 0));
+ am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delay, apnContext.getReconnectIntent());
+
+ }
+
+ private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
+ ApnContext apnContext) {
+ if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
+ apnContext.setState(State.FAILED);
+ if (lastFailCauseCode.isPermanentFail()
+ && (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) {
+ mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+ }
}
private void onRecordsLoaded() {
+ if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList();
- if (mState == State.FAILED) {
- cleanUpConnection(false, null);
+ if (mRadioAvailable) {
+ if (DBG) log("onRecordsLoaded: notifying data availability");
+ notifyDataAvailability(null);
}
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
+ setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}
@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)) {
- 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();
+ protected void onSetDependencyMet(String apnType, boolean met) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null) {
+ loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
+ apnType + ", " + met + ")");
+ return;
+ }
+ applyNewState(apnContext, apnContext.isEnabled(), met);
+ }
+
+ private void applyNewState(ApnContext apnContext, boolean enabled, boolean met) {
+ boolean cleanup = false;
+ boolean trySetup = false;
+ if (DBG) {
+ log("applyNewState(" + apnContext.getApnType() + ", " + enabled +
+ "(" + apnContext.isEnabled() + "), " + met + "(" +
+ apnContext.getDependencyMet() +"))");
+ }
+ if (apnContext.isReady()) {
+ if (enabled && met) return;
+ if (!enabled) {
+ apnContext.setReason(Phone.REASON_DATA_DISABLED);
+ } else {
+ apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_UNMET);
+ }
+ cleanup = true;
} else {
- log("oneEnableNewApn connection already exists, nothing to setup");
+ if (enabled && met) {
+ if (apnContext.isEnabled()) {
+ apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_MET);
+ } else {
+ apnContext.setReason(Phone.REASON_DATA_ENABLED);
+ }
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ }
+ trySetup = true;
+ }
}
+ apnContext.setEnabled(enabled);
+ apnContext.setDependencyMet(met);
+ if (cleanup) cleanUpConnection(true, apnContext);
+ if (trySetup) trySetupData(apnContext);
+ }
- // 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");
+ private DataConnection checkForConnectionForApnContext(ApnContext apnContext) {
+ // Loop through all apnContexts looking for one with a conn that satisfies this apnType
+ String apnType = apnContext.getApnType();
+ for (ApnContext c : mApnContexts.values()) {
+ DataConnection conn = c.getDataConnection();
+ if (conn != null) {
+ ApnSetting apnSetting = c.getApnSetting();
+ if (apnSetting != null && apnSetting.canHandleType(apnType)) {
+ if (DBG) {
+ log("checkForConnectionForApnContext: apnContext=" + apnContext +
+ " found conn=" + conn);
+ }
+ return conn;
+ }
+ }
+ }
+ if (DBG) log("checkForConnectionForApnContext: apnContext=" + apnContext + " NO conn");
+ return null;
}
@Override
+ protected void onEnableApn(int apnId, int enabled) {
+ ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
+ if (apnContext == null) {
+ loge("onEnableApn(" + apnId + ", " + enabled + "): NO ApnContext");
+ return;
+ }
+ // TODO change our retry manager to use the appropriate numbers for the new APN
+ if (DBG) log("onEnableApn: apnContext=" + apnContext + " call applyNewState");
+ applyNewState(apnContext, enabled == ENABLED, apnContext.getDependencyMet());
+ }
+
+ @Override
+ // TODO: We shouldnt need this.
protected boolean onTrySetupData(String reason) {
- return trySetupData(reason);
+ if (DBG) log("onTrySetupData: reason=" + reason);
+ setupDataOnReadyApns(reason);
+ return true;
+ }
+
+ protected boolean onTrySetupData(ApnContext apnContext) {
+ if (DBG) log("onTrySetupData: apnContext=" + apnContext);
+ return trySetupData(apnContext);
}
@Override
protected void onRoamingOff() {
- trySetupData(Phone.REASON_ROAMING_OFF);
+ if (DBG) log("onRoamingOff");
+ setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
}
@Override
protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) {
- trySetupData(Phone.REASON_ROAMING_ON);
+ if (DBG) log("onRoamingOn: setup data on roaming");
+ setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
} else {
- if (DBG) log("Tear down data connection on roaming.");
- cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+ if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
+ cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
}
}
@Override
protected void onRadioAvailable() {
+ if (DBG) log("onRadioAvailable");
+ mRadioAvailable = true;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
- setState(State.CONNECTED);
+ // setState(State.CONNECTED);
notifyDataConnection(null);
- log("We're on the simulator; assuming data is connected");
+ log("onRadioAvailable: We're on the simulator; assuming data is connected");
}
- if (mState != State.IDLE) {
+ if (mPhone.mIccRecords.getRecordsLoaded()) {
+ notifyDataAvailability(null);
+ }
+
+ if (getOverallState() != State.IDLE) {
cleanUpConnection(true, null);
}
}
@@ -908,72 +1551,80 @@
protected void onRadioOffOrNotAvailable() {
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
- mRetryMgr.resetRetryCount();
+
+ for (DataConnection dc : mDataConnections.values()) {
+ dc.resetRetryCount();
+ }
mReregisterOnReconnectFailure = false;
+ mRadioAvailable = false;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
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"?
- cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+ if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections");
+ cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
}
+ notifyDataAvailability(null);
}
@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;
+
+ ApnContext apnContext = null;
+
+ if(ar.userObj instanceof ApnContext){
+ apnContext = (ApnContext)ar.userObj;
+ } else {
+ throw new RuntimeException("onDataSetupComplete: No apnContext");
}
- if (ar.exception == null) {
- if(DBG) {
- log(String.format("onDataSetupComplete: success apn=%s", mWaitingApns.get(0).apn));
+ if (isDataSetupCompleteOk(ar)) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ throw new RuntimeException("onDataSetupCompete: No dcac");
}
- // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mPendingDataConnection);
- mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
+ DataConnection dc = apnContext.getDataConnection();
- ApnSetting apn = mPendingDataConnection.getApn();
+ if (DBG) {
+ log(String.format("onDataSetupComplete: success apn=%s",
+ apnContext.getWaitingApns().get(0).apn));
+ }
+ ApnSetting apn = apnContext.getApnSetting();
if (apn.proxy != null && apn.proxy.length() != 0) {
try {
ProxyProperties proxy = new ProxyProperties(apn.proxy,
Integer.parseInt(apn.port), null);
- mLinkProperties.setHttpProxy(proxy);
+ dcac.setLinkPropertiesHttpProxySync(proxy);
} catch (NumberFormatException e) {
- loge("NumberFormatException making ProxyProperties (" + apn.port +
- "): " + e);
+ loge("onDataSetupComplete: NumberFormatException making ProxyProperties (" +
+ apn.port + "): " + e);
}
}
// everything is setup
- if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+ if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
- if (canSetPreferApn && mPreferredApn == null) {
- log("PREFERRED APN is null");
- mPreferredApn = mActiveApn;
- setPreferredApn(mPreferredApn.id);
- }
+ if (canSetPreferApn && mPreferredApn == null) {
+ if (DBG) log("onDataSetupComplete: PREFERED APN is null");
+ mPreferredApn = apnContext.getApnSetting();
+ if (mPreferredApn != null) {
+ setPreferredApn(mPreferredApn.id);
+ }
+ }
} else {
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
}
- notifyDefaultData(reason);
-
- // TODO: For simultaneous PDP support, we need to build another
- // trigger another TRY_SETUP_DATA for the next APN type. (Note
- // that the existing connection may service that type, in which
- // case we should try the next type, etc.
+ notifyDefaultData(apnContext);
} else {
- GsmDataConnection.FailCause cause;
- cause = (GsmDataConnection.FailCause) (ar.result);
+ String apnString;
+ DataConnection.FailCause cause;
+
+ cause = (DataConnection.FailCause) (ar.result);
if (DBG) {
- String apnString;
try {
- apnString = mWaitingApns.get(0).apn;
+ apnString = apnContext.getWaitingApns().get(0).apn;
} catch (Exception e) {
apnString = "<unknown>";
}
@@ -981,35 +1632,46 @@
}
if (cause.isEventLoggable()) {
// Log this failure to the Event Logs.
- GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
+ int cid = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
- cause.ordinal(), loc != null ? loc.getCid() : -1,
- TelephonyManager.getDefault().getNetworkType());
+ cause.ordinal(), cid, TelephonyManager.getDefault().getNetworkType());
}
// Count permanent failures and remove the APN we just tried
- mWaitingApnsPermanentFailureCountDown -= cause.isPermanentFail() ? 1 : 0;
- mWaitingApns.remove(0);
- if (DBG) log(String.format("onDataSetupComplete: mWaitingApns.size=%d" +
- " mWaitingApnsPermanenatFailureCountDown=%d",
- mWaitingApns.size(), mWaitingApnsPermanentFailureCountDown));
+ if (cause.isPermanentFail()) apnContext.decWaitingApnsPermFailCount();
+
+ apnContext.removeNextWaitingApn();
+ if (DBG) {
+ log(String.format("onDataSetupComplete: WaitingApns.size=%d" +
+ " WaitingApnsPermFailureCountDown=%d",
+ apnContext.getWaitingApns().size(),
+ apnContext.getWaitingApnsPermFailCount()));
+ }
// See if there are more APN's to try
- if (mWaitingApns.isEmpty()) {
- if (mWaitingApnsPermanentFailureCountDown == 0) {
- if (DBG) log("onDataSetupComplete: Permanent failures stop retrying");
- notifyNoData(cause);
- notifyDataConnection(Phone.REASON_APN_FAILED);
+ if (apnContext.getWaitingApns().isEmpty()) {
+ if (apnContext.getWaitingApnsPermFailCount() == 0) {
+ if (DBG) {
+ log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
+ }
+ apnContext.setState(State.FAILED);
+ mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
+
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+ if (DBG) {
+ log("onDataSetupComplete: permanent error apn=%s" + apnString );
+ }
} else {
if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
- startDelayedRetry(cause, reason);
+ startDelayedRetry(cause, apnContext);
}
} else {
if (DBG) log("onDataSetupComplete: Try next APN");
- setState(State.SCANNING);
+ apnContext.setState(State.SCANNING);
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
- sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason), APN_DELAY_MILLIS);
+ startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
}
}
}
@@ -1019,43 +1681,55 @@
*/
@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;
- }
- setState(State.IDLE);
- notifyDataConnection(reason);
- mActiveApn = null;
- if (retryAfterDisconnected(reason)) {
- trySetupData(reason);
- }
- }
+ ApnContext apnContext = null;
- /**
- * Called when EVENT_RESET_DONE is received.
- */
- @Override
- protected void onResetDone(AsyncResult ar) {
- if (DBG) log("EVENT_RESET_DONE");
- String reason = null;
- if (ar.userObj instanceof String) {
- reason = (String) ar.userObj;
+ if(DBG) log("onDisconnectDone: EVENT_DISCONNECT_DONE connId=" + connId);
+ if (ar.userObj instanceof ApnContext) {
+ apnContext = (ApnContext) ar.userObj;
+ } else {
+ loge("Invalid ar in onDisconnectDone");
+ return;
}
- gotoIdleAndNotifyDataConnection(reason);
+
+ apnContext.setState(State.IDLE);
+ apnContext.setApnSetting(null);
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+
+ // if all data connection are gone, check whether Airplane mode request was
+ // pending.
+ if (!isConnected()) {
+ if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
+ // Radio will be turned off. No need to retry data setup
+ return;
+ }
+ }
+
+ // If APN is still enabled, try to bring it back up automatically
+ if (apnContext.isReady() && retryAfterDisconnected(apnContext.getReason())) {
+ SystemProperties.set("gsm.defaultpdpcontext.active", "false"); // TODO - what the heck? This shoudld go
+ // Wait a bit before trying the next APN, so that
+ // we're not tying up the RIL command channel.
+ // This also helps in any external dependency to turn off the context.
+ startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
+ }
}
protected void onPollPdp() {
- if (mState == State.CONNECTED) {
+ if (getOverallState() == State.CONNECTED) {
// only poll when connected
- mPhone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+ mPhone.mCM.getDataCallList(this.obtainMessage(EVENT_DATA_STATE_CHANGED));
sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
}
}
@Override
protected void onVoiceCallStarted() {
- if (mState == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+ if (DBG) log("onVoiceCallStarted");
+ if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
+ if (DBG) log("onVoiceCallStarted stop polling");
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
}
@@ -1063,8 +1737,9 @@
@Override
protected void onVoiceCallEnded() {
- if (mState == State.CONNECTED) {
- if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+ if (DBG) log("onVoiceCallEnded");
+ if (isConnected()) {
+ if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
} else {
@@ -1073,16 +1748,40 @@
}
} else {
// reset reconnect timer
- mRetryMgr.resetRetryCount();
- mReregisterOnReconnectFailure = false;
- // in case data setup was attempted when we were on a voice call
- trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+ setupDataOnReadyApns(Phone.REASON_VOICE_CALL_ENDED);
}
}
@Override
- protected void onCleanUpConnection(boolean tearDown, String reason) {
- cleanUpConnection(tearDown, reason);
+ protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) {
+ if (DBG) log("onCleanUpConnection");
+ ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
+ if (apnContext != null) {
+ apnContext.setReason(reason);
+ cleanUpConnection(tearDown, apnContext);
+ }
+ }
+
+ protected boolean isConnected() {
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.getState() == State.CONNECTED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void notifyDataConnection(String reason) {
+ if (DBG) log("notifyDataConnection: reason=" + reason);
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ if (DBG) log("notifyDataConnection: type:"+apnContext.getApnType());
+ mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
+ apnContext.getApnType());
+ }
+ }
+ notifyDataAvailability(reason);
}
/**
@@ -1091,10 +1790,10 @@
*/
private void createAllApnList() {
mAllApns = new ArrayList<ApnSetting>();
- String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
-
+ String operator = mPhone.mIccRecords.getOperatorNumeric();
if (operator != null) {
String selection = "numeric = '" + operator + "'";
+ if (DBG) log("createAllApnList: selection=" + selection);
Cursor cursor = mPhone.getContext().getContentResolver().query(
Telephony.Carriers.CONTENT_URI, null, selection, null, null);
@@ -1108,73 +1807,75 @@
}
if (mAllApns.isEmpty()) {
- if (DBG) log("No APN found for carrier: " + operator);
+ if (DBG) log("createAllApnList: No APN found for carrier: " + operator);
mPreferredApn = null;
- notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
+ // TODO: What is the right behaviour?
+ //notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
mPreferredApn = getPreferredApn();
- log("Get PreferredAPN");
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
mPreferredApn = null;
setPreferredApn(-1);
}
+ if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
}
+ if (DBG) log("createAllApnList: X mAllApns=" + mAllApns);
}
/** Return the id for a new data connection */
- private int createDataConnection(String apnType) {
- log("createDataConnection(" + apnType + ") E");
+ private GsmDataConnection createDataConnection() {
+ if (DBG) log("createDataConnection E");
+
RetryManager rm = new RetryManager();
+ int id = mUniqueIdGenerator.getAndIncrement();
+ GsmDataConnection conn = GsmDataConnection.makeDataConnection(mPhone, id, rm);
+ mDataConnections.put(id, conn);
+ DataConnectionAc dcac = new DataConnectionAc(conn, LOG_TAG);
+ int status = dcac.fullyConnectSync(mPhone.getContext(), this, conn.getHandler());
+ if (status == AsyncChannel.STATUS_SUCCESSFUL) {
+ mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
+ } else {
+ loge("createDataConnection: Could not connect to dcac.mDc=" + dcac.dataConnection +
+ " status=" + status);
+ }
+
+ if (DBG) log("createDataConnection() X id=" + id);
+ return conn;
+ }
+
+ private void configureRetry(DataConnection dc, String apnType) {
+ if ((dc == null) || (apnType == null)) return;
if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
- if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
- if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+ if (!dc.configureRetry(SystemProperties.get("ro.gsm.data_retry_config"))) {
+ if (!dc.configureRetry(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);
+ loge("createDataConnection: Could not configure using " +
+ "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
+ dc.configureRetry(20, 2000, 1000);
}
}
} else {
- if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
- if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) {
+ if (!dc.configureRetry(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
+ if (!dc.configureRetry(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");
+ loge("createDataConnection: Could note configure using " +
+ "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
+ dc.configureRetry("max_retries=3, 333, 333, 333");
}
}
}
-
- 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 destroyDataConnections() {
if(mDataConnections != null) {
- log("destroyDataConnectionList clear mDataConnectionList");
+ if (DBG) log("destroyDataConnections: clear mDataConnectionList");
mDataConnections.clear();
} else {
- log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
+ if (DBG) log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
}
}
- private ApnSetting fetchDunApn() {
- Context c = mPhone.getContext();
- String apnData = Settings.Secure.getString(c.getContentResolver(),
- Settings.Secure.TETHER_DUN_APN);
- ApnSetting dunSetting = ApnSetting.fromString(apnData);
- if (dunSetting != null) return dunSetting;
-
- apnData = c.getResources().getString(R.string.config_tether_apndata);
- return ApnSetting.fromString(apnData);
- }
-
/**
* Build a list of APNs to be used to create PDP's.
*
@@ -1187,53 +1888,44 @@
if (requestedApnType.equals(Phone.APN_TYPE_DUN)) {
ApnSetting dun = fetchDunApn();
- if (dun != null) apnList.add(dun);
- return apnList;
+ if (dun != null) {
+ apnList.add(dun);
+ if (DBG) log("buildWaitingApns: X added APN_TYPE_DUN apnList=" + apnList);
+ return apnList;
+ }
}
- String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
-
+ String operator = mPhone.mIccRecords.getOperatorNumeric();
if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (canSetPreferApn && mPreferredApn != null) {
- log("Preferred APN:" + operator + ":"
+ if (DBG) {
+ log("buildWaitingApns: Preferred APN:" + operator + ":"
+ mPreferredApn.numeric + ":" + mPreferredApn);
+ }
if (mPreferredApn.numeric.equals(operator)) {
- log("Waiting APN set to preferred APN");
apnList.add(mPreferredApn);
+ if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
return apnList;
} else {
+ if (DBG) log("buildWaitingApns: no preferred APN");
setPreferredApn(-1);
mPreferredApn = null;
}
}
}
-
if (mAllApns != null) {
for (ApnSetting apn : mAllApns) {
if (apn.canHandleType(requestedApnType)) {
apnList.add(apn);
}
}
+ } else {
+ loge("mAllApns is empty!");
}
+ if (DBG) log("buildWaitingApns: X apnList=" + apnList);
return apnList;
}
- /**
- * Get next apn in waitingApns
- * @return the first apn found in waitingApns, null if none
- */
- private ApnSetting getNextApn() {
- ArrayList<ApnSetting> list = mWaitingApns;
- ApnSetting apn = null;
-
- if (list != null) {
- if (!list.isEmpty()) {
- apn = list.get(0);
- }
- }
- return apn;
- }
-
private String apnListToString (ArrayList<ApnSetting> apns) {
StringBuilder result = new StringBuilder();
for (int i = 0, size = apns.size(); i < size; i++) {
@@ -1244,9 +1936,9 @@
return result.toString();
}
- private void startDelayedRetry(GsmDataConnection.FailCause cause, String reason) {
- notifyNoData(cause);
- reconnectAfterFail(cause, reason);
+ private void startDelayedRetry(GsmDataConnection.FailCause cause, ApnContext apnContext) {
+ notifyNoData(cause, apnContext);
+ reconnectAfterFail(cause, apnContext);
}
private void setPreferredApn(int pos) {
@@ -1300,10 +1992,10 @@
@Override
public void handleMessage (Message msg) {
- if (DBG) log("GSMDataConnTrack handleMessage "+msg);
+ if (DBG) log("handleMessage msg=" + msg);
- if (!mGsmPhone.mIsTheCurrentActivePhone) {
- log("Ignore GSM msgs since GSM phone is inactive");
+ if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
+ loge("handleMessage: Ignore GSM msgs since GSM phone is inactive");
return;
}
@@ -1312,20 +2004,16 @@
onRecordsLoaded();
break;
- case EVENT_GPRS_DETACHED:
- onGprsDetached();
+ case EVENT_DATA_CONNECTION_DETACHED:
+ onDataConnectionDetached();
break;
- case EVENT_GPRS_ATTACHED:
- onGprsAttached();
+ case EVENT_DATA_CONNECTION_ATTACHED:
+ onDataConnectionAttached();
break;
case EVENT_DATA_STATE_CHANGED:
- onDataStateChanged((AsyncResult) msg.obj, false);
- break;
-
- case EVENT_GET_PDP_LIST_COMPLETE:
- onDataStateChanged((AsyncResult) msg.obj, true);
+ onDataStateChanged((AsyncResult) msg.obj);
break;
case EVENT_POLL_PDP:
@@ -1351,7 +2039,7 @@
* PDP context and notify us with PDP_CONTEXT_CHANGED.
* But we should stop the network polling and prevent reset PDP.
*/
- log("[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
+ if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
stopNetStatPoll();
mIsPsRestricted = true;
break;
@@ -1361,20 +2049,39 @@
* When PS restrict is removed, we need setup PDP connection if
* PDP connection is down.
*/
- log("[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+ if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
mIsPsRestricted = false;
- if (mState == State.CONNECTED) {
+ if (isConnected()) {
startNetStatPoll();
} else {
+ // TODO: Should all PDN states be checked to fail?
if (mState == State.FAILED) {
- cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
- mRetryMgr.resetRetryCount();
+ cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED);
+ resetAllRetryCounts();
mReregisterOnReconnectFailure = false;
}
- trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
+ trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, Phone.APN_TYPE_DEFAULT);
+ }
+ break;
+ case EVENT_TRY_SETUP_DATA:
+ if (msg.obj instanceof ApnContext) {
+ onTrySetupData((ApnContext)msg.obj);
+ } else if (msg.obj instanceof String) {
+ onTrySetupData((String)msg.obj);
+ } else {
+ loge("EVENT_TRY_SETUP request w/o apnContext or String");
}
break;
+ case EVENT_CLEAN_UP_CONNECTION:
+ boolean tearDown = (msg.arg1 == 0) ? false : true;
+ if (DBG) log("EVENT_CLEAN_UP_CONNECTION tearDown=" + tearDown);
+ if (msg.obj instanceof ApnContext) {
+ cleanUpConnection(tearDown, (ApnContext)msg.obj);
+ } else {
+ loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context");
+ }
+ break;
default:
// handle the message in the super class DataConnectionTracker
super.handleMessage(msg);
@@ -1382,13 +2089,44 @@
}
}
+ protected int getApnProfileID(String apnType) {
+ if (TextUtils.equals(apnType, Phone.APN_TYPE_IMS)) {
+ return RILConstants.DATA_PROFILE_IMS;
+ } else if (TextUtils.equals(apnType, Phone.APN_TYPE_FOTA)) {
+ return RILConstants.DATA_PROFILE_FOTA;
+ } else if (TextUtils.equals(apnType, Phone.APN_TYPE_CBS)) {
+ return RILConstants.DATA_PROFILE_CBS;
+ } else {
+ return RILConstants.DATA_PROFILE_DEFAULT;
+ }
+ }
+
+ private int getCellLocationId() {
+ int cid = -1;
+ CellLocation loc = mPhone.getCellLocation();
+
+ if (loc != null) {
+ if (loc instanceof GsmCellLocation) {
+ cid = ((GsmCellLocation)loc).getCid();
+ } else if (loc instanceof CdmaCellLocation) {
+ cid = ((CdmaCellLocation)loc).getBaseStationId();
+ }
+ }
+ return cid;
+ }
+
+ @Override
+ public boolean isAnyActiveDataConnections() {
+ return isConnected();
+ }
+
@Override
protected void log(String s) {
- Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+ Log.d(LOG_TAG, "[GsmDCT] "+ s);
}
@Override
protected void loge(String s) {
- Log.e(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+ Log.e(LOG_TAG, "[GsmDCT] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 2962e0f..680b3cd 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -765,7 +765,7 @@
// invalid length
handlePasswordError(com.android.internal.R.string.invalidPin);
} else if (sc.equals(SC_PIN) &&
- phone.mSimCard.getState() == SimCard.State.PUK_REQUIRED ) {
+ phone.mIccCard.getState() == SimCard.State.PUK_REQUIRED ) {
// Sim is puk-locked
handlePasswordError(com.android.internal.R.string.needPuk);
} else {
@@ -885,7 +885,7 @@
*/
if ((ar.exception == null) && (msg.arg1 == 1)) {
boolean cffEnabled = (msg.arg2 == 1);
- phone.mSIMRecords.setVoiceCallForwardingFlag(1, cffEnabled);
+ phone.mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
}
onSetComplete(ar);
@@ -1203,7 +1203,7 @@
(info.serviceClass & serviceClassMask)
== CommandsInterface.SERVICE_CLASS_VOICE) {
boolean cffEnabled = (info.status == 1);
- phone.mSIMRecords.setVoiceCallForwardingFlag(1, cffEnabled);
+ phone.mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
}
return TextUtils.replace(template, sources, destinations);
@@ -1228,7 +1228,7 @@
sb.append(context.getText(com.android.internal.R.string.serviceDisabled));
// Set unconditional CFF in SIM to false
- phone.mSIMRecords.setVoiceCallForwardingFlag(1, false);
+ phone.mIccRecords.setVoiceCallForwardingFlag(1, false);
} else {
SpannableStringBuilder tb = new SpannableStringBuilder();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index f576b4e..21a12f1 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -99,7 +99,7 @@
/** {@inheritDoc} */
@Override
- protected int dispatchMessage(SmsMessageBase smsb) {
+ public int dispatchMessage(SmsMessageBase smsb) {
// If sms is null, means there was a parsing error.
if (smsb == null) {
@@ -383,7 +383,7 @@
/** {@inheritDoc} */
@Override
- protected void activateCellBroadcastSms(int activate, Message response) {
+ public 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.");
response.recycle();
@@ -391,7 +391,7 @@
/** {@inheritDoc} */
@Override
- protected void getCellBroadcastSmsConfig(Message response){
+ public 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.");
response.recycle();
@@ -399,7 +399,7 @@
/** {@inheritDoc} */
@Override
- protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+ public 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.");
response.recycle();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index ac83808..a7631cd 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -23,6 +23,7 @@
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RestrictedState;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
@@ -75,7 +76,6 @@
GsmCellLocation cellLoc;
GsmCellLocation newCellLoc;
int mPreferredNetworkType;
- RestrictedState rs;
private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
@@ -85,12 +85,6 @@
private int mNewReasonDataDenied = -1;
/**
- * Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
- */
- private int networkType = 0;
- private int newNetworkType = 0;
-
- /**
* GSM roaming status solely based on TS 27.007 7.2 CREG. Only used by
* handlePollStateResult to store CREG roaming result.
*/
@@ -107,11 +101,6 @@
*/
private boolean mEmergencyOnly = false;
- private RegistrantList gprsAttachedRegistrants = new RegistrantList();
- private RegistrantList gprsDetachedRegistrants = new RegistrantList();
- private RegistrantList psRestrictEnabledRegistrants = new RegistrantList();
- private RegistrantList psRestrictDisabledRegistrants = new RegistrantList();
-
/**
* Sometimes we get the NITZ time before we know what country we
* are in. Keep the time zone information from the NITZ string so
@@ -169,8 +158,6 @@
static final int PS_NOTIFICATION = 888; // Id to update and cancel PS restricted
static final int CS_NOTIFICATION = 999; // Id to update and cancel CS restricted
- static final int MAX_NUM_DATA_STATE_READS = 15;
-
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -206,7 +193,6 @@
newSS = new ServiceState();
cellLoc = new GsmCellLocation();
newCellLoc = new GsmCellLocation();
- rs = new RestrictedState();
mSignalStrength = new SignalStrength();
PowerManager powerManager =
@@ -255,7 +241,7 @@
cm.unregisterForVoiceNetworkStateChanged(this);
cm.unregisterForSIMReady(this);
- phone.mSIMRecords.unregisterForRecordsLoaded(this);
+ phone.mIccRecords.unregisterForRecordsLoaded(this);
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnRestrictedStateChanged(this);
cm.unSetOnNITZTime(this);
@@ -264,7 +250,7 @@
}
protected void finalize() {
- if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");
+ if(DBG) log("finalize");
}
@Override
@@ -272,97 +258,6 @@
return phone;
}
- /**
- * Registration point for transition into GPRS attached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForGprsAttached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- gprsAttachedRegistrants.add(r);
-
- if (gprsState == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForGprsAttached(Handler h) {
- gprsAttachedRegistrants.remove(h);
- }
-
- void registerForNetworkAttach(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- networkAttachedRegistrants.add(r);
-
- if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForNetworkAttach(Handler h) {
- networkAttachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into GPRS detached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForGprsDetached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- gprsDetachedRegistrants.add(r);
-
- if (gprsState == ServiceState.STATE_OUT_OF_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForGprsDetached(Handler h) {
- gprsDetachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into packet service restricted zone.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
- Registrant r = new Registrant(h, what, obj);
- psRestrictEnabledRegistrants.add(r);
-
- if (rs.isPsRestricted()) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForPsRestrictedEnabled(Handler h) {
- psRestrictEnabledRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition out of packet service restricted zone.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
- Registrant r = new Registrant(h, what, obj);
- psRestrictDisabledRegistrants.add(r);
-
- if (rs.isPsRestricted()) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForPsRestrictedDisabled(Handler h) {
- psRestrictDisabledRegistrants.remove(h);
- }
-
public void handleMessage (Message msg) {
AsyncResult ar;
int[] ints;
@@ -380,7 +275,7 @@
// it has been unlocked. At this stage, the radio is already
// powered on.
if (mNeedToRegForSimLoaded) {
- phone.mSIMRecords.registerForRecordsLoaded(this,
+ phone.mIccRecords.registerForRecordsLoaded(this,
EVENT_SIM_RECORDS_LOADED, null);
mNeedToRegForSimLoaded = false;
}
@@ -548,7 +443,7 @@
// This is a notification from
// CommandsInterface.setOnRestrictedStateChanged
- Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_RESTRICTED_STATE_CHANGED");
+ if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED");
ar = (AsyncResult) msg.obj;
@@ -556,7 +451,7 @@
break;
default:
- Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+ super.handleMessage(msg);
break;
}
}
@@ -567,36 +462,14 @@
&& cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
cm.setRadioPower(true, null);
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
- DataConnectionTracker dcTracker = phone.mDataConnection;
- if (! dcTracker.isDataConnectionAsDesired()) {
- EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
- dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0);
- }
// If it's on and available and we want it off gracefully
- powerOffRadioSafely();
+ DataConnectionTracker dcTracker = phone.mDataConnectionTracker;
+ powerOffRadioSafely(dcTracker);
} // Otherwise, we're in the desired state
}
@Override
- protected void powerOffRadioSafely() {
- // clean data connection
- DataConnectionTracker dcTracker = phone.mDataConnection;
- Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 1; // tearDown is true
- msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
- dcTracker.sendMessage(msg);
-
- // poll data state up to 15 times, with a 100ms delay
- // totaling 1.5 sec. Normal data disable action will finish in 100ms.
- for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
- if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
- && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
- Log.d(LOG_TAG, "Data shutdown complete.");
- break;
- }
- SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
- }
-
+ protected void hangupAndPowerOff() {
// hang up all active voice calls
if (phone.isInCall()) {
phone.mCT.ringingCall.hangupIfAlive();
@@ -608,15 +481,15 @@
}
protected void updateSpnDisplay() {
- int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
- String spn = phone.mSIMRecords.getServiceProviderName();
+ int rule = phone.mIccRecords.getDisplayRule(ss.getOperatorNumeric());
+ String spn = phone.mIccRecords.getServiceProviderName();
String plmn = ss.getOperatorAlphaLong();
// For emergency calls only, pass the EmergencyCallsOnly string via EXTRA_PLMN
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 (DBG) log("updateSpnDisplay: emergency only and radio is on plmn='" + plmn + "'");
}
if (rule != curSpnRule
@@ -627,10 +500,11 @@
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 +
+ if (DBG) {
+ log(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);
@@ -674,10 +548,8 @@
return;
}
- if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
- err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
- Log.e(LOG_TAG,
- "RIL implementation has returned an error where it must succeed" +
+ if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
+ loge("RIL implementation has returned an error where it must succeed" +
ar.exception);
}
} else try {
@@ -706,7 +578,7 @@
}
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
+ loge("error parsing RegistrationState: " + ex);
}
}
@@ -746,12 +618,12 @@
mNewMaxDataCalls = Integer.parseInt(states[5]);
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing GprsRegistrationState: " + ex);
+ loge("error parsing GprsRegistrationState: " + ex);
}
}
newGPRSState = regCodeToServiceState(regState);
mDataRoaming = regCodeIsRoaming(regState);
- newNetworkType = type;
+ mNewRadioTechnology = type;
newSS.setRadioTechnology(type);
break;
@@ -771,8 +643,7 @@
}
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "Exception while polling service state. "
- + "Probably malformed RIL response.", ex);
+ loge("Exception while polling service state. Probably malformed RIL response." + ex);
}
pollingContext[0]--;
@@ -835,7 +706,7 @@
case RUIM_LOCKED_OR_ABSENT:
case NV_NOT_READY:
case NV_READY:
- Log.d(LOG_TAG, "Radio Technology Change ongoing, setting SS to off");
+ if (DBG) log("Radio Technology Change ongoing, setting SS to off");
newSS.setStateOff();
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
@@ -872,48 +743,17 @@
}
}
- private static String networkTypeToString(int type) {
- //Network Type from GPRS_REGISTRATION_STATE
- String ret = "unknown";
-
- switch (type) {
- case DATA_ACCESS_GPRS:
- ret = "GPRS";
- break;
- case DATA_ACCESS_EDGE:
- ret = "EDGE";
- break;
- case DATA_ACCESS_UMTS:
- ret = "UMTS";
- break;
- case DATA_ACCESS_HSDPA:
- ret = "HSDPA";
- break;
- case DATA_ACCESS_HSUPA:
- ret = "HSUPA";
- break;
- case DATA_ACCESS_HSPA:
- ret = "HSPA";
- break;
- default:
- Log.e(LOG_TAG, "Wrong network type: " + Integer.toString(type));
- break;
- }
-
- return ret;
- }
-
private void pollStateDone() {
if (DBG) {
- Log.d(LOG_TAG, "Poll ServiceState done: " +
+ log("Poll ServiceState done: " +
" oldSS=[" + ss + "] newSS=[" + newSS +
"] oldGprs=" + gprsState + " newData=" + newGPRSState +
" oldMaxDataCalls=" + mMaxDataCalls +
" mNewMaxDataCalls=" + mNewMaxDataCalls +
" oldReasonDataDenied=" + mReasonDataDenied +
" mNewReasonDataDenied=" + mNewReasonDataDenied +
- " oldType=" + networkTypeToString(networkType) +
- " newType=" + networkTypeToString(newNetworkType));
+ " oldType=" + ServiceState.radioTechnologyToString(mRadioTechnology) +
+ " newType=" + ServiceState.radioTechnologyToString(mNewRadioTechnology));
}
boolean hasRegistered =
@@ -932,7 +772,7 @@
gprsState == ServiceState.STATE_IN_SERVICE
&& newGPRSState != ServiceState.STATE_IN_SERVICE;
- boolean hasNetworkTypeChanged = networkType != newNetworkType;
+ boolean hasRadioTechnologyChanged = mRadioTechnology != mNewRadioTechnology;
boolean hasChanged = !newSS.equals(ss);
@@ -962,33 +802,36 @@
// Add an event log when network type switched
// TODO: we may add filtering to reduce the event logged,
// i.e. check preferred network setting, only switch to 2G, etc
- if (hasNetworkTypeChanged) {
+ if (hasRadioTechnologyChanged) {
int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
if (loc != null) cid = loc.getCid();
- EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED, cid, networkType, newNetworkType);
- Log.d(LOG_TAG,
- "RAT switched " + networkTypeToString(networkType) + " -> "
- + networkTypeToString(newNetworkType) + " at cell " + cid);
+ EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED, cid, mRadioTechnology,
+ mNewRadioTechnology);
+ if (DBG) {
+ log("RAT switched " + ServiceState.radioTechnologyToString(mRadioTechnology) +
+ " -> " + ServiceState.radioTechnologyToString(mNewRadioTechnology) +
+ " at cell " + cid);
+ }
}
gprsState = newGPRSState;
mReasonDataDenied = mNewReasonDataDenied;
mMaxDataCalls = mNewMaxDataCalls;
- networkType = newNetworkType;
+ mRadioTechnology = mNewRadioTechnology;
// this new state has been applied - forget it until we get a new new state
- newNetworkType = 0;
+ mNewRadioTechnology = 0;
newSS.setStateOutOfService(); // clean slate for next time
- if (hasNetworkTypeChanged) {
+ if (hasRadioTechnologyChanged) {
phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
- networkTypeToString(networkType));
+ ServiceState.radioTechnologyToString(mRadioTechnology));
}
if (hasRegistered) {
- networkAttachedRegistrants.notifyRegistrants();
+ mNetworkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
@@ -1010,9 +853,9 @@
iso = MccTable.countryCodeForMcc(Integer.parseInt(
operatorNumeric.substring(0,3)));
} catch ( NumberFormatException ex){
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("countryCodeForMcc error" + ex);
} catch ( StringIndexOutOfBoundsException ex) {
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("countryCodeForMcc error" + ex);
}
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso);
@@ -1065,23 +908,23 @@
}
if (hasGprsAttached) {
- gprsAttachedRegistrants.notifyRegistrants();
+ mAttachedRegistrants.notifyRegistrants();
}
if (hasGprsDetached) {
- gprsDetachedRegistrants.notifyRegistrants();
+ mDetachedRegistrants.notifyRegistrants();
}
- if (hasNetworkTypeChanged) {
- phone.notifyDataConnection();
+ if (hasRadioTechnologyChanged) {
+ phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED, Phone.APN_TYPE_ALL);
}
if (hasRoamingOn) {
- roamingOnRegistrants.notifyRegistrants();
+ mRoamingOnRegistrants.notifyRegistrants();
}
if (hasRoamingOff) {
- roamingOffRegistrants.notifyRegistrants();
+ mRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
@@ -1125,10 +968,7 @@
// Couldn't find a proper timezone. Perhaps the DST data is wrong.
guess = findTimeZone(offset, !dst, when);
}
- if (DBG) {
- Log.d(LOG_TAG, "getNitzTimeZone returning "
- + (guess == null ? guess : guess.getID()));
- }
+ if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
return guess;
}
@@ -1199,7 +1039,7 @@
lteRssnr = ints[10];
lteCqi = ints[11];
} else {
- Log.e(LOG_TAG, "Bogus signal strength response");
+ loge("Bogus signal strength response");
rssi = 99;
}
}
@@ -1226,10 +1066,9 @@
* @param ar an int value of RIL_RESTRICTED_STATE_*
*/
private void onRestrictedStateChanged(AsyncResult ar) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
RestrictedState newRs = new RestrictedState();
- Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ rs);
+ if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState);
if (ar.exception == null) {
int[] ints = (int[])ar.result;
@@ -1247,13 +1086,13 @@
(state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
}
- Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
+ if (DBG) log("onRestrictedStateChanged: new rs "+ newRs);
- if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
- psRestrictEnabledRegistrants.notifyRegistrants();
+ if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
+ mPsRestrictEnabledRegistrants.notifyRegistrants();
setNotification(PS_ENABLED);
- } else if (rs.isPsRestricted() && !newRs.isPsRestricted()) {
- psRestrictDisabledRegistrants.notifyRegistrants();
+ } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
+ mPsRestrictDisabledRegistrants.notifyRegistrants();
setNotification(PS_DISABLED);
}
@@ -1262,7 +1101,7 @@
* there are 4 x 4 combinations in current and new restricted states
* and we only need to notify when state is changed.
*/
- if (rs.isCsRestricted()) {
+ if (mRestrictedState.isCsRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
@@ -1273,7 +1112,8 @@
// remove emergency restriction
setNotification(CS_NORMAL_ENABLED);
}
- } else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
+ } else if (mRestrictedState.isCsEmergencyRestricted() &&
+ !mRestrictedState.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
@@ -1284,7 +1124,8 @@
// remove emergency restriction and enable normal restriction
setNotification(CS_NORMAL_ENABLED);
}
- } else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
+ } else if (!mRestrictedState.isCsEmergencyRestricted() &&
+ mRestrictedState.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
@@ -1308,9 +1149,9 @@
}
}
- rs = newRs;
+ mRestrictedState = newRs;
}
- Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
+ log("onRestrictedStateChanged: X rs "+ mRestrictedState);
}
/** code is registration state 0-5 from TS 27.007 7.2 */
@@ -1334,7 +1175,7 @@
return ServiceState.STATE_IN_SERVICE;
default:
- Log.w(LOG_TAG, "unexpected service state " + code);
+ loge("regCodeToServiceState: unexpected service state " + code);
return ServiceState.STATE_OUT_OF_SERVICE;
}
}
@@ -1401,12 +1242,16 @@
return gprsState;
}
+ public int getCurrentDataConnectionState() {
+ return gprsState;
+ }
+
/**
* @return true if phone is camping on a technology (eg UMTS)
* that could support voice and data simultaneously.
*/
- boolean isConcurrentVoiceAndData() {
- return (networkType >= DATA_ACCESS_UMTS);
+ public boolean isConcurrentVoiceAndDataAllowed() {
+ return (mRadioTechnology >= ServiceState.RADIO_TECHNOLOGY_UMTS);
}
/**
@@ -1450,8 +1295,9 @@
// tz is in number of quarter-hours
long start = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime +
+ if (DBG) {log("NITZ: " + nitz + "," + nitzReceiveTime +
" start=" + start + " delay=" + (start - nitzReceiveTime));
+ }
try {
/* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
@@ -1548,7 +1394,7 @@
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
- Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
+ log("NITZ: Not setting clock because gsm.ignore-nitz is set");
return;
}
@@ -1561,43 +1407,49 @@
if (millisSinceNitzReceived < 0) {
// Sanity check: something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ if (DBG) {
+ log("NITZ: not setting time, clock has rolled "
+ "backwards since NITZ time was received, "
+ nitz);
+ }
return;
}
if (millisSinceNitzReceived > Integer.MAX_VALUE) {
// If the time is this far off, something is wrong > 24 days!
- Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ if (DBG) {
+ log("NITZ: not setting time, processing has taken "
+ (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ " days");
+ }
return;
}
// Note: with range checks above, cast to int is safe
c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
- Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime()
- + " NITZ receive delay(ms): " + millisSinceNitzReceived
- + " gained(ms): "
- + (c.getTimeInMillis() - System.currentTimeMillis())
- + " from " + nitz);
+ if (DBG) {
+ log("NITZ: Setting time of day to " + c.getTime()
+ + " NITZ receive delay(ms): " + millisSinceNitzReceived
+ + " gained(ms): "
+ + (c.getTimeInMillis() - System.currentTimeMillis())
+ + " from " + nitz);
+ }
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
Log.i(LOG_TAG, "NITZ: after Setting time of day");
}
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
saveNitzTime(c.getTimeInMillis());
- if (Config.LOGV) {
+ if (DBG) {
long end = SystemClock.elapsedRealtime();
- Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ log("NITZ: end=" + end + " dur=" + (end - start));
}
} finally {
mWakeLock.release();
}
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
+ loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
}
}
@@ -1663,8 +1515,10 @@
Settings.System.AUTO_TIME, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedTime
+ if (DBG) {
+ log("Reverting to NITZ Time: mSavedTime=" + mSavedTime
+ " mSavedAtTime=" + mSavedAtTime);
+ }
if (mSavedTime != 0 && mSavedAtTime != 0) {
setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
@@ -1676,7 +1530,7 @@
Settings.System.AUTO_TIME_ZONE, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
+ if (DBG) log("Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
if (mSavedTimeZone != null) {
setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
}
@@ -1689,7 +1543,7 @@
*/
private void setNotification(int notifyType) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType);
+ if (DBG) log("setNotification: create notification " + notifyType);
Context context = phone.getContext();
mNotification = new Notification();
@@ -1726,7 +1580,7 @@
break;
}
- Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details);
+ if (DBG) log("setNotification: put notification " + title + " / " +details);
mNotification.tickerText = title;
mNotification.setLatestEventInfo(context, title, details,
mNotification.contentIntent);
@@ -1745,6 +1599,15 @@
@Override
protected void log(String s) {
- Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s);
+ Log.d(LOG_TAG, "[GsmSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[GsmSST] " + s);
+ }
+
+ private static void sloge(String s) {
+ Log.e(LOG_TAG, "[GsmSST] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 3b133da..b0bad56 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -28,6 +28,7 @@
import com.android.internal.telephony.AdnRecord;
import com.android.internal.telephony.AdnRecordCache;
import com.android.internal.telephony.AdnRecordLoader;
+import com.android.internal.telephony.BaseCommands;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccRecords;
@@ -35,6 +36,8 @@
import com.android.internal.telephony.IccVmFixedException;
import com.android.internal.telephony.IccVmNotSupportedException;
import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
import java.util.ArrayList;
@@ -42,12 +45,12 @@
/**
* {@hide}
*/
-public final class SIMRecords extends IccRecords {
- static final String LOG_TAG = "GSM";
+public class SIMRecords extends IccRecords {
+ protected static final String LOG_TAG = "GSM";
private static final boolean CRASH_RIL = false;
- private static final boolean DBG = true;
+ protected static final boolean DBG = true;
// ***** Instance Variables
@@ -58,8 +61,8 @@
// ***** Cached SIM State; cleared on channel close
- String imsi;
- boolean callForwardingEnabled;
+ private String imsi;
+ private boolean callForwardingEnabled;
/**
@@ -117,13 +120,13 @@
private static final int EVENT_SIM_READY = 1;
private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
- private static final int EVENT_GET_IMSI_DONE = 3;
- private static final int EVENT_GET_ICCID_DONE = 4;
+ protected static final int EVENT_GET_IMSI_DONE = 3;
+ protected static final int EVENT_GET_ICCID_DONE = 4;
private static final int EVENT_GET_MBI_DONE = 5;
private static final int EVENT_GET_MBDN_DONE = 6;
private static final int EVENT_GET_MWIS_DONE = 7;
private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8;
- private static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM
+ protected static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM
private static final int EVENT_GET_MSISDN_DONE = 10;
private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11;
private static final int EVENT_GET_SPN_DONE = 12;
@@ -144,6 +147,8 @@
private static final int EVENT_GET_CFIS_DONE = 32;
private static final int EVENT_GET_CSP_CPHS_DONE = 33;
+ protected static final int CSIM_EVENT_BASE = 100;
+
// Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = {
@@ -165,7 +170,7 @@
// ***** Constructor
- SIMRecords(GSMPhone p) {
+ public SIMRecords(PhoneBase p) {
super(p);
adnCache = new AdnRecordCache(phone);
@@ -178,23 +183,29 @@
// recordsToLoad is set to 0 because no requests are made yet
recordsToLoad = 0;
-
- p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+ // SIMRecord is used by CDMA+LTE mode, and SIM_READY event
+ // will be subscribed by CdmaLteServiceStateTracker.
+ if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
+ p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+ }
p.mCM.registerForOffOrNotAvailable(
this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
- p.mCM.setOnIccRefresh(this, EVENT_SIM_REFRESH, null);
+ p.mCM.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);
// Start off by setting empty state
onRadioOffOrNotAvailable();
}
+ @Override
public void dispose() {
//Unregister for all events
- phone.mCM.unregisterForSIMReady(this);
+ if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
+ phone.mCM.unregisterForSIMReady(this);
+ }
phone.mCM.unregisterForOffOrNotAvailable( this);
- phone.mCM.unSetOnIccRefresh(this);
+ phone.mCM.unregisterForIccRefresh(this);
}
protected void finalize() {
@@ -230,7 +241,10 @@
//***** Public Methods
- /** Returns null if SIM is not yet ready */
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public String getIMSI() {
return imsi;
}
@@ -364,7 +378,7 @@
countVoiceMessages = countWaiting;
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
try {
if (efMWIS != null) {
@@ -403,17 +417,25 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public boolean getVoiceCallForwardingFlag() {
return callForwardingEnabled;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void setVoiceCallForwardingFlag(int line, boolean enable) {
if (line != 1) return; // only line 1 is supported
callForwardingEnabled = enable;
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
try {
if (mEfCfis != null) {
@@ -467,11 +489,17 @@
}
}
- /** Returns the 5 or 6 digit MCC/MNC of the operator that
- * provided the SIM card. Returns null of SIM is not yet ready
+ /**
+ * {@inheritDoc}
*/
- String getSIMOperatorNumeric() {
- if (imsi == null || mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+ @Override
+ public String getOperatorNumeric() {
+ if (imsi == null) {
+ Log.d(LOG_TAG, "getOperatorNumeric: IMSI == null");
+ return null;
+ }
+ if (mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+ Log.d(LOG_TAG, "getSIMOperatorNumeric: bad mncLength");
return null;
}
@@ -518,7 +546,7 @@
imsi = null;
}
- Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxx");
+ Log.d(LOG_TAG, "IMSI: " + /* imsi.substring(0, 6) +*/ "xxxxxxx");
if (((mncLength == UNKNOWN) || (mncLength == 2)) &&
((imsi != null) && (imsi.length() >= 6))) {
@@ -547,7 +575,7 @@
// finally have both the imsi and the mncLength and can parse the imsi properly
MccTable.updateMccMncConfiguration(phone, imsi.substring(0, 3 + mncLength));
}
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_IMSI, null);
break;
@@ -702,7 +730,7 @@
countVoiceMessages = -1;
}
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
break;
case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
@@ -731,7 +759,7 @@
countVoiceMessages = 0;
}
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
}
break;
@@ -842,7 +870,7 @@
callForwardingEnabled =
((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
}
break;
@@ -1042,7 +1070,7 @@
// Refer TS 51.011 Section 10.3.46 for the content description
callForwardingEnabled = ((data[1] & 0x01) != 0);
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
break;
case EVENT_GET_CSP_CPHS_DONE:
@@ -1152,7 +1180,7 @@
System.arraycopy(ba, 1, pdu, 0, n - 1);
SmsMessage message = SmsMessage.createFromPdu(pdu);
- ((GSMPhone) phone).mSMS.dispatchMessage(message);
+ phone.mSMS.dispatchMessage(message);
}
}
@@ -1178,7 +1206,7 @@
System.arraycopy(ba, 1, pdu, 0, n - 1);
SmsMessage message = SmsMessage.createFromPdu(pdu);
- ((GSMPhone) phone).mSMS.dispatchMessage(message);
+ phone.mSMS.dispatchMessage(message);
// 3GPP TS 51.011 v5.0.0 (20011-12) 10.5.3
// 1 == "received by MS from network; message read"
@@ -1209,7 +1237,7 @@
protected void onAllRecordsLoaded() {
Log.d(LOG_TAG, "SIMRecords: record load complete");
- String operator = getSIMOperatorNumeric();
+ String operator = getOperatorNumeric();
// Some fields require more than one SIM record to set
@@ -1228,7 +1256,7 @@
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_LOADED, null);
}
@@ -1249,17 +1277,17 @@
}
}
- private void onSimReady() {
+ public void onSimReady() {
/* broadcast intent SIM_READY here so that we can make sure
READY is sent before IMSI ready
*/
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_READY, null);
fetchSimRecords();
}
- private void fetchSimRecords() {
+ protected void fetchSimRecords() {
recordsRequested = true;
IccFileHandler iccFh = phone.getIccFileHandler();
@@ -1350,7 +1378,8 @@
*
* If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
*/
- protected int getDisplayRule(String plmn) {
+ @Override
+ public int getDisplayRule(String plmn) {
int rule;
if (spn == null || spnDisplayCondition == -1) {
// EF_SPN was not found on the SIM, or not yet loaded. Just show ONS.
@@ -1377,7 +1406,7 @@
private boolean isOnMatchingPlmn(String plmn) {
if (plmn == null) return false;
- if (plmn.equals(getSIMOperatorNumeric())) {
+ if (plmn.equals(getOperatorNumeric())) {
return true;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
index 835cb29..643f709 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -19,6 +19,10 @@
import android.util.Log;
import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.TelephonyProperties;
+import android.os.SystemProperties;
/**
* {@hide}
@@ -34,17 +38,39 @@
updateStateProperty();
}
+ /**
+ * We have the Sim card for LTE on CDMA phone
+ */
+ public SimCard(PhoneBase phone, String logTag, Boolean dbg) {
+ super(phone, logTag, dbg);
+ mPhone.mCM.registerForSIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
+ mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+ mPhone.mCM.registerForSIMReady(mHandler, EVENT_ICC_READY, null);
+ updateStateProperty();
+
+ if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ mPhone.mCM.registerForNVReady(mHandler, EVENT_ICC_READY, null);
+ mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
+ }
+ }
+
@Override
public void dispose() {
+ super.dispose();
//Unregister for all events
mPhone.mCM.unregisterForSIMLockedOrAbsent(mHandler);
mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
mPhone.mCM.unregisterForSIMReady(mHandler);
+
+ if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ mPhone.mCM.unregisterForNVReady(mHandler);
+ mPhone.mCM.unregisterForIccStatusChanged(mHandler);
+ }
}
@Override
public String getServiceProviderName () {
- return ((GSMPhone)mPhone).mSIMRecords.getServiceProviderName();
+ return mPhone.mIccRecords.getServiceProviderName();
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
index feb508a..377f8f0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
@@ -32,7 +32,7 @@
public SimPhoneBookInterfaceManager(GSMPhone phone) {
super(phone);
- adnCache = phone.mSIMRecords.getAdnCache();
+ adnCache = phone.mIccRecords.getAdnCache();
//NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
index f2ece7f..5208ccd 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -326,6 +326,10 @@
public void reportStkServiceIsRunning(Message result) {
}
+ @Override
+ public void getCdmaSubscriptionSource(Message response) {
+ }
+
public void getGsmBroadcastConfig(Message response) {
}
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index d9bd7e8..80de9f3 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -1001,6 +1001,11 @@
resultSuccess(result, null);
}
+ @Override
+ public void getCdmaSubscriptionSource(Message result) {
+ unimplemented(result);
+ }
+
private boolean isSimLocked() {
if (mSimLockedState != SimLockState.NONE) {
return true;
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 3cde949..9ae26da 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -16,8 +16,8 @@
package android.net.wifi;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.net.wifi.WifiStateMachine.StateChangeResult;
import android.content.Context;
@@ -33,7 +33,7 @@
* - detect a failed WPA handshake that loops indefinitely
* - authentication failure handling
*/
-class SupplicantStateTracker extends HierarchicalStateMachine {
+class SupplicantStateTracker extends StateMachine {
private static final String TAG = "SupplicantStateTracker";
private static final boolean DBG = false;
@@ -53,14 +53,14 @@
private Context mContext;
- private HierarchicalState mUninitializedState = new UninitializedState();
- private HierarchicalState mDefaultState = new DefaultState();
- private HierarchicalState mInactiveState = new InactiveState();
- private HierarchicalState mDisconnectState = new DisconnectedState();
- private HierarchicalState mScanState = new ScanState();
- private HierarchicalState mHandshakeState = new HandshakeState();
- private HierarchicalState mCompletedState = new CompletedState();
- private HierarchicalState mDormantState = new DormantState();
+ private State mUninitializedState = new UninitializedState();
+ private State mDefaultState = new DefaultState();
+ private State mInactiveState = new InactiveState();
+ private State mDisconnectState = new DisconnectedState();
+ private State mScanState = new ScanState();
+ private State mHandshakeState = new HandshakeState();
+ private State mCompletedState = new CompletedState();
+ private State mDormantState = new DormantState();
public SupplicantStateTracker(Context context, WifiStateMachine wsm, Handler target) {
super(TAG, target.getLooper());
@@ -146,7 +146,7 @@
* HSM states
*******************************************************/
- class DefaultState extends HierarchicalState {
+ class DefaultState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -188,21 +188,21 @@
* or after we have lost the control channel
* connection to the supplicant
*/
- class UninitializedState extends HierarchicalState {
+ class UninitializedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
}
}
- class InactiveState extends HierarchicalState {
+ class InactiveState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
}
}
- class DisconnectedState extends HierarchicalState {
+ class DisconnectedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -221,14 +221,14 @@
}
}
- class ScanState extends HierarchicalState {
+ class ScanState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
}
}
- class HandshakeState extends HierarchicalState {
+ class HandshakeState extends State {
/**
* The max number of the WPA supplicant loop iterations before we
* decide that the loop should be terminated:
@@ -277,7 +277,7 @@
}
}
- class CompletedState extends HierarchicalState {
+ class CompletedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -318,7 +318,7 @@
}
//TODO: remove after getting rid of the state in supplicant
- class DormantState extends HierarchicalState {
+ class DormantState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 6455d84..d83b968 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -23,6 +23,7 @@
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.ProxyProperties;
+import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
@@ -120,7 +121,7 @@
private static final String ipConfigFile = Environment.getDataDirectory() +
"/misc/wifi/ipconfig.txt";
- private static final int IPCONFIG_FILE_VERSION = 1;
+ private static final int IPCONFIG_FILE_VERSION = 2;
/* IP and proxy configuration keys */
private static final String ID_KEY = "id";
@@ -445,9 +446,8 @@
if (iter.hasNext()) {
LinkAddress linkAddress = iter.next();
dhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress();
- Iterator<InetAddress>gateways = linkProperties.getGateways().iterator();
- if (gateways.hasNext()) {
- dhcpInfoInternal.gateway = gateways.next().getHostAddress();
+ for (RouteInfo route : linkProperties.getRoutes()) {
+ dhcpInfoInternal.addRoute(route);
}
dhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength();
Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
@@ -478,6 +478,21 @@
}
}
+ /**
+ * clear IP configuration for a given network id
+ */
+ static void clearIpConfiguration(int netId) {
+ synchronized (sConfiguredNetworks) {
+ WifiConfiguration config = sConfiguredNetworks.get(netId);
+ if (config != null && config.linkProperties != null) {
+ // Clear everything except proxy
+ ProxyProperties proxy = config.linkProperties.getHttpProxy();
+ config.linkProperties.clear();
+ config.linkProperties.setHttpProxy(proxy);
+ }
+ }
+ }
+
/**
* Fetch the proxy properties for a given network id
@@ -604,9 +619,22 @@
out.writeUTF(linkAddr.getAddress().getHostAddress());
out.writeInt(linkAddr.getNetworkPrefixLength());
}
- for (InetAddress gateway : linkProperties.getGateways()) {
+ for (RouteInfo route : linkProperties.getRoutes()) {
out.writeUTF(GATEWAY_KEY);
- out.writeUTF(gateway.getHostAddress());
+ LinkAddress dest = route.getDestination();
+ if (dest != null) {
+ out.writeInt(1);
+ out.writeUTF(dest.getAddress().getHostAddress());
+ out.writeInt(dest.getNetworkPrefixLength());
+ } else {
+ out.writeInt(0);
+ }
+ if (route.getGateway() != null) {
+ out.writeInt(1);
+ out.writeUTF(route.getGateway().getHostAddress());
+ } else {
+ out.writeInt(0);
+ }
}
for (InetAddress inetAddr : linkProperties.getDnses()) {
out.writeUTF(DNS_KEY);
@@ -682,7 +710,8 @@
in = new DataInputStream(new BufferedInputStream(new FileInputStream(
ipConfigFile)));
- if (in.readInt() != IPCONFIG_FILE_VERSION) {
+ int version = in.readInt();
+ if (version != 2 && version != 1) {
Log.e(TAG, "Bad version on IP configuration file, ignore read");
return;
}
@@ -709,8 +738,22 @@
NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
linkProperties.addLinkAddress(linkAddr);
} else if (key.equals(GATEWAY_KEY)) {
- linkProperties.addGateway(
- NetworkUtils.numericToInetAddress(in.readUTF()));
+ LinkAddress dest = null;
+ InetAddress gateway = null;
+ if (version == 1) {
+ // only supported default gateways - leave the dest/prefix empty
+ gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ } else {
+ if (in.readInt() == 1) {
+ dest = new LinkAddress(
+ NetworkUtils.numericToInetAddress(in.readUTF()),
+ in.readInt());
+ }
+ if (in.readInt() == 1) {
+ gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ }
+ }
+ linkProperties.addRoute(new RouteInfo(dest, gateway));
} else if (key.equals(DNS_KEY)) {
linkProperties.addDns(
NetworkUtils.numericToInetAddress(in.readUTF()));
@@ -1022,22 +1065,21 @@
.getLinkAddresses();
Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses();
Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses();
- Collection<InetAddress> currentGateways =
- currentConfig.linkProperties.getGateways();
- Collection<InetAddress> newGateways = newConfig.linkProperties.getGateways();
+ Collection<RouteInfo> currentRoutes = currentConfig.linkProperties.getRoutes();
+ Collection<RouteInfo> newRoutes = newConfig.linkProperties.getRoutes();
boolean linkAddressesDiffer =
(currentLinkAddresses.size() != newLinkAddresses.size()) ||
!currentLinkAddresses.containsAll(newLinkAddresses);
boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) ||
!currentDnses.containsAll(newDnses);
- boolean gatewaysDiffer = (currentGateways.size() != newGateways.size()) ||
- !currentGateways.containsAll(newGateways);
+ boolean routesDiffer = (currentRoutes.size() != newRoutes.size()) ||
+ !currentRoutes.containsAll(newRoutes);
if ((currentConfig.ipAssignment != newConfig.ipAssignment) ||
linkAddressesDiffer ||
dnsesDiffer ||
- gatewaysDiffer) {
+ routesDiffer) {
ipChanged = true;
}
break;
@@ -1112,8 +1154,8 @@
for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) {
linkProperties.addLinkAddress(linkAddr);
}
- for (InetAddress gateway : config.linkProperties.getGateways()) {
- linkProperties.addGateway(gateway);
+ for (RouteInfo route : config.linkProperties.getRoutes()) {
+ linkProperties.addRoute(route);
}
for (InetAddress dns : config.linkProperties.getDnses()) {
linkProperties.addDns(dns);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 0c0e2534..3cbf726 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -74,9 +74,9 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -90,7 +90,7 @@
*
* @hide
*/
-public class WifiStateMachine extends HierarchicalStateMachine {
+public class WifiStateMachine extends StateMachine {
private static final String TAG = "WifiStateMachine";
private static final String NETWORKTYPE = "WIFI";
@@ -364,50 +364,50 @@
private static final int SOFT_AP_RUNNING = 1;
/* Default parent state */
- private HierarchicalState mDefaultState = new DefaultState();
+ private State mDefaultState = new DefaultState();
/* Temporary initial state */
- private HierarchicalState mInitialState = new InitialState();
+ private State mInitialState = new InitialState();
/* Unloading the driver */
- private HierarchicalState mDriverUnloadingState = new DriverUnloadingState();
+ private State mDriverUnloadingState = new DriverUnloadingState();
/* Loading the driver */
- private HierarchicalState mDriverUnloadedState = new DriverUnloadedState();
+ private State mDriverUnloadedState = new DriverUnloadedState();
/* Driver load/unload failed */
- private HierarchicalState mDriverFailedState = new DriverFailedState();
+ private State mDriverFailedState = new DriverFailedState();
/* Driver loading */
- private HierarchicalState mDriverLoadingState = new DriverLoadingState();
+ private State mDriverLoadingState = new DriverLoadingState();
/* Driver loaded */
- private HierarchicalState mDriverLoadedState = new DriverLoadedState();
+ private State mDriverLoadedState = new DriverLoadedState();
/* Driver loaded, waiting for supplicant to start */
- private HierarchicalState mSupplicantStartingState = new SupplicantStartingState();
+ private State mSupplicantStartingState = new SupplicantStartingState();
/* Driver loaded and supplicant ready */
- private HierarchicalState mSupplicantStartedState = new SupplicantStartedState();
+ private State mSupplicantStartedState = new SupplicantStartedState();
/* Waiting for supplicant to stop and monitor to exit */
- private HierarchicalState mSupplicantStoppingState = new SupplicantStoppingState();
+ private State mSupplicantStoppingState = new SupplicantStoppingState();
/* Driver start issued, waiting for completed event */
- private HierarchicalState mDriverStartingState = new DriverStartingState();
+ private State mDriverStartingState = new DriverStartingState();
/* Driver started */
- private HierarchicalState mDriverStartedState = new DriverStartedState();
+ private State mDriverStartedState = new DriverStartedState();
/* Driver stopping */
- private HierarchicalState mDriverStoppingState = new DriverStoppingState();
+ private State mDriverStoppingState = new DriverStoppingState();
/* Driver stopped */
- private HierarchicalState mDriverStoppedState = new DriverStoppedState();
+ private State mDriverStoppedState = new DriverStoppedState();
/* Scan for networks, no connection will be established */
- private HierarchicalState mScanModeState = new ScanModeState();
+ private State mScanModeState = new ScanModeState();
/* Connecting to an access point */
- private HierarchicalState mConnectModeState = new ConnectModeState();
+ private State mConnectModeState = new ConnectModeState();
/* Fetching IP after network connection (assoc+auth complete) */
- private HierarchicalState mConnectingState = new ConnectingState();
+ private State mConnectingState = new ConnectingState();
/* Connected with IP addr */
- private HierarchicalState mConnectedState = new ConnectedState();
+ private State mConnectedState = new ConnectedState();
/* disconnect issued, waiting for network disconnect confirmation */
- private HierarchicalState mDisconnectingState = new DisconnectingState();
+ private State mDisconnectingState = new DisconnectingState();
/* Network is not connected, supplicant assoc+auth is not complete */
- private HierarchicalState mDisconnectedState = new DisconnectedState();
+ private State mDisconnectedState = new DisconnectedState();
/* Waiting for WPS to be completed*/
- private HierarchicalState mWaitForWpsCompletionState = new WaitForWpsCompletionState();
+ private State mWaitForWpsCompletionState = new WaitForWpsCompletionState();
/* Soft Ap is running */
- private HierarchicalState mSoftApStartedState = new SoftApStartedState();
+ private State mSoftApStartedState = new SoftApStartedState();
/**
@@ -481,7 +481,7 @@
mNetworkInfo.setIsAvailable(false);
mLinkProperties.clear();
mLastBssid = null;
- mLastNetworkId = -1;
+ mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSignalLevel = -1;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
@@ -821,11 +821,12 @@
}
public void connectNetwork(WifiConfiguration wifiConfig) {
- /* arg1 is used to indicate netId, force a netId value of -1 when
- * we are passing a configuration since the default value of
- * 0 is a valid netId
+ /* arg1 is used to indicate netId, force a netId value of
+ * WifiConfiguration.INVALID_NETWORK_ID when we are passing
+ * a configuration since the default value of 0 is a valid netId
*/
- sendMessage(obtainMessage(CMD_CONNECT_NETWORK, -1, 0, wifiConfig));
+ sendMessage(obtainMessage(CMD_CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
+ 0, wifiConfig));
}
public void saveNetwork(WifiConfiguration wifiConfig) {
@@ -1429,7 +1430,7 @@
mWifiInfo.setInetAddress(null);
mWifiInfo.setBSSID(null);
mWifiInfo.setSSID(null);
- mWifiInfo.setNetworkId(-1);
+ mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
mWifiInfo.setRssi(MIN_RSSI);
mWifiInfo.setLinkSpeed(-1);
@@ -1439,10 +1440,13 @@
/* Clear network properties */
mLinkProperties.clear();
+ /* Clear IP settings if the network used DHCP */
+ if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
+ WifiConfigStore.clearIpConfiguration(mLastNetworkId);
+ }
mLastBssid= null;
- mLastNetworkId = -1;
-
+ mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
}
void handlePreDhcpSetup() {
@@ -1674,7 +1678,7 @@
* HSM states
*******************************************************/
- class DefaultState extends HierarchicalState {
+ class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
@@ -1757,7 +1761,7 @@
}
}
- class InitialState extends HierarchicalState {
+ class InitialState extends State {
@Override
//TODO: could move logging into a common class
public void enter() {
@@ -1778,7 +1782,7 @@
}
}
- class DriverLoadingState extends HierarchicalState {
+ class DriverLoadingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1857,7 +1861,7 @@
}
}
- class DriverLoadedState extends HierarchicalState {
+ class DriverLoadedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1898,7 +1902,7 @@
}
}
- class DriverUnloadingState extends HierarchicalState {
+ class DriverUnloadingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1979,7 +1983,7 @@
}
}
- class DriverUnloadedState extends HierarchicalState {
+ class DriverUnloadedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2000,7 +2004,7 @@
}
}
- class DriverFailedState extends HierarchicalState {
+ class DriverFailedState extends State {
@Override
public void enter() {
Log.e(TAG, getName() + "\n");
@@ -2014,7 +2018,7 @@
}
- class SupplicantStartingState extends HierarchicalState {
+ class SupplicantStartingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2034,7 +2038,7 @@
mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE);
/* Initialize data structures */
mLastBssid = null;
- mLastNetworkId = -1;
+ mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSignalLevel = -1;
mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand());
@@ -2086,7 +2090,7 @@
}
}
- class SupplicantStartedState extends HierarchicalState {
+ class SupplicantStartedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2209,7 +2213,7 @@
}
}
- class SupplicantStoppingState extends HierarchicalState {
+ class SupplicantStoppingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2252,7 +2256,7 @@
}
}
- class DriverStartingState extends HierarchicalState {
+ class DriverStartingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2293,7 +2297,7 @@
}
}
- class DriverStartedState extends HierarchicalState {
+ class DriverStartedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2397,7 +2401,7 @@
}
}
- class DriverStoppingState extends HierarchicalState {
+ class DriverStoppingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2433,7 +2437,7 @@
}
}
- class DriverStoppedState extends HierarchicalState {
+ class DriverStoppedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2457,7 +2461,7 @@
}
}
- class ScanModeState extends HierarchicalState {
+ class ScanModeState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2494,7 +2498,7 @@
}
}
- class ConnectModeState extends HierarchicalState {
+ class ConnectModeState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2524,7 +2528,10 @@
// Network id is only valid when we start connecting
if (SupplicantState.isConnecting(state)) {
mWifiInfo.setNetworkId(stateChangeResult.networkId);
+ } else {
+ mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
}
+
if (state == SupplicantState.ASSOCIATING) {
/* BSSID is valid only in ASSOCIATING state */
mWifiInfo.setBSSID(stateChangeResult.BSSID);
@@ -2604,7 +2611,7 @@
}
}
- class ConnectingState extends HierarchicalState {
+ class ConnectingState extends State {
@Override
public void enter() {
@@ -2708,7 +2715,7 @@
}
}
- class ConnectedState extends HierarchicalState {
+ class ConnectedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2833,7 +2840,7 @@
}
}
- class DisconnectingState extends HierarchicalState {
+ class DisconnectingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2863,7 +2870,7 @@
}
}
- class DisconnectedState extends HierarchicalState {
+ class DisconnectedState extends State {
private boolean mAlarmEnabled = false;
private long mScanIntervalMs;
@@ -2970,7 +2977,7 @@
}
}
- class WaitForWpsCompletionState extends HierarchicalState {
+ class WaitForWpsCompletionState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -3009,7 +3016,7 @@
}
}
- class SoftApStartedState extends HierarchicalState {
+ class SoftApStartedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 07900ae..338cb4d 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -50,6 +50,7 @@
private LinkProperties mLinkProperties;
private LinkCapabilities mLinkCapabilities;
private NetworkInfo mNetworkInfo;
+ private NetworkInfo.State mLastState = NetworkInfo.State.UNKNOWN;
/* For sending events to connectivity service handler */
private Handler mCsHandler;
@@ -217,6 +218,14 @@
if (mLinkCapabilities == null) {
mLinkCapabilities = new LinkCapabilities();
}
+ // don't want to send redundent state messages
+ // TODO can this be fixed in WifiStateMachine?
+ NetworkInfo.State state = mNetworkInfo.getState();
+ if (mLastState == state) {
+ return;
+ } else {
+ mLastState = state;
+ }
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
} else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
@@ -228,4 +237,7 @@
}
}
+ public void setDependencyMet(boolean met) {
+ // not supported on this network
+ }
}
diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java
index 32d77a1..120b228 100644
--- a/wifi/java/android/net/wifi/WpsStateMachine.java
+++ b/wifi/java/android/net/wifi/WpsStateMachine.java
@@ -17,8 +17,8 @@
package android.net.wifi;
import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.content.Context;
import android.content.Intent;
@@ -46,7 +46,7 @@
* reloads the configuration and updates the IP and proxy
* settings, if any.
*/
-class WpsStateMachine extends HierarchicalStateMachine {
+class WpsStateMachine extends StateMachine {
private static final String TAG = "WpsStateMachine";
private static final boolean DBG = false;
@@ -58,9 +58,9 @@
private Context mContext;
AsyncChannel mReplyChannel = new AsyncChannel();
- private HierarchicalState mDefaultState = new DefaultState();
- private HierarchicalState mInactiveState = new InactiveState();
- private HierarchicalState mActiveState = new ActiveState();
+ private State mDefaultState = new DefaultState();
+ private State mInactiveState = new InactiveState();
+ private State mActiveState = new ActiveState();
public WpsStateMachine(Context context, WifiStateMachine wsm, Handler target) {
super(TAG, target.getLooper());
@@ -82,7 +82,7 @@
* HSM states
*******************************************************/
- class DefaultState extends HierarchicalState {
+ class DefaultState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -128,7 +128,7 @@
}
}
- class ActiveState extends HierarchicalState {
+ class ActiveState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -182,7 +182,7 @@
}
}
- class InactiveState extends HierarchicalState {
+ class InactiveState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");