am fef7b625: am 7f3cf449: Merge "docs: update screen support doc to de-emphasize support for 1.5 this includes a variety of other revisions to reorganize some of the content in the main document and also add separate documents for how to enable screen filtering and ad
* commit 'fef7b62506a74d0133b60fd1d6ae9bf54bf599c9':
docs: update screen support doc to de-emphasize support for 1.5 this includes a variety of other revisions to reorganize some of the content in the main document and also add separate documents for how to enable screen filtering and add screen support on 1.5
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 9e6bcc8..6570078 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);
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 491c73a..b541ec3 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -221,12 +221,32 @@
/** {@hide} */
public static final int TYPE_DUMMY = 8;
+
/** {@hide} */
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
new file mode 100644
index 0000000..eaf087f
--- /dev/null
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -0,0 +1,353 @@
+/*
+ * 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 com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.DhcpInfoInternal;
+import android.net.NetworkUtils;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+/**
+ * StateMachine that interacts with the native DHCP client and can talk to
+ * a controller that also needs to be a StateMachine
+ *
+ * The Dhcp state machine provides the following features:
+ * - Wakeup and renewal using the native DHCP client (which will not renew
+ * on its own when the device is in suspend state and this can lead to device
+ * holding IP address beyond expiry)
+ * - A notification right before DHCP request or renewal is started. This
+ * can be used for any additional setup before DHCP. For example, wifi sets
+ * BT-Wifi coex settings right before DHCP is initiated
+ *
+ * @hide
+ */
+public class DhcpStateMachine extends StateMachine {
+
+ private static final String TAG = "DhcpStateMachine";
+ private static final boolean DBG = false;
+
+
+ /* A StateMachine that controls the DhcpStateMachine */
+ private StateMachine mController;
+
+ private Context mContext;
+ private BroadcastReceiver mBroadcastReceiver;
+ private AlarmManager mAlarmManager;
+ private PendingIntent mDhcpRenewalIntent;
+ private PowerManager.WakeLock mDhcpRenewWakeLock;
+ private static final String WAKELOCK_TAG = "DHCP";
+
+ private static final int DHCP_RENEW = 0;
+ private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW";
+
+ private enum DhcpAction {
+ START,
+ RENEW
+ };
+
+ private String mInterfaceName;
+ private boolean mRegisteredForPreDhcpNotification = false;
+
+ private static final int BASE = Protocol.BASE_DHCP;
+
+ /* Commands from controller to start/stop DHCP */
+ public static final int CMD_START_DHCP = BASE + 1;
+ public static final int CMD_STOP_DHCP = BASE + 2;
+ public static final int CMD_RENEW_DHCP = BASE + 3;
+
+ /* Notification from DHCP state machine prior to DHCP discovery/renewal */
+ public static final int CMD_PRE_DHCP_ACTION = BASE + 4;
+ /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates
+ * success/failure */
+ public static final int CMD_POST_DHCP_ACTION = BASE + 5;
+
+ /* Command from controller to indicate DHCP discovery/renewal can continue
+ * after pre DHCP action is complete */
+ public static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 6;
+
+ /* Message.arg1 arguments to CMD_POST_DHCP notification */
+ public static final int DHCP_SUCCESS = 1;
+ public static final int DHCP_FAILURE = 2;
+
+ 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, StateMachine controller, String intf) {
+ super(TAG);
+
+ mContext = context;
+ mController = controller;
+ mInterfaceName = intf;
+
+ mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+ Intent dhcpRenewalIntent = new Intent(ACTION_DHCP_RENEW, null);
+ mDhcpRenewalIntent = PendingIntent.getBroadcast(mContext, DHCP_RENEW, dhcpRenewalIntent, 0);
+
+ PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
+
+ mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ //DHCP renew
+ if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this);
+ //acquire a 40s wakelock to finish DHCP renewal
+ mDhcpRenewWakeLock.acquire(40000);
+ sendMessage(CMD_RENEW_DHCP);
+ }
+ };
+ mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_DHCP_RENEW));
+
+ addState(mDefaultState);
+ addState(mStoppedState, mDefaultState);
+ addState(mWaitBeforeStartState, mDefaultState);
+ addState(mRunningState, mDefaultState);
+ addState(mWaitBeforeRenewalState, mDefaultState);
+
+ setInitialState(mStoppedState);
+ }
+
+ public static DhcpStateMachine makeDhcpStateMachine(Context context, StateMachine controller,
+ String intf) {
+ DhcpStateMachine dsm = new DhcpStateMachine(context, controller, intf);
+ dsm.start();
+ return dsm;
+ }
+
+ /**
+ * This sends a notification right before DHCP request/renewal so that the
+ * controller can do certain actions before DHCP packets are sent out.
+ * When the controller is ready, it sends a CMD_PRE_DHCP_ACTION_COMPLETE message
+ * to indicate DHCP can continue
+ *
+ * This is used by Wifi at this time for the purpose of doing BT-Wifi coex
+ * handling during Dhcp
+ */
+ public void registerForPreDhcpNotification() {
+ mRegisteredForPreDhcpNotification = true;
+ }
+
+ class DefaultState extends State {
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_RENEW_DHCP:
+ Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
+ break;
+ case SM_QUIT_CMD:
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ //let parent kill the state machine
+ return NOT_HANDLED;
+ default:
+ Log.e(TAG, "Error! unhandled message " + message);
+ break;
+ }
+ return HANDLED;
+ }
+ }
+
+
+ class StoppedState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_START_DHCP:
+ if (mRegisteredForPreDhcpNotification) {
+ /* Notify controller before starting DHCP */
+ mController.sendMessage(CMD_PRE_DHCP_ACTION);
+ transitionTo(mWaitBeforeStartState);
+ } else {
+ if (runDhcp(DhcpAction.START)) {
+ transitionTo(mRunningState);
+ }
+ }
+ break;
+ case CMD_STOP_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ break;
+ }
+ return retValue;
+ }
+ }
+
+ class WaitBeforeStartState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
+ if (runDhcp(DhcpAction.START)) {
+ transitionTo(mRunningState);
+ } else {
+ transitionTo(mStoppedState);
+ }
+ break;
+ case CMD_STOP_DHCP:
+ transitionTo(mStoppedState);
+ break;
+ case CMD_START_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ break;
+ }
+ return retValue;
+ }
+ }
+
+ class RunningState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_STOP_DHCP:
+ mAlarmManager.cancel(mDhcpRenewalIntent);
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
+ }
+ transitionTo(mStoppedState);
+ break;
+ case CMD_RENEW_DHCP:
+ if (mRegisteredForPreDhcpNotification) {
+ /* Notify controller before starting DHCP */
+ mController.sendMessage(CMD_PRE_DHCP_ACTION);
+ transitionTo(mWaitBeforeRenewalState);
+ } else {
+ if (!runDhcp(DhcpAction.RENEW)) {
+ transitionTo(mStoppedState);
+ }
+ }
+ break;
+ case CMD_START_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ }
+ return retValue;
+ }
+ }
+
+ class WaitBeforeRenewalState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_STOP_DHCP:
+ mAlarmManager.cancel(mDhcpRenewalIntent);
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
+ }
+ transitionTo(mStoppedState);
+ break;
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
+ if (runDhcp(DhcpAction.RENEW)) {
+ transitionTo(mRunningState);
+ } else {
+ transitionTo(mStoppedState);
+ }
+ break;
+ case CMD_START_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ break;
+ }
+ return retValue;
+ }
+ }
+
+ private boolean runDhcp(DhcpAction dhcpAction) {
+ boolean success = false;
+ DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+
+ if (dhcpAction == DhcpAction.START) {
+ Log.d(TAG, "DHCP request on " + mInterfaceName);
+ success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
+ } else if (dhcpAction == DhcpAction.RENEW) {
+ Log.d(TAG, "DHCP renewal on " + mInterfaceName);
+ success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpInfoInternal);
+ }
+
+ if (success) {
+ Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
+ //Do it a bit earlier than half the lease duration time
+ //to beat the native DHCP client and avoid extra packets
+ //48% for one hour lease time = 29 minutes
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() +
+ dhcpInfoInternal.leaseDuration * 480, //in milliseconds
+ mDhcpRenewalIntent);
+
+ mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpInfoInternal)
+ .sendToTarget();
+ } else {
+ Log.d(TAG, "DHCP failed on " + mInterfaceName + ": " +
+ NetworkUtils.getDhcpError());
+ NetworkUtils.stopDhcp(mInterfaceName);
+ mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
+ .sendToTarget();
+ }
+ return success;
+ }
+}
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..61acf2b 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,7 +67,7 @@
mIfaceName = source.getInterfaceName();
mLinkAddresses = source.getLinkAddresses();
mDnses = source.getDnses();
- mGateways = source.getGateways();
+ mRoutes = source.getRoutes();
mHttpProxy = new ProxyProperties(source.getHttpProxy());
}
}
@@ -91,7 +89,7 @@
}
public void addLinkAddress(LinkAddress address) {
- mLinkAddresses.add(address);
+ if (address != null) mLinkAddresses.add(address);
}
public Collection<LinkAddress> getLinkAddresses() {
@@ -99,18 +97,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 +122,7 @@
mIfaceName = null;
mLinkAddresses = new ArrayList<LinkAddress>();
mDnses = new ArrayList<InetAddress>();
- mGateways = new ArrayList<InetAddress>();
+ mRoutes = new ArrayList<RouteInfo>();
mHttpProxy = null;
}
@@ -141,19 +139,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 +231,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 +272,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..bb6ee0f 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;
@@ -437,7 +438,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 +494,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 +567,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 b3f3988..823d10f 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -80,6 +80,16 @@
public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);
/**
+ * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
+ * a result (either success or failure) from the daemon.
+ * @param interfaceName the name of the interface to configure
+ * @param ipInfo if the request succeeds, this object is filled in with
+ * the IP address information.
+ * @return {@code true} for success, {@code false} for failure
+ */
+ public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);
+
+ /**
* Shut down the DHCP client daemon.
* @param interfaceName the name of the interface for which the daemon
* should be stopped
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..5b10531
--- /dev/null
+++ b/core/java/android/net/RouteInfo.java
@@ -0,0 +1,162 @@
+/*
+ * 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;
+/**
+ * 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) {
+ try {
+ if ((gateway != null) && (gateway instanceof Inet4Address)) {
+ destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
+ } else {
+ destination = new LinkAddress(InetAddress.getByName("::0"), 128);
+ }
+ } catch (Exception e) {}
+ }
+ mDestination = destination;
+ mGateway = gateway;
+ mIsDefault = isDefault();
+ }
+
+ public RouteInfo(InetAddress gateway) {
+ LinkAddress destination = null;
+ try {
+ if ((gateway != null) && (gateway instanceof Inet4Address)) {
+ destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
+ } else {
+ destination = new LinkAddress(InetAddress.getByName("::0"), 128);
+ }
+ } catch (Exception e) {}
+ mDestination = destination;
+ mGateway = gateway;
+ mIsDefault = isDefault();
+ }
+
+ private boolean isDefault() {
+ boolean val = false;
+ if (mGateway != null) {
+ if (mGateway instanceof Inet4Address) {
+ val = (mDestination == null || mDestination.getNetworkPrefixLength() == 32);
+ } else {
+ val = (mDestination == null || mDestination.getNetworkPrefixLength() == 128);
+ }
+ }
+ 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());
+ }
+ }
+
+ 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];
+ }
+ };
+}
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/provider/Settings.java b/core/java/android/provider/Settings.java
index 6deb5a0..b09b44e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3688,6 +3688,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 a53c6d0..7d6e18f 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1175,10 +1175,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
new file mode 100644
index 0000000..2e7ec58
--- /dev/null
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -0,0 +1,46 @@
+/*
+ * 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.util;
+
+/**
+ * This class defines Message.what base addresses for various protocols that are recognized
+ * to be unique by any {@link com.android.internal.util.Statemachine} implementation. This
+ * allows for interaction between different StateMachine implementations without a conflict
+ * of message codes.
+ *
+ * As an example, all messages in {@link android.net.wifi.WifiStateMachine} will have message
+ * codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI +
+ * Protocol.MAX_MESSAGE
+ *
+ * {@hide}
+ */
+public class Protocol {
+ public static final int MAX_MESSAGE = 0x0000FFFF;
+
+ /** 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/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 3adf770..904eaf9 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -40,6 +40,16 @@
const char *dns2,
const char *server,
uint32_t *lease);
+
+int dhcp_do_request_renew(const char *ifname,
+ const char *ipaddr,
+ const char *gateway,
+ uint32_t *prefixLength,
+ const char *dns1,
+ const char *dns2,
+ const char *server,
+ uint32_t *lease);
+
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
char *dhcp_get_errmsg();
@@ -58,7 +68,6 @@
jclass dhcpInfoInternalClass;
jmethodID constructorId;
jfieldID ipaddress;
- jfieldID gateway;
jfieldID prefixLength;
jfieldID dns1;
jfieldID dns2;
@@ -146,7 +155,8 @@
return (jint)result;
}
-static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
+ jobject info, bool renew)
{
int result;
char ipaddr[PROPERTY_VALUE_MAX];
@@ -160,12 +170,41 @@
const char *nameStr = env->GetStringUTFChars(ifname, NULL);
if (nameStr == NULL) return (jboolean)false;
- result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease);
+ if (renew) {
+ result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
+ dns1, dns2, server, &lease);
+ } else {
+ result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
+ dns1, dns2, server, &lease);
+ }
+
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));
@@ -176,6 +215,17 @@
return (jboolean)(result == 0);
}
+static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+{
+ return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
+}
+
+static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+{
+ return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
+}
+
+
static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
{
int result;
@@ -219,6 +269,7 @@
{ "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 },
{ "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
{ "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
@@ -233,7 +284,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 9e00a7d..09a5fd41 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 2f431c4..bb31347 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/values/config.xml b/core/res/res/values/config.xml
old mode 100644
new mode 100755
index 27c7a4d..3224973
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -51,6 +51,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
@@ -143,13 +148,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
@@ -580,4 +592,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/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/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..70a78df 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;
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/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b1552a8..428c94f 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -28,11 +28,13 @@
import android.net.IConnectivityManager;
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;
@@ -189,6 +191,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 +227,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 +294,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 +317,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 +347,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 +382,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 +398,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 +416,7 @@
break;
default:
loge("Trying to create a DataStateTracker for an unknown radio type " +
- mNetAttributes[netType].mRadio);
+ mNetConfigs[netType].radio);
continue;
}
}
@@ -474,8 +463,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);
@@ -544,7 +533,7 @@
public NetworkInfo getActiveNetworkInfo() {
enforceAccessPermission();
for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- if (mNetAttributes[type] == null || !mNetAttributes[type].isDefault()) {
+ if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
continue;
}
NetworkStateTracker t = mNetTrackers[type];
@@ -590,7 +579,7 @@
public LinkProperties getActiveLinkProperties() {
enforceAccessPermission();
for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- if (mNetAttributes[type] == null || !mNetAttributes[type].isDefault()) {
+ if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
continue;
}
NetworkStateTracker t = mNetTrackers[type];
@@ -692,7 +681,7 @@
}
enforceChangePermission();
if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
- mNetAttributes[networkType] == null) {
+ mNetConfigs[networkType] == null) {
return Phone.APN_REQUEST_FAILED;
}
@@ -701,15 +690,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 +719,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 +841,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];
@@ -1015,6 +997,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 +1023,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 +1084,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 +1109,7 @@
info.getExtraInfo());
}
- if (mNetAttributes[prevNetType].isDefault()) {
+ if (mNetConfigs[prevNetType].isDefault()) {
tryFailover(prevNetType);
if (mActiveDefaultNetwork != -1) {
NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
@@ -1139,7 +1139,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 +1149,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 +1166,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 +1239,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();
@@ -1292,11 +1292,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 +1360,14 @@
handleDnsConfigurationChange(netType);
if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
- if (mNetAttributes[netType].isDefault()) {
+ if (mNetConfigs[netType].isDefault()) {
handleApplyDefaultProxy(netType);
addDefaultRoute(mNetTrackers[netType]);
} else {
addPrivateDnsRoutes(mNetTrackers[netType]);
}
} else {
- if (mNetAttributes[netType].isDefault()) {
+ if (mNetConfigs[netType].isDefault()) {
removeDefaultRoute(mNetTrackers[netType]);
} else {
removePrivateDnsRoutes(mNetTrackers[netType]);
@@ -1418,14 +1418,19 @@
if (p == null) return;
String interfaceName = p.getInterfaceName();
if (TextUtils.isEmpty(interfaceName)) return;
- for (InetAddress gateway : p.getGateways()) {
+ for (RouteInfo route : p.getRoutes()) {
- 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());
+ //TODO - handle non-default routes
+ if (route.isDefaultRoute()) {
+ InetAddress gateway = route.getGateway();
+ 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());
+ }
}
}
}
@@ -1528,7 +1533,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 +1615,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 +1662,7 @@
}
}
- private int getRestoreDefaultNetworkDelay() {
+ private int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = SystemProperties.get(
NETWORK_RESTORE_DELAY_PROP_NAME);
if(restoreDefaultNetworkDelayStr != null &&
@@ -1667,7 +1672,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 +1753,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 +1791,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 +1845,13 @@
case EVENT_APPLY_GLOBAL_HTTP_PROXY:
{
handleDeprecatedGlobalHttpProxy();
+ break;
+ }
+ case EVENT_SET_DEPENDENCY_MET:
+ {
+ boolean met = (msg.arg1 == ENABLED);
+ handleSetDependencyMet(msg.arg2, met);
+ break;
}
}
}
@@ -2184,4 +2185,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/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 5853696..9ff5233 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;
@@ -668,7 +669,7 @@
}
- 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 +695,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 +733,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 +783,7 @@
return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
}
- class InitialState extends HierarchicalState {
+ class InitialState extends State {
@Override
public void enter() {
setAvailable(true);
@@ -812,7 +813,7 @@
}
}
- class StartingState extends HierarchicalState {
+ class StartingState extends State {
@Override
public void enter() {
setAvailable(false);
@@ -870,7 +871,7 @@
}
}
- class TetheredState extends HierarchicalState {
+ class TetheredState extends State {
@Override
public void enter() {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
@@ -1034,7 +1035,7 @@
}
}
- class UnavailableState extends HierarchicalState {
+ class UnavailableState extends State {
@Override
public void enter() {
setAvailable(false);
@@ -1064,7 +1065,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
@@ -1082,14 +1083,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 +1126,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;
@@ -1440,7 +1441,7 @@
}
}
- 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..ba05837 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.
@@ -424,6 +430,15 @@
case 12:
radioTechnology = "EvDo rev. B";
break;
+ case 13:
+ radioTechnology = "eHRPD";
+ break;
+ case 14:
+ radioTechnology = "LTE";
+ break;
+ case 15:
+ radioTechnology = "HSPAP";
+ break;
default:
Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
break;
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/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
new file mode 100644
index 0000000..ce1a3b6
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -0,0 +1,215 @@
+/*
+ * 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() {
+ log("getDataConnectionAc dcac=" + mDataConnectionAc);
+ return mDataConnectionAc;
+ }
+
+ public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
+ log("setDataConnectionAc dcac=" + 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..ee9ceaf 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -34,6 +34,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 +71,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,7 +87,6 @@
protected Registrant mCatCallSetUpRegistrant;
protected Registrant mIccSmsFullRegistrant;
protected Registrant mEmergencyCallbackModeRegistrant;
- protected Registrant mIccRefreshRegistrant;
protected Registrant mRingRegistrant;
protected Registrant mRestrictedStateRegistrant;
protected Registrant mGsmBroadcastSmsRegistrant;
@@ -93,7 +97,8 @@
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 +110,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 +217,7 @@
synchronized (mStateMonitor) {
mSIMReadyRegistrants.add(r);
- if (mState.isSIMReady()) {
+ if (mSimState.isSIMReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -219,7 +236,7 @@
synchronized (mStateMonitor) {
mRUIMReadyRegistrants.add(r);
- if (mState.isRUIMReady()) {
+ if (mRuimState.isRUIMReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -238,7 +255,7 @@
synchronized (mStateMonitor) {
mNVReadyRegistrants.add(r);
- if (mState.isNVReady()) {
+ if (mNvState.isNVReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -256,7 +273,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 +291,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 +455,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 +648,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 +696,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()) {
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..96788ef 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -20,25 +20,28 @@
import android.os.Message;
import android.os.Handler;
+import android.os.SystemProperties;
/**
* {@hide}
*/
public interface CommandsInterface {
+ static final boolean LTE_AVAILABLE_ON_CDMA =
+ SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false);
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 +53,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 +79,25 @@
}
public boolean isGsm() {
- return this == SIM_NOT_READY
- || this == SIM_LOCKED_OR_ABSENT
- || this == SIM_READY;
+ if (LTE_AVAILABLE_ON_CDMA) {
+ 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 (LTE_AVAILABLE_ON_CDMA) {
+ 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 +172,9 @@
//***** Methods
RadioState getRadioState();
+ RadioState getSimState();
+ RadioState getRuimState();
+ RadioState getNvState();
/**
* Fires on any RadioState transition
@@ -330,14 +352,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 +606,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 +1457,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:
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..0188cf1 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -17,27 +17,29 @@
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.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 +57,13 @@
*
* 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 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 +80,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;
}
/**
@@ -208,21 +179,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();
@@ -244,10 +216,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 +247,8 @@
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;
}
}
if (phone.mCM.getRadioState().isOn()) {
@@ -333,30 +304,171 @@
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);
+ }
+
+ private AtomicInteger mRefCount = new AtomicInteger(0);
+
+ /**
+ * Set refCount.
+ *
+ * @param val is new refCount
+ */
+ public void setRefCount(int val) {
+ mRefCount.set(val);
+ }
+
+ /**
+ * Get refCount
+ *
+ * @return refCount
+ */
+ public int getRefCount() {
+ return mRefCount.get();
+ }
+
+ /**
+ * @return decrement and return refCount
+ *
+ * TODO: Consider using the refCount for defining the
+ * life time of a connection. When this goes zero the
+ * DataConnection could tear itself down.
+ */
+ public int decAndGetRefCount() {
+ int v = mRefCount.decrementAndGet();
+ if (v < 0) {
+ log("BUG: decAndGetRefCount caused refCount to be < 0");
+ mRefCount.set(0);
+ }
+ return v;
+ }
+
+ /**
+ * @return increment and return refCount
+ */
+ public int incAndGetRefCount() {
+ return mRefCount.incrementAndGet();
+ }
+
+ /*
+ * **************************************************************************
+ * 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;
mLinkProperties = new LinkProperties();
+ mApn = null;
}
/**
@@ -365,10 +477,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,166 +491,127 @@
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 + ".";
+ // Check if system property dns usable
+ boolean okToUseSystemPropertyDns = false;
+ cid = response.cid;
+ 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);
- 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;
+ // set link properties based on data call response
+ result = response.setLinkProperties(mLinkProperties,
+ okToUseSystemPropertyDns);
}
- if (DBG) {
- log("onSetupConnectionCompleted: DataConnection setup result='"
- + result + "' on cid=" + cid);
- if (result == SetupResult.SUCCESS) {
- log("onSetupConnectionCompleted: LinkProperties: " + mLinkProperties.toString());
- }
- }
return result;
}
/**
* 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) {
+ 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);
+ 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: {
+ log("CMD_CHANNEL_DISCONNECT");
+ mAc.disconnect();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ log("CMD_CHANNEL_DISCONNECTED");
+ mAc = null;
+ break;
+ }
+ case DataConnectionAc.REQ_IS_INACTIVE: {
+ boolean val = getCurrentState() == mInactiveState;
+ log("REQ_IS_INACTIVE isInactive=" + val);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_IS_INACTIVE, val ? 1 : 0);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_CID: {
+ log("REQ_GET_CID cid=" + cid);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, cid);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_APNSETTING: {
+ 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);
+ 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;
+ 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_GET_LINK_CAPABILITIES: {
+ LinkCapabilities lc = new LinkCapabilities(mCapabilities);
+ log("REQ_GET_LINK_CAPABILITIES linkCapabilities" + lc);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_CAPABILITIES, lc);
+ break;
+ }
+ case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
+ Bundle data = msg.getData();
+ mLinkProperties = (LinkProperties) data.get("linkProperties");
+ break;
+ }
+ case DataConnectionAc.REQ_RESET:
+ if (DBG) log("DcDefaultState: msg.what=REQ_RESET");
+ clearSettings();
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
transitionTo(mInactiveState);
break;
@@ -553,6 +626,20 @@
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);
@@ -560,7 +647,7 @@
break;
}
- return true;
+ return HANDLED;
}
}
private DcDefaultState mDefaultState = new DcDefaultState();
@@ -568,7 +655,7 @@
/**
* 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;
@@ -584,7 +671,8 @@
mDisconnectParams = dp;
}
- @Override protected void enter() {
+ @Override
+ public void enter() {
mTag += 1;
/**
@@ -604,25 +692,25 @@
}
}
- @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:
@@ -631,12 +719,12 @@
cp.tag = mTag;
onConnect(cp);
transitionTo(mActivatingState);
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -647,8 +735,9 @@
/**
* 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;
@@ -657,7 +746,7 @@
case EVENT_DISCONNECT:
if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
deferMessage(msg);
- retVal = true;
+ retVal = HANDLED;
break;
case EVENT_SETUP_DATA_CONNECTION_DONE:
@@ -666,7 +755,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 +789,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 +816,12 @@
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -743,7 +832,7 @@
/**
* 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;
@@ -767,13 +856,15 @@
}
}
- @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) {
@@ -783,12 +874,12 @@
dp.tag = mTag;
tearDownData(dp);
transitionTo(mDisconnectingState);
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -799,8 +890,9 @@
/**
* 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) {
@@ -817,12 +909,12 @@
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;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -833,8 +925,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,7 +951,7 @@
" stale dp.tag=" + cp.tag + ", mTag=" + mTag);
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
@@ -866,7 +959,7 @@
log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+ msg.what);
}
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -878,143 +971,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..a9796dd
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -0,0 +1,288 @@
+/*
+ * 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 = true;
+ 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 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 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 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 {
+ if (DBG) 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..43f3b95 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -22,24 +22,29 @@
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.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 +92,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 +134,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 +206,19 @@
// 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;
+
// member variables
protected PhoneBase mPhone;
protected Activity mActivity = Activity.NONE;
@@ -206,9 +233,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 +245,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 +253,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 +260,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();
@@ -261,15 +303,8 @@
startNetStatPoll();
} else if (action.equals(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 +318,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 +373,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;
@@ -320,6 +394,11 @@
}
public void dispose() {
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ dcac.disconnect();
+ }
+ mDataConnectionAsyncChannels.clear();
+ mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
@@ -333,36 +412,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 +445,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 +454,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 +463,7 @@
Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
if (mPhone.getServiceState().getRoaming()) {
if (enabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
}
sendMessage(obtainMessage(EVENT_ROAMING_ON));
}
@@ -429,10 +480,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 +500,23 @@
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();
+ 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 +531,7 @@
case EVENT_ROAMING_OFF:
if (getDataOnRoamingEnabled() == false) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
}
onRoamingOff();
break;
@@ -498,28 +566,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 +623,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 +634,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 +657,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 +684,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++) {
@@ -681,36 +750,12 @@
notifyOffApnsOfAvailability(reason, isDataPossible());
}
- /**
- * 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 +835,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 +846,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 +854,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 +869,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 +906,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,17 +948,25 @@
}
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 boolean isAnyActiveDataConnections() {
+ // TODO: Remember if there are any connected or
+ // loop asking each DC/APN?
+ return true;
}
protected void onSetDataEnabled(boolean 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);
+ onCleanUpConnection(true, APN_DEFAULT_ID, 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/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index e270ce9..dbfc0d4 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -28,6 +28,7 @@
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.CommandsInterface.RadioState;
+import android.os.SystemProperties;
/**
* {@hide}
@@ -85,6 +86,9 @@
private static final int EVENT_QUERY_FACILITY_FDN_DONE = 10;
private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 11;
+ static final boolean LTE_AVAILABLE_ON_CDMA =
+ SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false);
+
/*
UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
PIN_REQUIRED state, the query for ICC status returns UNKNOWN before it
@@ -426,6 +430,9 @@
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED,
INTENT_VALUE_LOCKED_NETWORK);
}
+ if (oldState != State.READY && newState == State.READY && LTE_AVAILABLE_ON_CDMA) {
+ mPhone.mSIMRecords.onSimReady();
+ }
}
/**
@@ -612,14 +619,16 @@
currentRadioState == RadioState.SIM_NOT_READY ||
currentRadioState == RadioState.RUIM_NOT_READY ||
currentRadioState == RadioState.NV_NOT_READY ||
- currentRadioState == RadioState.NV_READY) {
+ (currentRadioState == RadioState.NV_READY && !LTE_AVAILABLE_ON_CDMA)) {
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 && LTE_AVAILABLE_ON_CDMA)) {
+
int index;
diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java
index 9f60a6c..4cf21ee 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);
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index b12d2d4..b40f945 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -58,6 +58,13 @@
static final int EF_CST = 0x6f32;
static final int EF_RUIM_SPN =0x6F41;
+ //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 +74,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/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java
index c0bf7ec..fde1b59 100644
--- a/telephony/java/com/android/internal/telephony/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/MccTable.java
@@ -322,7 +322,7 @@
table.add(new MccEntry(289,"ge",2)); //Abkhazia (Georgia)
table.add(new MccEntry(290,"gl",2)); //Greenland (Denmark)
table.add(new MccEntry(292,"sm",2)); //San Marino (Republic of)
- table.add(new MccEntry(293,"sl",2)); //Slovenia (Republic of)
+ table.add(new MccEntry(293,"si",2)); //Slovenia (Republic of)
table.add(new MccEntry(294,"mk",2)); //The Former Yugoslav Republic of Macedonia
table.add(new MccEntry(295,"li",2)); //Liechtenstein (Principality of)
table.add(new MccEntry(297,"me",2)); //Montenegro (Republic of)
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index acb86d4..b99f39b 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -125,6 +125,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 +138,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 +149,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 +159,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 +174,9 @@
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";
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
@@ -193,6 +206,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 +333,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 +1250,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 +1368,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();
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 54341b1..5a77da7 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 SIMRecords mSIMRecords;
+ public SimCard mSimCard;
+ 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;
}
}
@@ -662,6 +668,20 @@
}
/**
+ * Retrieves the ServiceStateTracker of the phone instance.
+ */
+ public ServiceStateTracker getServiceStateTracker() {
+ return null;
+ }
+
+ /**
+ * Get call tracker
+ */
+ public CallTracker getCallTracker() {
+ return null;
+ }
+
+ /**
* Query the status of the CDMA roaming preference
*/
public void queryCdmaRoamingPreference(Message response) {
@@ -954,31 +974,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 ((mDataConnectionTracker != null) && (mDataConnectionTracker.isDataPossible()));
+ }
+
+ public boolean isDataConnectivityPossible(String apnType) {
+ return ((mDataConnectionTracker != null) &&
+ (mDataConnectionTracker.isDataPossible(apnType)));
}
/**
@@ -1008,7 +1033,7 @@
break;
}
- mDataConnection.setState(dcState);
+ mDataConnectionTracker.setState(dcState);
notifyDataConnection(null, Phone.APN_TYPE_DEFAULT);
}
@@ -1080,4 +1105,14 @@
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);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 2e391cb..a04623f 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,9 @@
static final String LOG_TAG = "PHONE";
static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
static final int SOCKET_OPEN_MAX_RETRY = 3;
+ static final boolean LTE_AVAILABLE_ON_CDMA =
+ SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false);
+
//***** Class Variables
static private Phone sProxyPhone = null;
@@ -101,10 +106,32 @@
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 = SystemProperties.getInt(
+ TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, -1);
+ switch (lteOnCdma) {
+ case 0:
+ cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_NV;
+ Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
+ break;
+ case 1:
+ cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_RUIM;
+ Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
+ break;
+ case -1:
+ 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 +142,15 @@
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));
+ if (LTE_AVAILABLE_ON_CDMA == false ) {
+ Log.i(LOG_TAG, "Creating CDMAPhone");
+ sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ } else {
+ Log.i(LOG_TAG, "Creating CDMALTEPhone");
+ sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ }
}
sMadeDefaults = true;
@@ -145,8 +178,19 @@
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 (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA,
+ false)) {
+ return Phone.PHONE_TYPE_CDMA;
+ } else {
+ return Phone.PHONE_TYPE_GSM;
+ }
default:
return Phone.PHONE_TYPE_GSM;
}
@@ -166,8 +210,13 @@
public static Phone getCdmaPhone() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
- Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
- return phone;
+ if (LTE_AVAILABLE_ON_CDMA == false) {
+ Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
+ return phone;
+ } else {
+ Phone phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier);
+ return phone;
+ }
}
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 15b23bb..a3fc25d 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();
}
@@ -661,6 +657,10 @@
return mActivePhone.isDataConnectivityPossible();
}
+ public boolean isDataConnectivityPossible(String apnType) {
+ return mActivePhone.isDataConnectivityPossible(apnType);
+ }
+
public String getDeviceId() {
return mActivePhone.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);
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 804ace4..242a322 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,17 +602,15 @@
}} 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) {
super(context);
@@ -638,6 +632,14 @@
case RILConstants.NETWORK_MODE_GLOBAL:
mPhoneType = RILConstants.CDMA_PHONE;
break;
+ case RILConstants.NETWORK_MODE_LTE_ONLY:
+ if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA,
+ false)) {
+ mPhoneType = RILConstants.CDMA_PHONE;
+ } else {
+ mPhoneType = RILConstants.GSM_PHONE;
+ }
+ break;
default:
mPhoneType = RILConstants.CDMA_PHONE;
}
@@ -904,10 +906,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 +1384,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);
}
@@ -2053,25 +2030,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);
}
/**
@@ -2361,7 +2320,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 +2420,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 +2602,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 +2728,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 +2754,30 @@
new AsyncResult (null, null, null));
}
break;
+
+ case RIL_UNSOL_RIL_CONNECTED: {
+ if (RILJ_LOGD) unsljLogRet(response, ret);
+
+ // Initial conditions
+ setRadioPower(false, null);
+ setPreferredNetworkType(mNetworkMode, 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));
}
}
@@ -3038,7 +3025,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 +3034,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();
@@ -3525,9 +3513,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>";
}
}
@@ -3627,12 +3616,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..2a27926 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 */
@@ -138,10 +143,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 +286,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..695805c 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;
@@ -74,9 +60,17 @@
*/
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 +80,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 +155,6 @@
protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
public ServiceStateTracker() {
-
}
public boolean getDesiredPowerState() {
@@ -180,7 +171,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 +179,7 @@
}
public void unregisterForRoamingOn(Handler h) {
- roamingOnRegistrants.remove(h);
+ mRoamingOnRegistrants.remove(h);
}
/**
@@ -201,7 +192,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 +200,7 @@
}
public void unregisterForRoamingOff(Handler h) {
- roamingOffRegistrants.remove(h);
+ mRoamingOffRegistrants.remove(h);
}
/**
@@ -272,20 +263,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..4927006 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -72,6 +72,11 @@
*/
static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
+ /** 'true' if device supports both LTE and CDMA mode of operation.
+ * Availability: Set only on devices supporting LTE and CDMA.
+ */
+ static final String PROPERTY_NETWORK_LTE_ON_CDMA = "telephony.lte_on_cdma";
+
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..2f3b177 100644
--- a/telephony/java/com/android/internal/telephony/cat/CatService.java
+++ b/telephony/java/com/android/internal/telephony/cat/CatService.java
@@ -118,6 +118,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 +135,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 +173,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");
}
@@ -373,25 +378,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 +525,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 +591,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/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..e45141a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -0,0 +1,174 @@
+/*
+ * 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);
+ log("CDMALTEPhone Constructors");
+ }
+
+ public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+ boolean unitTestMode) {
+ super(context, ci, notifier, false);
+
+ mSIMRecords = new SIMRecords(this);
+ mSimCard = new SimCard(this, LOG_TAG, DBG);
+ }
+
+ @Override
+ protected void initSST() {
+ mSST = new CdmaLteServiceStateTracker(this);
+ }
+
+ public void dispose() {
+ synchronized (PhoneProxy.lockForRadioTechnologyChange) {
+ super.dispose();
+ mSIMRecords.dispose();
+ mSimCard.dispose();
+ }
+ }
+
+ @Override
+ public void removeReferences() {
+ super.removeReferences();
+ this.mSIMRecords = null;
+ this.mSimCard = null;
+ }
+
+ @Override
+ public ServiceStateTracker getServiceStateTracker() {
+ return mSST;
+ }
+
+ public IccCard getIccCard() {
+ return mSimCard;
+ }
+
+ @Override
+ public String getIccSerialNumber() {
+ return mSIMRecords.iccid;
+ }
+
+ @Override
+ public DataState getDataConnectionState(String apnType) {
+ boolean isCdmaDataConnectionTracker = false;
+ if (mDataConnectionTracker instanceof CdmaDataConnectionTracker) {
+ isCdmaDataConnectionTracker = true;
+ }
+ log("getDataConnectionState");
+ DataState ret = DataState.DISCONNECTED;
+
+ if (!isCdmaDataConnectionTracker && (SystemProperties.get("adb.connected", "").length()
+ > 0)) {
+ // We're connected to an ADB host and we have USB networking
+ // turned on. No matter what the radio state is,
+ // we report data connected
+
+ ret = DataState.CONNECTED;
+ } else if (mSST == null) {
+ // Radio Technology Change is ongoning, dispose() and
+ // removeReferences() have
+ // already been called
+
+ ret = DataState.DISCONNECTED;
+ } else if (mSST.getCurrentCdmaDataConnectionState() != 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 (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;
+ }
+ }
+
+ return ret;
+ }
+
+ public boolean updateCurrentCarrierInProvider() {
+ if (mSIMRecords != null) {
+ try {
+ Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
+ ContentValues map = new ContentValues();
+ map.put(Telephony.Carriers.NUMERIC, mSIMRecords.getSIMOperatorNumeric());
+ mContext.getContentResolver().insert(uri, map);
+ return true;
+ } catch (SQLException e) {
+ Log.e(LOG_TAG, "[CDMALTEPhone] Can't store current operator", e);
+ }
+ }
+ return false;
+ }
+
+ public String getActiveApn(String apnType) {
+ return mDataConnectionTracker.getActiveApnString(apnType);
+ }
+
+ 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..152ffd5 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -66,6 +66,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,7 +98,6 @@
// Instance Variables
CdmaCallTracker mCT;
- CdmaSMSDispatcher mSMS;
CdmaServiceStateTracker mSST;
RuimRecords mRuimRecords;
RuimCard mRuimCard;
@@ -141,20 +141,29 @@
// Constructors
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
- this(context,ci,notifier, false);
+ super(notifier, context, ci, false);
+ initSST();
+ init(context, notifier);
}
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
super(notifier, context, ci, unitTestMode);
+ initSST();
+ init(context, notifier);
+ }
+ protected void initSST() {
+ mSST = new CdmaServiceStateTracker(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);
+ mDataConnectionTracker = new CdmaDataConnectionTracker (this);
mRuimCard = new RuimCard(this);
mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
@@ -168,7 +177,7 @@
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);
@@ -220,7 +229,7 @@
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,7 +237,7 @@
//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
@@ -250,7 +259,7 @@
this.mRuimRecords = null;
this.mIccFileHandler = null;
this.mRuimCard = null;
- this.mDataConnection = null;
+ this.mDataConnectionTracker = null;
this.mCT = null;
this.mSST = null;
this.mEriManager = null;
@@ -270,10 +279,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";
}
@@ -321,7 +338,7 @@
if (mSST.getCurrentCdmaDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
- switch (mDataConnection.getActivity()) {
+ switch (mDataConnectionTracker.getActivity()) {
case DATAIN:
ret = DataActivityState.DATAIN;
break;
@@ -547,7 +564,7 @@
}
public void setDataRoamingEnabled(boolean enable) {
- mDataConnection.setDataOnRoamingEnabled(enable);
+ mDataConnectionTracker.setDataOnRoamingEnabled(enable);
}
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
@@ -612,11 +629,11 @@
// 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 +642,7 @@
case CONNECTED:
case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData()) {
+ && !mSST.isConcurrentVoiceAndDataAllowed()) {
ret = DataState.SUSPENDED;
} else {
ret = DataState.CONNECTED;
@@ -707,11 +724,7 @@
}
public boolean getDataRoamingEnabled() {
- return mDataConnection.getDataOnRoamingEnabled();
- }
-
- public List<DataConnection> getCurrentDataConnectionList () {
- return mDataConnection.getAllDataConnections();
+ return mDataConnectionTracker.getDataOnRoamingEnabled();
}
public void setVoiceMailNumber(String alphaTag,
@@ -912,7 +925,7 @@
// send an Intent
sendEmergencyCallbackModeChange();
// Re-initiate data connection
- mDataConnection.setInternalDataEnabled(true);
+ mDataConnectionTracker.setInternalDataEnabled(true);
}
}
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..f325812 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;
@@ -104,8 +103,8 @@
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,6 +117,8 @@
@Override
public void dispose() {
+ cleanUpConnection(false, null);
+
super.dispose();
// Unregister from all events
@@ -128,8 +129,8 @@
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,30 +173,6 @@
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();
@@ -200,9 +182,9 @@
boolean allowed =
(psState == ServiceState.STATE_IN_SERVICE ||
mAutoAttachOnCreation) &&
- (mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+ (mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
- (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+ (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 ||
+ if (!(mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
mCdmaPhone.mRuimRecords.getRecordsLoaded())) {
- reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded";
+ 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,36 @@
return allowed;
}
+ /**
+ * 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.
+ */
+ @Override
+ 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;
+ }
+
+ @Override
+ protected boolean isDataPossible(String apnType) {
+ return isDataPossible();
+ }
+
+
private boolean trySetupData(String reason) {
if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
@@ -262,9 +274,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 +296,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 +322,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 +354,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 +370,7 @@
setState(State.CONNECTED);
notifyDataConnection(reason);
startNetStatPoll();
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
}
private void resetPollStats() {
@@ -386,7 +402,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,7 +520,7 @@
* at the last time until the state is changed.
* TODO: Make this configurable?
*/
- int nextReconnectDelay = mRetryMgr.getRetryTimer();
+ int nextReconnectDelay = mDataConnections.get(0).getRetryTimer();
log("Data Connection activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
@@ -518,7 +534,7 @@
SystemClock.elapsedRealtime() + nextReconnectDelay,
mReconnectIntent);
- mRetryMgr.increaseRetryCount();
+ mDataConnections.get(0).increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
log("NOT Posting Data Connection Unavailable notification "
@@ -534,7 +550,7 @@
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 +559,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 +576,7 @@
*/
@Override
protected void onEnableNewApn() {
+ // No mRequestedApnType check; only one connection is supported
cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
}
@@ -588,7 +605,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 +626,7 @@
notifyDataAvailability(null);
if (mState != State.IDLE) {
- cleanUpConnection(true, null);
+ cleanUpAllConnections(null);
}
}
@@ -618,7 +635,7 @@
*/
@Override
protected void onRadioOffOrNotAvailable() {
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
@@ -626,7 +643,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 +657,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 +701,17 @@
notifyDataConnection(reason);
mActiveApn = null;
if (retryAfterDisconnected(reason)) {
- trySetupData(reason);
+ // Wait a bit before trying, so we're not tying up RIL command channel.
+ sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason), APN_DELAY_MILLIS);
}
}
/**
- * 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 +724,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 +733,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 +795,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 +813,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 +909,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 +950,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..32c5d75
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -0,0 +1,473 @@
+/*
+ * 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.DataConnectionTracker;
+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.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.AsyncResult;
+import android.os.Message;
+
+import android.util.Log;
+import android.util.EventLog;
+
+import com.android.internal.telephony.RestrictedState;
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
+ static final String LOG_TAG = "CDMA";
+
+ CDMALTEPhone mCdmaLtePhone;
+
+ private ServiceState mLteSS; // The last LTE state from Voice Registration
+
+ public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
+ super(phone);
+ mCdmaLtePhone = phone;
+
+ mLteSS = new ServiceState();
+ if (DBG) log("CdmaLteServiceStateTracker Constructors");
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+ int[] ints;
+ String[] strings;
+ if (msg.what == EVENT_POLL_STATE_GPRS) {
+ if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS");
+ ar = (AsyncResult)msg.obj;
+ handlePollStateResult(msg.what, ar);
+ } else {
+ 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);
+ }
+ }
+
+ // Not sure if this is needed in CDMALTE phone.
+ // mDataRoaming = regCodeIsRoaming(regState);
+ 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;
+ }
+ }
+
+ protected static String networkTypeToString(int type) {
+ String ret = "unknown";
+
+ switch (type) {
+ case ServiceState.RADIO_TECHNOLOGY_IS95A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95B:
+ ret = "CDMA";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_1xRTT:
+ ret = "CDMA - 1xRTT";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
+ ret = "CDMA - EvDo rev. 0";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
+ ret = "CDMA - EvDo rev. A";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_B:
+ ret = "CDMA - EvDo rev. B";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_LTE:
+ ret = "LTE";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EHRPD:
+ ret = "CDMA - eHRPD";
+ break;
+ default:
+ sloge("networkTypeToString: Wrong network, can not return a string.");
+ break;
+ }
+ return ret;
+ }
+
+ @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 + "]");
+
+ 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 + " hasCdmaDataConnectionAttached = "
+ + hasCdmaDataConnectionAttached + " hasCdmaDataConnectionChanged = "
+ + hasCdmaDataConnectionChanged + " hasNetworkTypeChanged = "
+ + hasNetworkTypeChanged + " 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();
+
+ // TODO: 4G Tech Handoff
+ // if (has4gHandoff) {
+ // Message msg = phone.mDataConnectionTracker.obtainMessage(
+ // DataConnectionTracker.EVENT_4G_TECHNOLOGY_CHANGE);
+ // phone.mDataConnectionTracker.sendMessage(msg);
+ // }
+
+ 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((CDMAPhone)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,
+ networkTypeToString(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.setCdmaEriText(eriText);
+ }
+
+ 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.mDataConnectionTracker instanceof CdmaDataConnectionTracker)) {
+ phone.notifyDataConnection();
+ }
+
+ if (hasRoamingOn) {
+ mRoamingOnRegistrants.notifyRegistrants();
+ }
+
+ if (hasRoamingOff) {
+ mRoamingOffRegistrants.notifyRegistrants();
+ }
+
+ if (hasLocationChanged) {
+ phone.notifyLocationChanged();
+ }
+ }
+
+ 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");
+ }
+ }
+
+ 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;
+ }
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+
+ protected static void sloge(String s) {
+ Log.e(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+}
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..afebebe 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;
@@ -143,8 +139,6 @@
private boolean isEriTextLoaded = false;
private boolean isSubscriptionFromRuim = false;
- private boolean mPendingRadioPowerOffAfterDataOff = 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();
}
};
@@ -223,8 +217,8 @@
phone.mRuimRecords.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
@@ -401,7 +344,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);
}
}
@@ -435,11 +378,11 @@
try {
mHomeSystemId[i] = Integer.parseInt(sid[i]);
} catch (NumberFormatException ex) {
- Log.e(LOG_TAG, "error parsing system id: ", ex);
+ loge("error parsing system id: " + ex);
}
}
}
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION SID=" + cdmaSubscription[1] );
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: SID=" + cdmaSubscription[1] );
if (cdmaSubscription[2] != null) {
String[] nid = cdmaSubscription[2].split(",");
@@ -448,14 +391,14 @@
try {
mHomeNetworkId[i] = Integer.parseInt(nid[i]);
} catch (NumberFormatException ex) {
- Log.e(LOG_TAG, "error parsing network id: ", ex);
+ loge("GET_CDMA_SUBSCRIPTION: error parsing network id: " + ex);
}
}
}
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION NID=" + cdmaSubscription[2] );
+ if (DBG) log("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;
@@ -465,19 +408,23 @@
// Notify apps subscription info is ready
if (cdmaForSubscriptionInfoReadyRegistrants != null) {
- Log.d(LOG_TAG, "call cdmaForSubscriptionInfoReady.notifyRegistrants()");
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: call notifyRegistrants()");
cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
}
if (oldOtaspMode != mCurrentOtaspMode) {
- Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" +
+ if (DBG) {
+ log("GET_CDMA_SUBSCRIPTION: call notifyOtaspChanged old otaspMode=" +
oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
+ }
phone.notifyOtaspChanged(mCurrentOtaspMode);
}
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 +479,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 +502,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 +526,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 +548,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 +728,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 +804,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 +816,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 +843,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,29 +871,29 @@
}
}
- private static String networkTypeToString(int type) {
+ protected static String networkTypeToString(int type) {
String ret = "unknown";
switch (type) {
- case DATA_ACCESS_CDMA_IS95A:
- case DATA_ACCESS_CDMA_IS95B:
+ case ServiceState.RADIO_TECHNOLOGY_IS95A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95B:
ret = "CDMA";
break;
- case DATA_ACCESS_CDMA_1xRTT:
+ case ServiceState.RADIO_TECHNOLOGY_1xRTT:
ret = "CDMA - 1xRTT";
break;
- case DATA_ACCESS_CDMA_EvDo_0:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
ret = "CDMA - EvDo rev. 0";
break;
- case DATA_ACCESS_CDMA_EvDo_A:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
ret = "CDMA - EvDo rev. A";
break;
- case DATA_ACCESS_CDMA_EvDo_B:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_B:
ret = "CDMA - EvDo rev. B";
break;
default:
if (DBG) {
- Log.e(LOG_TAG, "Wrong network. Can not return a string.");
+ slog("Wrong network. Can not return a string.");
}
break;
}
@@ -994,7 +901,7 @@
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 +938,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 +950,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 +972,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 +989,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;
@@ -1095,7 +1002,7 @@
}
if (hasRegistered) {
- networkAttachedRegistrants.notifyRegistrants();
+ mNetworkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
@@ -1129,9 +1036,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 +1057,11 @@
}
if (hasCdmaDataConnectionAttached) {
- cdmaDataConnectionAttachedRegistrants.notifyRegistrants();
+ mAttachedRegistrants.notifyRegistrants();
}
if (hasCdmaDataConnectionDetached) {
- cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
+ mDetachedRegistrants.notifyRegistrants();
}
if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
@@ -1162,11 +1069,11 @@
}
if (hasRoamingOn) {
- roamingOnRegistrants.notifyRegistrants();
+ mRoamingOnRegistrants.notifyRegistrants();
}
if (hasRoamingOff) {
- roamingOffRegistrants.notifyRegistrants();
+ mRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
@@ -1234,7 +1141,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 +1160,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 +1186,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,7 +1212,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;
}
}
@@ -1315,7 +1223,14 @@
* ServiceState.RADIO_TECHNOLOGY_UNKNOWN is the same as detached.
*/
/*package*/ int getCurrentCdmaDataConnectionState() {
- return cdmaDataConnectionState;
+ return mDataConnectionState;
+ }
+
+ /**
+ * TODO: In the future, we need remove getCurrentCdmaDataConnectionState
+ */
+ public int getCurrentDataConnectionState() {
+ return mDataConnectionState;
}
/**
@@ -1388,8 +1303,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 +1403,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 +1418,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 +1452,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 +1471,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 +1539,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,7 +1553,7 @@
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);
}
@@ -1662,7 +1588,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 +1633,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 +1649,30 @@
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);
}
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[CdmaSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaSST] " + s);
+ }
+
+ private static void slog(String s) {
+ Log.d(LOG_TAG, "[CdmaSST] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index 87b0c60..a6fd966 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -87,7 +87,7 @@
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();
@@ -98,7 +98,7 @@
//Unregister for all events
phone.mCM.unregisterForRUIMReady(this);
phone.mCM.unregisterForOffOrNotAvailable( this);
- phone.mCM.unSetOnIccRefresh(this);
+ phone.mCM.unregisterForIccRefresh(this);
}
@Override
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..b137ca7 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;
@@ -144,7 +143,7 @@
mSMS = new GsmSMSDispatcher(this);
mIccFileHandler = new SIMFileHandler(this);
mSIMRecords = new SIMRecords(this);
- mDataConnection = new GsmDataConnectionTracker (this);
+ mDataConnectionTracker = new GsmDataConnectionTracker (this);
mSimCard = new SimCard(this);
if (!unitTestMode) {
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
@@ -160,7 +159,7 @@
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 {
@@ -210,7 +209,7 @@
mSIMRecords.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,7 +218,7 @@
//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();
@@ -240,7 +239,7 @@
this.mSIMRecords = null;
this.mIccFileHandler = null;
this.mSimCard = null;
- this.mDataConnection = null;
+ this.mDataConnectionTracker = null;
this.mCT = null;
this.mSST = null;
}
@@ -283,6 +282,14 @@
return mSIMRecords.getVoiceCallForwardingFlag();
}
+ public CallTracker getCallTracker() {
+ return mCT;
+ }
+
+ public ServiceStateTracker getServiceStateTracker() {
+ return mSST;
+ }
+
public List<? extends MmiCode>
getPendingMmiCodes() {
return mPendingMMIs;
@@ -301,11 +308,11 @@
// 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 { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
- switch (mDataConnection.getState()) {
+ switch (mDataConnectionTracker.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
@@ -314,7 +321,7 @@
case CONNECTED:
case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData()) {
+ && !mSST.isConcurrentVoiceAndDataAllowed()) {
ret = DataState.SUSPENDED;
} else {
ret = DataState.CONNECTED;
@@ -336,7 +343,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 +411,7 @@
mNotifier.notifySignalStrength(this);
}
- /*package*/ void
+ public void
notifyDataConnectionFailed(String reason, String apnType) {
mNotifier.notifyDataConnectionFailed(this, reason, apnType);
}
@@ -1062,10 +1069,6 @@
mCM.getDataCallList(response);
}
- public List<DataConnection> getCurrentDataConnectionList () {
- return mDataConnection.getAllDataConnections();
- }
-
public void updateServiceLocation() {
mSST.enableSingleLocationUpdate();
}
@@ -1079,11 +1082,11 @@
}
public boolean getDataRoamingEnabled() {
- return mDataConnection.getDataOnRoamingEnabled();
+ return mDataConnectionTracker.getDataOnRoamingEnabled();
}
public void setDataRoamingEnabled(boolean enable) {
- mDataConnection.setDataOnRoamingEnabled(enable);
+ mDataConnectionTracker.setDataOnRoamingEnabled(enable);
}
/**
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..3d7fc54 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.SharedPreferences;
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,62 @@
// call reRegisterNetwork, or pingTest succeeds.
private int mPdpResetCount = 0;
- /** Delay between APN attempts */
- protected static final int APN_DELAY_MILLIS = 5000;
-
- //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) {
+ Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 0; // tearDown is false
+ msg.obj = (ApnContext)apnContext;
+ sendMessage(msg);
+ }
+ 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.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 +165,90 @@
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.mSIMRecords.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);
+ }
+
+ /**
+ * 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.
+ * TODO - do per-apn notifications of availability using dependencyMet values.
+ */
+ @Override
+ protected boolean isDataPossible() {
+ boolean possible = (isDataAllowed()
+ && !(getAnyDataEnabled() && (getOverallState() == State.FAILED)));
+ if (!possible && DBG && isDataAllowed()) {
+ if (DBG) log("Data not possible. No coverage: dataState = " + getOverallState());
+ }
+ return possible;
+ }
+
+ @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,41 +258,257 @@
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() {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+ boolean defaultEnabled = !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
+ // 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
@@ -249,41 +527,62 @@
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() &&
+ gprsState == ServiceState.STATE_IN_SERVICE &&
+ mPhone.mSIMRecords.getRecordsLoaded() &&
mPhone.getState() == Phone.State.IDLE &&
mInternalDataEnabled &&
(!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
@@ -291,10 +590,10 @@
desiredPowerState;
if (!allowed && DBG) {
String reason = "";
- if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
+ if (!(gprsState == ServiceState.STATE_IN_SERVICE)) {
reason += " - gprs= " + gprsState;
}
- if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
+ if (!mPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
if (mPhone.getState() != Phone.State.IDLE) {
reason += " - PhoneState= " + mPhone.getState();
}
@@ -304,99 +603,238 @@
}
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));
+ /**
+ * Release the apnContext
+ *
+ * @param apnContext
+ * @param tearDown
+ * @return refCount
+ */
+ private int releaseApnContext(ApnContext apnContext, boolean tearDown) {
+ if (apnContext == null) {
+ if (DBG) loge("releaseApnContext: apnContext null should not happen, ignore");
+ return -1;
+ }
+ DataConnection dc = apnContext.getDataConnection();
+ if (dc == null) {
+ if (DBG) loge("releaseApnContext: apnContext dc == null should not happen, ignore");
+ return -1;
+ }
+ int refCount = dc.decAndGetRefCount();
+ if (DBG) log("releaseApnContext: dec refCount=" + refCount + " tearDown=" + tearDown);
+ if (tearDown && (refCount == 0)) {
+ if (DBG) log("releaseApnContext: tearing down");
+ Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+ apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+ }
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+ return refCount;
+ }
- log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+ private void setupDataOnReadyApns(String reason) {
+ // Only check for default APN state
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ if (apnContext.getState() == State.FAILED) {
+ cleanUpConnection(false, 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);
+ }
+ }
+ }
+ }
+
+ 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());
+ }
// 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);
+ if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
+ if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
+ return;
+ }
- boolean notificationDeferred = false;
- for (DataConnection conn : mDataConnections.values()) {
+ if (apnContext.getState() == State.FAILED) {
+ if (DBG) log("cleanUpConnection: state is in FAILED");
+ apnContext.setState(State.IDLE);
+ return;
+ }
+
+ DataConnection conn = apnContext.getDataConnection();
+ if (conn != null) {
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
+ apnContext.setState(State.DISCONNECTING);
if (tearDown) {
- if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
- conn.getDataConnectionId(), 0, reason));
- notificationDeferred = true;
+ releaseApnContext(apnContext, tearDown);
} else {
- if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
- conn.resetSynchronously();
- notificationDeferred = false;
+ if (dcac != null) {
+ dcac.resetSync();
+ }
+ apnContext.setState(State.IDLE);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
}
}
- stopNetStatPoll();
-
- if (!notificationDeferred) {
- if (DBG) log("cleanupConnection: !notificationDeferred");
- gotoIdleAndNotifyDataConnection(reason);
- }
}
+
/**
* @param types comma delimited list of APN types
* @return array of APN types
@@ -439,41 +877,94 @@
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) {
+
+ 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;
+ }
+
+ 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;
}
- mActiveApn = apn;
- mPendingDataConnection = gdc;
+
+ dc.setProfileId( profileId );
+ dc.setActiveApnType(apnContext.getApnType());
+ int refCount = dc.incAndGetRefCount();
+ if (DBG) log("setupData: init dc and apnContext refCount=" + refCount);
+
+ // configure retry count if no other Apn is using the same connection.
+ if (refCount == 1) {
+ configureRetry(dc, apnContext.getApnType());
+ }
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId());
+ 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;
}
@@ -498,24 +989,25 @@
* 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);
}
}
@@ -525,76 +1017,97 @@
* via an unsolicited response (which could have happened at any
* previous state
*/
- 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) {
+ for (ApnContext apnContext : mApnContexts.values()) {
+ onDataStateChanged(dataCallStates, apnContext);
+ }
+ if (DBG) log("onDataStateChanged(ar) X");
+ }
+
+ private void onDataStateChanged (ArrayList<DataCallState> dataCallStates,
+ ApnContext apnContext) {
+ if (DBG) log("onDataStateChanged(dataCallState, apnContext): apnContext=" + apnContext);
+
+ if (apnContext == null) {
+ // Should not happen
+ if (DBG) log("onDataStateChanged(dataCallState, apnContext): ignore apnContext=null");
+ return;
+ }
+
+ 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 deactivated one.
- if (!dataCallStatesHasCID(dataCallStates, mCidActive)) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ if (DBG) log("onDataStateChanged(dataCallState, apnContext): dcac==null BAD NEWS");
+ return;
+ }
+ int cid = dcac.getCidSync();
+ if (!dataCallStatesHasCID(dataCallStates, cid)) {
// It looks like the PDP context has deactivated.
// Tear everything down and try to reconnect.
- log("PDP connection has dropped. Reconnecting");
-
+ if (DBG) {
+ log("onDataStateChanged(dataCallStates,apnContext) " +
+ "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,
+ int cellLocationId = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
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.
+ cleanUpConnection(true, apnContext);
+ } else if (!dataCallStatesHasActiveCID(dataCallStates,
+ apnContext.getDataConnectionAc().getCidSync())) {
- 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);
+ if (DBG) {
+ log("onDataStateChanged(dataCallStates,apnContext) " +
+ "PDP connection has dropped (active=false case). Reconnecting");
}
+
+ // Log the network drop on the event log.
+ int cellLocationId = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
+ TelephonyManager.getDefault().getNetworkType());
+
+ cleanUpConnection(true, apnContext);
}
}
}
- 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 +1121,32 @@
}
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);
+ if (DBG) log("doRecovery() re-register getting preferred network type");
+ mPhone.getServiceStateTracker().reRegisterNetwork(null);
}
// 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 +1157,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
@@ -726,8 +1243,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,7 +1253,7 @@
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();
sendMessage(obtainMessage(EVENT_START_RECOVERY));
@@ -784,122 +1301,220 @@
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) {
+ 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 "
+ int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+ if (DBG) {
+ log("reconnectAfterFail: 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);
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
+ // Should put an extra of apn type?
+ 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() + nextReconnectDelay,
- mReconnectIntent);
+ apnContext.getReconnectIntent());
- mRetryMgr.increaseRetryCount();
+ 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 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);
+ }
+ DataConnection conn = checkForConnectionForApnContext(apnContext);
+ if (conn == null) {
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ }
+ trySetup = true;
+ } else {
+ int refCount = conn.incAndGetRefCount();
+ apnContext.setDataConnection(conn);
+ apnContext.setDataConnectionAc(
+ mDataConnectionAsyncChannels.get(conn.getDataConnectionId()));
+ if (DBG) {
+ log("applyNewState: Found existing connection for " +
+ apnContext.getApnType() + " inc refCount=" + refCount +
+ " conn=" + conn);
+ }
+ }
+ }
}
+ 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.mSIMRecords.getRecordsLoaded()) {
+ notifyDataAvailability(null);
+ }
+
+ if (getOverallState() != State.IDLE) {
cleanUpConnection(true, null);
}
}
@@ -908,72 +1523,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) + " refCount=" + dc.getRefCount());
+ }
+ 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 +1604,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());
} 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);
+ sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext),
+ APN_DELAY_MILLIS);
+ }
+
+ int refCount = releaseApnContext(apnContext, false);
+ if (DBG) {
+ log("onDataSetupComplete: error apn=%s" + apnString + " refCount=" + refCount);
}
}
}
@@ -1019,43 +1653,53 @@
*/
@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);
+
+ 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.
+ sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext),APN_DELAY_MILLIS);
+ }
}
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 +1707,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 +1718,37 @@
}
} 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));
+ 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 +1757,10 @@
*/
private void createAllApnList() {
mAllApns = new ArrayList<ApnSetting>();
- String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
-
+ String operator = mPhone.mSIMRecords.getSIMOperatorNumeric();
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 +1774,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.
*
@@ -1188,52 +1856,41 @@
if (requestedApnType.equals(Phone.APN_TYPE_DUN)) {
ApnSetting dun = fetchDunApn();
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.mSIMRecords.getSIMOperatorNumeric();
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 +1901,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 +1957,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 +1969,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 +2004,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 +2014,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 +2054,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/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..72cc666 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,7 +85,7 @@
private int mNewReasonDataDenied = -1;
/**
- * Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
+ * Values correspond to ServiceState.RADIO_TECHNOLOGY_ definitions.
*/
private int networkType = 0;
private int newNetworkType = 0;
@@ -107,11 +107,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 +164,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 +199,6 @@
newSS = new ServiceState();
cellLoc = new GsmCellLocation();
newCellLoc = new GsmCellLocation();
- rs = new RestrictedState();
mSignalStrength = new SignalStrength();
PowerManager powerManager =
@@ -264,7 +256,7 @@
}
protected void finalize() {
- if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");
+ if(DBG) log("finalize");
}
@Override
@@ -272,97 +264,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;
@@ -548,7 +449,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 +457,7 @@
break;
default:
- Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+ super.handleMessage(msg);
break;
}
}
@@ -567,36 +468,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();
@@ -616,7 +495,7 @@
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 +506,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 +554,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 +584,7 @@
}
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
+ loge("error parsing RegistrationState: " + ex);
}
}
@@ -746,7 +624,7 @@
mNewMaxDataCalls = Integer.parseInt(states[5]);
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing GprsRegistrationState: " + ex);
+ loge("error parsing GprsRegistrationState: " + ex);
}
}
newGPRSState = regCodeToServiceState(regState);
@@ -771,8 +649,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 +712,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();
@@ -877,26 +754,26 @@
String ret = "unknown";
switch (type) {
- case DATA_ACCESS_GPRS:
+ case ServiceState.RADIO_TECHNOLOGY_GPRS:
ret = "GPRS";
break;
- case DATA_ACCESS_EDGE:
+ case ServiceState.RADIO_TECHNOLOGY_EDGE:
ret = "EDGE";
break;
- case DATA_ACCESS_UMTS:
+ case ServiceState.RADIO_TECHNOLOGY_UMTS:
ret = "UMTS";
break;
- case DATA_ACCESS_HSDPA:
+ case ServiceState.RADIO_TECHNOLOGY_HSDPA:
ret = "HSDPA";
break;
- case DATA_ACCESS_HSUPA:
+ case ServiceState.RADIO_TECHNOLOGY_HSUPA:
ret = "HSUPA";
break;
- case DATA_ACCESS_HSPA:
+ case ServiceState.RADIO_TECHNOLOGY_HSPA:
ret = "HSPA";
break;
default:
- Log.e(LOG_TAG, "Wrong network type: " + Integer.toString(type));
+ sloge("Wrong network type: " + Integer.toString(type));
break;
}
@@ -905,7 +782,7 @@
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 +
@@ -967,9 +844,10 @@
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) + " -> "
+ if (DBG) {
+ log("RAT switched " + networkTypeToString(networkType) + " -> "
+ networkTypeToString(newNetworkType) + " at cell " + cid);
+ }
}
gprsState = newGPRSState;
@@ -988,7 +866,7 @@
}
if (hasRegistered) {
- networkAttachedRegistrants.notifyRegistrants();
+ mNetworkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
@@ -1010,9 +888,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 +943,23 @@
}
if (hasGprsAttached) {
- gprsAttachedRegistrants.notifyRegistrants();
+ mAttachedRegistrants.notifyRegistrants();
}
if (hasGprsDetached) {
- gprsDetachedRegistrants.notifyRegistrants();
+ mDetachedRegistrants.notifyRegistrants();
}
if (hasNetworkTypeChanged) {
- phone.notifyDataConnection();
+ 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 +1003,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 +1074,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 +1101,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 +1121,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 +1136,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 +1147,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 +1159,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 +1184,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 +1210,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 +1277,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 (networkType >= ServiceState.RADIO_TECHNOLOGY_UMTS);
}
/**
@@ -1450,8 +1330,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 +1429,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 +1442,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 +1550,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 +1565,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 +1578,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 +1615,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 +1634,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..7fb250f 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -35,6 +35,7 @@
import com.android.internal.telephony.IccVmFixedException;
import com.android.internal.telephony.IccVmNotSupportedException;
import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.PhoneBase;
import java.util.ArrayList;
@@ -165,7 +166,7 @@
// ***** Constructor
- SIMRecords(GSMPhone p) {
+ public SIMRecords(PhoneBase p) {
super(p);
adnCache = new AdnRecordCache(phone);
@@ -183,7 +184,7 @@
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();
@@ -194,7 +195,7 @@
//Unregister for all events
phone.mCM.unregisterForSIMReady(this);
phone.mCM.unregisterForOffOrNotAvailable( this);
- phone.mCM.unSetOnIccRefresh(this);
+ phone.mCM.unregisterForIccRefresh(this);
}
protected void finalize() {
@@ -364,7 +365,7 @@
countVoiceMessages = countWaiting;
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
try {
if (efMWIS != null) {
@@ -413,7 +414,7 @@
callForwardingEnabled = enable;
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
try {
if (mEfCfis != null) {
@@ -470,11 +471,22 @@
/** Returns the 5 or 6 digit MCC/MNC of the operator that
* provided the SIM card. Returns null of SIM is not yet ready
*/
- String getSIMOperatorNumeric() {
- if (imsi == null || mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+ public String getSIMOperatorNumeric() {
+ if (imsi == null) {
+ Log.d(LOG_TAG, "getSIMOperatorNumeric: IMSI == null");
+ return null;
+ }
+ if (mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+ Log.d(LOG_TAG, "getSIMOperatorNumeric: bad mncLength");
return null;
}
+ // STOPSHIP: to be removed
+ if (SystemProperties.getInt(com.android.internal.telephony.TelephonyProperties
+ .PROPERTY_NETWORK_LTE_ON_CDMA, 0) == 1) {
+ Log.e(LOG_TAG, "getSIMOperatorNumeric: STOPSHIP bad numeric operators in lte");
+ return SystemProperties.get("ro.cdma.home.operator.numeric", "310004");
+ }
// Length = length of MCC + length of MNC
// length of mcc = 3 (TS 23.003 Section 2.2)
return imsi.substring(0, 3 + mncLength);
@@ -518,7 +530,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 +559,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.mSimCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_IMSI, null);
break;
@@ -702,7 +714,7 @@
countVoiceMessages = -1;
}
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
break;
case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
@@ -731,7 +743,7 @@
countVoiceMessages = 0;
}
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
}
break;
@@ -842,7 +854,7 @@
callForwardingEnabled =
((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
}
break;
@@ -1042,7 +1054,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 +1164,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 +1190,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"
@@ -1228,7 +1240,7 @@
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mSimCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_LOADED, null);
}
@@ -1249,11 +1261,11 @@
}
}
- 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.mSimCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_READY, null);
fetchSimRecords();
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
index 835cb29..781746c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -19,6 +19,9 @@
import android.util.Log;
import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.TelephonyProperties;
+import android.os.SystemProperties;
/**
* {@hide}
@@ -34,6 +37,21 @@
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(SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false)) {
+ mPhone.mCM.registerForNVReady(mHandler, EVENT_ICC_READY, null);
+ }
+ }
+
@Override
public void dispose() {
//Unregister for all events
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..7f9fc31 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();
@@ -604,9 +604,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 +695,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 +723,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 +1050,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 +1139,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 4346b327..a6b1a2c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -48,6 +48,7 @@
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.DhcpInfoInternal;
+import android.net.DhcpStateMachine;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -73,8 +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;
@@ -88,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";
@@ -151,6 +153,7 @@
private NetworkInfo mNetworkInfo;
private SupplicantStateTracker mSupplicantStateTracker;
private WpsStateMachine mWpsStateMachine;
+ private DhcpStateMachine mDhcpStateMachine;
private AlarmManager mAlarmManager;
private PendingIntent mScanIntent;
@@ -165,95 +168,97 @@
private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022;
private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023;
+ /* The base for wifi message types */
+ static final int BASE = Protocol.BASE_WIFI;
/* Load the driver */
- static final int CMD_LOAD_DRIVER = 1;
+ static final int CMD_LOAD_DRIVER = BASE + 1;
/* Unload the driver */
- static final int CMD_UNLOAD_DRIVER = 2;
+ static final int CMD_UNLOAD_DRIVER = BASE + 2;
/* Indicates driver load succeeded */
- static final int CMD_LOAD_DRIVER_SUCCESS = 3;
+ static final int CMD_LOAD_DRIVER_SUCCESS = BASE + 3;
/* Indicates driver load failed */
- static final int CMD_LOAD_DRIVER_FAILURE = 4;
+ static final int CMD_LOAD_DRIVER_FAILURE = BASE + 4;
/* Indicates driver unload succeeded */
- static final int CMD_UNLOAD_DRIVER_SUCCESS = 5;
+ static final int CMD_UNLOAD_DRIVER_SUCCESS = BASE + 5;
/* Indicates driver unload failed */
- static final int CMD_UNLOAD_DRIVER_FAILURE = 6;
+ static final int CMD_UNLOAD_DRIVER_FAILURE = BASE + 6;
/* Start the supplicant */
- static final int CMD_START_SUPPLICANT = 11;
+ static final int CMD_START_SUPPLICANT = BASE + 11;
/* Stop the supplicant */
- static final int CMD_STOP_SUPPLICANT = 12;
+ static final int CMD_STOP_SUPPLICANT = BASE + 12;
/* Start the driver */
- static final int CMD_START_DRIVER = 13;
+ static final int CMD_START_DRIVER = BASE + 13;
/* Start the driver */
- static final int CMD_STOP_DRIVER = 14;
- /* Indicates DHCP succeded */
- static final int CMD_IP_CONFIG_SUCCESS = 15;
- /* Indicates DHCP failed */
- static final int CMD_IP_CONFIG_FAILURE = 16;
+ static final int CMD_STOP_DRIVER = BASE + 14;
+ /* Indicates Static IP succeded */
+ static final int CMD_STATIC_IP_SUCCESS = BASE + 15;
+ /* Indicates Static IP failed */
+ static final int CMD_STATIC_IP_FAILURE = BASE + 16;
/* Start the soft access point */
- static final int CMD_START_AP = 21;
+ static final int CMD_START_AP = BASE + 21;
/* Stop the soft access point */
- static final int CMD_STOP_AP = 22;
+ static final int CMD_STOP_AP = BASE + 22;
- static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = 23;
+ static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 23;
/* Supplicant events */
/* Connection to supplicant established */
- static final int SUP_CONNECTION_EVENT = 31;
+ static final int SUP_CONNECTION_EVENT = BASE + 31;
/* Connection to supplicant lost */
- static final int SUP_DISCONNECTION_EVENT = 32;
+ static final int SUP_DISCONNECTION_EVENT = BASE + 32;
/* Driver start completed */
- static final int DRIVER_START_EVENT = 33;
+ static final int DRIVER_START_EVENT = BASE + 33;
/* Driver stop completed */
- static final int DRIVER_STOP_EVENT = 34;
+ static final int DRIVER_STOP_EVENT = BASE + 34;
/* Network connection completed */
- static final int NETWORK_CONNECTION_EVENT = 36;
+ static final int NETWORK_CONNECTION_EVENT = BASE + 36;
/* Network disconnection completed */
- static final int NETWORK_DISCONNECTION_EVENT = 37;
+ static final int NETWORK_DISCONNECTION_EVENT = BASE + 37;
/* Scan results are available */
- static final int SCAN_RESULTS_EVENT = 38;
+ static final int SCAN_RESULTS_EVENT = BASE + 38;
/* Supplicate state changed */
- static final int SUPPLICANT_STATE_CHANGE_EVENT = 39;
+ static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 39;
/* Password failure and EAP authentication failure */
- static final int AUTHENTICATION_FAILURE_EVENT = 40;
+ static final int AUTHENTICATION_FAILURE_EVENT = BASE + 40;
/* WPS overlap detected */
- static final int WPS_OVERLAP_EVENT = 41;
+ static final int WPS_OVERLAP_EVENT = BASE + 41;
/* Supplicant commands */
/* Is supplicant alive ? */
- static final int CMD_PING_SUPPLICANT = 51;
+ static final int CMD_PING_SUPPLICANT = BASE + 51;
/* Add/update a network configuration */
- static final int CMD_ADD_OR_UPDATE_NETWORK = 52;
+ static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52;
/* Delete a network */
- static final int CMD_REMOVE_NETWORK = 53;
+ static final int CMD_REMOVE_NETWORK = BASE + 53;
/* Enable a network. The device will attempt a connection to the given network. */
- static final int CMD_ENABLE_NETWORK = 54;
+ static final int CMD_ENABLE_NETWORK = BASE + 54;
/* Enable all networks */
- static final int CMD_ENABLE_ALL_NETWORKS = 55;
+ static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55;
/* Disable a network. The device does not attempt a connection to the given network. */
- static final int CMD_DISABLE_NETWORK = 56;
+ static final int CMD_DISABLE_NETWORK = BASE + 56;
/* Blacklist network. De-prioritizes the given BSSID for connection. */
- static final int CMD_BLACKLIST_NETWORK = 57;
+ static final int CMD_BLACKLIST_NETWORK = BASE + 57;
/* Clear the blacklist network list */
- static final int CMD_CLEAR_BLACKLIST = 58;
+ static final int CMD_CLEAR_BLACKLIST = BASE + 58;
/* Save configuration */
- static final int CMD_SAVE_CONFIG = 59;
+ static final int CMD_SAVE_CONFIG = BASE + 59;
/* Supplicant commands after driver start*/
/* Initiate a scan */
- static final int CMD_START_SCAN = 71;
+ static final int CMD_START_SCAN = BASE + 71;
/* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */
- static final int CMD_SET_SCAN_MODE = 72;
+ static final int CMD_SET_SCAN_MODE = BASE + 72;
/* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */
- static final int CMD_SET_SCAN_TYPE = 73;
+ static final int CMD_SET_SCAN_TYPE = BASE + 73;
/* Disconnect from a network */
- static final int CMD_DISCONNECT = 74;
+ static final int CMD_DISCONNECT = BASE + 74;
/* Reconnect to a network */
- static final int CMD_RECONNECT = 75;
+ static final int CMD_RECONNECT = BASE + 75;
/* Reassociate to a network */
- static final int CMD_REASSOCIATE = 76;
+ static final int CMD_REASSOCIATE = BASE + 76;
/* Controls power mode and suspend mode optimizations
*
* When high perf mode is enabled, power mode is set to
@@ -267,19 +272,19 @@
* - turn off roaming
* - DTIM wake up settings
*/
- static final int CMD_SET_HIGH_PERF_MODE = 77;
+ static final int CMD_SET_HIGH_PERF_MODE = BASE + 77;
/* Set the country code */
- static final int CMD_SET_COUNTRY_CODE = 80;
+ static final int CMD_SET_COUNTRY_CODE = BASE + 80;
/* Request connectivity manager wake lock before driver stop */
- static final int CMD_REQUEST_CM_WAKELOCK = 81;
+ static final int CMD_REQUEST_CM_WAKELOCK = BASE + 81;
/* Enables RSSI poll */
- static final int CMD_ENABLE_RSSI_POLL = 82;
+ static final int CMD_ENABLE_RSSI_POLL = BASE + 82;
/* RSSI poll */
- static final int CMD_RSSI_POLL = 83;
+ static final int CMD_RSSI_POLL = BASE + 83;
/* Set up packet filtering */
- static final int CMD_START_PACKET_FILTERING = 84;
+ static final int CMD_START_PACKET_FILTERING = BASE + 84;
/* Clear packet filter */
- static final int CMD_STOP_PACKET_FILTERING = 85;
+ static final int CMD_STOP_PACKET_FILTERING = BASE + 85;
/* Connect to a specified network (network id
* or WifiConfiguration) This involves increasing
* the priority of the network, enabling the network
@@ -288,33 +293,33 @@
* an existing network. All the networks get enabled
* upon a successful connection or a failure.
*/
- static final int CMD_CONNECT_NETWORK = 86;
+ static final int CMD_CONNECT_NETWORK = BASE + 86;
/* Save the specified network. This involves adding
* an enabled network (if new) and updating the
* config and issuing a save on supplicant config.
*/
- static final int CMD_SAVE_NETWORK = 87;
+ static final int CMD_SAVE_NETWORK = BASE + 87;
/* Delete the specified network. This involves
* removing the network and issuing a save on
* supplicant config.
*/
- static final int CMD_FORGET_NETWORK = 88;
+ static final int CMD_FORGET_NETWORK = BASE + 88;
/* Start Wi-Fi protected setup */
- static final int CMD_START_WPS = 89;
+ static final int CMD_START_WPS = BASE + 89;
/* Set the frequency band */
- static final int CMD_SET_FREQUENCY_BAND = 90;
+ static final int CMD_SET_FREQUENCY_BAND = BASE + 90;
/* Enable background scan for configured networks */
- static final int CMD_ENABLE_BACKGROUND_SCAN = 91;
+ static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91;
/* Commands from/to the SupplicantStateTracker */
/* Reset the supplicant state tracker */
- static final int CMD_RESET_SUPPLICANT_STATE = 111;
+ static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111;
/* Commands/events reported by WpsStateMachine */
/* Indicates the completion of WPS activity */
- static final int WPS_COMPLETED_EVENT = 121;
+ static final int WPS_COMPLETED_EVENT = BASE + 121;
/* Reset the WPS state machine */
- static final int CMD_RESET_WPS_STATE = 122;
+ static final int CMD_RESET_WPS_STATE = BASE + 122;
private static final int CONNECT_MODE = 1;
private static final int SCAN_ONLY_MODE = 2;
@@ -335,8 +340,11 @@
*/
private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
- private static final int POWER_MODE_ACTIVE = 1;
- private static final int POWER_MODE_AUTO = 0;
+ static final int POWER_MODE_ACTIVE = 1;
+ static final int POWER_MODE_AUTO = 0;
+
+ /* Tracks the power mode for restoration after a DHCP request/renewal goes through */
+ private int mPowerMode = POWER_MODE_AUTO;
/**
* See {@link Settings.Secure#WIFI_SCAN_INTERVAL_MS}. This is the default value if a
@@ -348,50 +356,50 @@
private static final int MAX_RSSI = 256;
/* 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();
/**
@@ -1389,8 +1397,10 @@
*/
NetworkUtils.resetConnections(mInterfaceName);
- if (!NetworkUtils.stopDhcp(mInterfaceName)) {
- Log.e(TAG, "Could not stop DHCP");
+ if (mDhcpStateMachine != null) {
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
+ mDhcpStateMachine.quit();
+ mDhcpStateMachine = null;
}
/* Disable interface */
@@ -1416,6 +1426,100 @@
}
+ void handlePreDhcpSetup() {
+ if (!mBluetoothConnectionActive) {
+ /*
+ * There are problems setting the Wi-Fi driver's power
+ * mode to active when bluetooth coexistence mode is
+ * enabled or sense.
+ * <p>
+ * We set Wi-Fi to active mode when
+ * obtaining an IP address because we've found
+ * compatibility issues with some routers with low power
+ * mode.
+ * <p>
+ * In order for this active power mode to properly be set,
+ * we disable coexistence mode until we're done with
+ * obtaining an IP address. One exception is if we
+ * are currently connected to a headset, since disabling
+ * coexistence would interrupt that connection.
+ */
+ // Disable the coexistence mode
+ WifiNative.setBluetoothCoexistenceModeCommand(
+ WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
+ }
+
+ mPowerMode = WifiNative.getPowerModeCommand();
+ if (mPowerMode < 0) {
+ // Handle the case where supplicant driver does not support
+ // getPowerModeCommand.
+ mPowerMode = WifiStateMachine.POWER_MODE_AUTO;
+ }
+ if (mPowerMode != WifiStateMachine.POWER_MODE_ACTIVE) {
+ WifiNative.setPowerModeCommand(WifiStateMachine.POWER_MODE_ACTIVE);
+ }
+ }
+
+
+ void handlePostDhcpSetup() {
+ /* restore power mode */
+ WifiNative.setPowerModeCommand(mPowerMode);
+
+ // Set the coexistence mode back to its default value
+ WifiNative.setBluetoothCoexistenceModeCommand(
+ WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
+ }
+
+ private void handleSuccessfulIpConfiguration(DhcpInfoInternal dhcpInfoInternal) {
+ synchronized (mDhcpInfoInternal) {
+ mDhcpInfoInternal = dhcpInfoInternal;
+ }
+ mLastSignalLevel = -1; // force update of signal strength
+ WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal);
+ InetAddress addr = NetworkUtils.numericToInetAddress(dhcpInfoInternal.ipAddress);
+ mWifiInfo.setInetAddress(addr);
+ if (getNetworkDetailedState() == DetailedState.CONNECTED) {
+ //DHCP renewal in connected state
+ LinkProperties linkProperties = dhcpInfoInternal.makeLinkProperties();
+ linkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId));
+ linkProperties.setInterfaceName(mInterfaceName);
+ if (!linkProperties.equals(mLinkProperties)) {
+ Log.d(TAG, "Link configuration changed for netId: " + mLastNetworkId
+ + " old: " + mLinkProperties + "new: " + linkProperties);
+ NetworkUtils.resetConnections(mInterfaceName);
+ mLinkProperties = linkProperties;
+ sendLinkConfigurationChangedBroadcast();
+ }
+ } else {
+ configureLinkProperties();
+ setNetworkDetailedState(DetailedState.CONNECTED);
+ sendNetworkStateChangeBroadcast(mLastBssid);
+ }
+ }
+
+ private void handleFailedIpConfiguration() {
+ Log.e(TAG, "IP configuration failed");
+
+ mWifiInfo.setInetAddress(null);
+ /**
+ * If we've exceeded the maximum number of retries for DHCP
+ * to a given network, disable the network
+ */
+ if (++mReconnectCount > getMaxDhcpRetries()) {
+ Log.e(TAG, "Failed " +
+ mReconnectCount + " times, Disabling " + mLastNetworkId);
+ WifiConfigStore.disableNetwork(mLastNetworkId);
+ mReconnectCount = 0;
+ }
+
+ /* DHCP times out after about 30 seconds, we do a
+ * disconnect and an immediate reconnect to try again
+ */
+ WifiNative.disconnectCommand();
+ WifiNative.reconnectCommand();
+
+ }
+
/*********************************************************
* Notifications from WifiMonitor
@@ -1527,7 +1631,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");
@@ -1587,6 +1691,8 @@
case CMD_FORGET_NETWORK:
case CMD_RSSI_POLL:
case CMD_ENABLE_ALL_NETWORKS:
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
break;
case CMD_START_WPS:
/* Return failure when the state machine cannot handle WPS initiation*/
@@ -1601,7 +1707,7 @@
}
}
- class InitialState extends HierarchicalState {
+ class InitialState extends State {
@Override
//TODO: could move logging into a common class
public void enter() {
@@ -1620,7 +1726,7 @@
}
}
- class DriverLoadingState extends HierarchicalState {
+ class DriverLoadingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1699,7 +1805,7 @@
}
}
- class DriverLoadedState extends HierarchicalState {
+ class DriverLoadedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1752,7 +1858,7 @@
}
}
- class DriverUnloadingState extends HierarchicalState {
+ class DriverUnloadingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1833,7 +1939,7 @@
}
}
- class DriverUnloadedState extends HierarchicalState {
+ class DriverUnloadedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1854,7 +1960,7 @@
}
}
- class DriverFailedState extends HierarchicalState {
+ class DriverFailedState extends State {
@Override
public void enter() {
Log.e(TAG, getName() + "\n");
@@ -1868,7 +1974,7 @@
}
- class SupplicantStartingState extends HierarchicalState {
+ class SupplicantStartingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -1940,7 +2046,7 @@
}
}
- class SupplicantStartedState extends HierarchicalState {
+ class SupplicantStartedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2063,7 +2169,7 @@
}
}
- class SupplicantStoppingState extends HierarchicalState {
+ class SupplicantStoppingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2106,7 +2212,7 @@
}
}
- class DriverStartingState extends HierarchicalState {
+ class DriverStartingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2147,7 +2253,7 @@
}
}
- class DriverStartedState extends HierarchicalState {
+ class DriverStartedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2251,7 +2357,7 @@
}
}
- class DriverStoppingState extends HierarchicalState {
+ class DriverStoppingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2287,7 +2393,7 @@
}
}
- class DriverStoppedState extends HierarchicalState {
+ class DriverStoppedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2311,7 +2417,7 @@
}
}
- class ScanModeState extends HierarchicalState {
+ class ScanModeState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2348,7 +2454,7 @@
}
}
- class ConnectModeState extends HierarchicalState {
+ class ConnectModeState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2458,75 +2564,19 @@
}
}
- class ConnectingState extends HierarchicalState {
- boolean mModifiedBluetoothCoexistenceMode;
- int mPowerMode;
- boolean mUseStaticIp;
- Thread mDhcpThread;
+ class ConnectingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- mUseStaticIp = WifiConfigStore.isUsingStaticIp(mLastNetworkId);
- if (!mUseStaticIp) {
- mDhcpThread = null;
- mModifiedBluetoothCoexistenceMode = false;
- mPowerMode = POWER_MODE_AUTO;
- if (!mBluetoothConnectionActive) {
- /*
- * There are problems setting the Wi-Fi driver's power
- * mode to active when bluetooth coexistence mode is
- * enabled or sense.
- * <p>
- * We set Wi-Fi to active mode when
- * obtaining an IP address because we've found
- * compatibility issues with some routers with low power
- * mode.
- * <p>
- * In order for this active power mode to properly be set,
- * we disable coexistence mode until we're done with
- * obtaining an IP address. One exception is if we
- * are currently connected to a headset, since disabling
- * coexistence would interrupt that connection.
- */
- mModifiedBluetoothCoexistenceMode = true;
-
- // Disable the coexistence mode
- WifiNative.setBluetoothCoexistenceModeCommand(
- WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
- }
-
- mPowerMode = WifiNative.getPowerModeCommand();
- if (mPowerMode < 0) {
- // Handle the case where supplicant driver does not support
- // getPowerModeCommand.
- mPowerMode = POWER_MODE_AUTO;
- }
- if (mPowerMode != POWER_MODE_ACTIVE) {
- WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE);
- }
-
- Log.d(TAG, "DHCP request started");
- mDhcpThread = new Thread(new Runnable() {
- public void run() {
- DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
- if (NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal)) {
- Log.d(TAG, "DHCP request succeeded");
- synchronized (mDhcpInfoInternal) {
- mDhcpInfoInternal = dhcpInfoInternal;
- }
- WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal);
- sendMessage(CMD_IP_CONFIG_SUCCESS);
- } else {
- Log.d(TAG, "DHCP request failed: " +
- NetworkUtils.getDhcpError());
- sendMessage(CMD_IP_CONFIG_FAILURE);
- }
- }
- });
- mDhcpThread.start();
+ if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
+ //start DHCP
+ mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
+ mContext, WifiStateMachine.this, mInterfaceName);
+ mDhcpStateMachine.registerForPreDhcpNotification();
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
} else {
DhcpInfoInternal dhcpInfoInternal = WifiConfigStore.getIpConfiguration(
mLastNetworkId);
@@ -2538,16 +2588,13 @@
try {
netd.setInterfaceConfig(mInterfaceName, ifcg);
Log.v(TAG, "Static IP configuration succeeded");
- synchronized (mDhcpInfoInternal) {
- mDhcpInfoInternal = dhcpInfoInternal;
- }
- sendMessage(CMD_IP_CONFIG_SUCCESS);
+ sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal);
} catch (RemoteException re) {
Log.v(TAG, "Static IP configuration failed: " + re);
- sendMessage(CMD_IP_CONFIG_FAILURE);
+ sendMessage(CMD_STATIC_IP_FAILURE);
} catch (IllegalStateException e) {
Log.v(TAG, "Static IP configuration failed: " + e);
- sendMessage(CMD_IP_CONFIG_FAILURE);
+ sendMessage(CMD_STATIC_IP_FAILURE);
}
}
}
@@ -2556,44 +2603,26 @@
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
switch(message.what) {
- case CMD_IP_CONFIG_SUCCESS:
- mLastSignalLevel = -1; // force update of signal strength
- InetAddress addr;
- synchronized (mDhcpInfoInternal) {
- addr = NetworkUtils.numericToInetAddress(mDhcpInfoInternal.ipAddress);
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ handlePreDhcpSetup();
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE);
+ break;
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ handlePostDhcpSetup();
+ if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
+ handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
+ transitionTo(mConnectedState);
+ } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
+ handleFailedIpConfiguration();
+ transitionTo(mDisconnectingState);
}
- mWifiInfo.setInetAddress(addr);
- configureLinkProperties();
- if (getNetworkDetailedState() == DetailedState.CONNECTED) {
- sendLinkConfigurationChangedBroadcast();
- } else {
- setNetworkDetailedState(DetailedState.CONNECTED);
- sendNetworkStateChangeBroadcast(mLastBssid);
- }
- //TODO: The framework is not detecting a DHCP renewal and a possible
- //IP change. we should detect this and send out a config change broadcast
+ break;
+ case CMD_STATIC_IP_SUCCESS:
+ handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
transitionTo(mConnectedState);
break;
- case CMD_IP_CONFIG_FAILURE:
- mWifiInfo.setInetAddress(null);
-
- Log.e(TAG, "IP configuration failed");
- /**
- * If we've exceeded the maximum number of retries for DHCP
- * to a given network, disable the network
- */
- if (++mReconnectCount > getMaxDhcpRetries()) {
- Log.e(TAG, "Failed " +
- mReconnectCount + " times, Disabling " + mLastNetworkId);
- WifiConfigStore.disableNetwork(mLastNetworkId);
- mReconnectCount = 0;
- }
-
- /* DHCP times out after about 30 seconds, we do a
- * disconnect and an immediate reconnect to try again
- */
- WifiNative.disconnectCommand();
- WifiNative.reconnectCommand();
+ case CMD_STATIC_IP_FAILURE:
+ handleFailedIpConfiguration();
transitionTo(mDisconnectingState);
break;
case CMD_DISCONNECT:
@@ -2637,26 +2666,9 @@
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
return HANDLED;
}
-
- @Override
- public void exit() {
- /* reset power state & bluetooth coexistence if on DHCP */
- if (!mUseStaticIp) {
- if (mPowerMode != POWER_MODE_ACTIVE) {
- WifiNative.setPowerModeCommand(mPowerMode);
- }
-
- if (mModifiedBluetoothCoexistenceMode) {
- // Set the coexistence mode back to its default value
- WifiNative.setBluetoothCoexistenceModeCommand(
- WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
- }
- }
-
- }
}
- class ConnectedState extends HierarchicalState {
+ class ConnectedState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2671,6 +2683,19 @@
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
boolean eventLoggingEnabled = true;
switch (message.what) {
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ handlePreDhcpSetup();
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE);
+ break;
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ handlePostDhcpSetup();
+ if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
+ handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
+ } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
+ handleFailedIpConfiguration();
+ transitionTo(mDisconnectingState);
+ }
+ break;
case CMD_DISCONNECT:
WifiNative.disconnectCommand();
transitionTo(mDisconnectingState);
@@ -2768,7 +2793,7 @@
}
}
- class DisconnectingState extends HierarchicalState {
+ class DisconnectingState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2798,7 +2823,7 @@
}
}
- class DisconnectedState extends HierarchicalState {
+ class DisconnectedState extends State {
private boolean mAlarmEnabled = false;
private long mScanIntervalMs;
@@ -2905,7 +2930,7 @@
}
}
- class WaitForWpsCompletionState extends HierarchicalState {
+ class WaitForWpsCompletionState extends State {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
@@ -2944,7 +2969,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");