am b69c4e36: am 544ff558: am 29c99aaa: Merge "Added check to make orientation calculations more robust" into gingerbread
* commit 'b69c4e36bec6bfd66e9d67ee3a5befab98ff9e64':
Added check to make orientation calculations more robust
diff --git a/api/current.xml b/api/current.xml
index 785950b..a865813 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -194215,10 +194215,10 @@
synchronized="false"
static="true"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
-<parameter name="addr" type="int">
+<parameter name="ipv4Address" type="int">
</parameter>
</method>
<method name="formatShortFileSize"
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 2fa2834..f45cf2a 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1373,6 +1373,7 @@
public void handleMessage(Message msg) {
long earliestFuturePollTime = Long.MAX_VALUE;
long nextPendingSyncTime = Long.MAX_VALUE;
+
// Setting the value here instead of a method because we want the dumpsys logs
// to have the most recent value used.
try {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b2937ba..20a22e5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3080,11 +3080,7 @@
if (!sCompatibilityModeEnabled) {
ai.disableCompatibilityMode();
}
- if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- ai.enabled = true;
- } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
- ai.enabled = false;
- }
+ ai.enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
return ai;
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 8a653dd..f1bf852 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -125,24 +125,19 @@
/**
* Convert a IPv4 address from an integer to an InetAddress.
- * @param hostAddr is an Int corresponding to the IPv4 address in network byte order
- * @return the IP address as an {@code InetAddress}, returns null if
- * unable to convert or if the int is an invalid address.
+ * @param hostAddress an int corresponding to the IPv4 address in network byte order
*/
public static InetAddress intToInetAddress(int hostAddress) {
- InetAddress inetAddress;
byte[] addressBytes = { (byte)(0xff & hostAddress),
(byte)(0xff & (hostAddress >> 8)),
(byte)(0xff & (hostAddress >> 16)),
(byte)(0xff & (hostAddress >> 24)) };
try {
- inetAddress = InetAddress.getByAddress(addressBytes);
- } catch(UnknownHostException e) {
- return null;
+ return InetAddress.getByAddress(addressBytes);
+ } catch (UnknownHostException e) {
+ throw new AssertionError();
}
-
- return inetAddress;
}
/**
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index baaa3ce..5ae65df 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -17,32 +17,33 @@
package android.text.format;
import android.content.Context;
+import android.net.NetworkUtils;
/**
* Utility class to aid in formatting common values that are not covered
- * by the standard java.util.Formatter.
+ * by {@link java.util.Formatter}
*/
public final class Formatter {
/**
* Formats a content size to be in the form of bytes, kilobytes, megabytes, etc
- *
+ *
* @param context Context to use to load the localized units
- * @param number size value to be formated
- * @return formated string with the number
+ * @param number size value to be formatted
+ * @return formatted string with the number
*/
public static String formatFileSize(Context context, long number) {
return formatFileSize(context, number, false);
}
-
+
/**
* Like {@link #formatFileSize}, but trying to generate shorter numbers
- * (showing fewer digits of precisin).
+ * (showing fewer digits of precision).
*/
public static String formatShortFileSize(Context context, long number) {
return formatFileSize(context, number, true);
}
-
+
private static String formatFileSize(Context context, long number, boolean shorter) {
if (context == null) {
return "";
@@ -92,21 +93,21 @@
getString(com.android.internal.R.string.fileSizeSuffix,
value, context.getString(suffix));
}
-
+
/**
* Returns a string in the canonical IP format ###.###.###.### from a packed integer containing
* the IP address. The IP address is expected to be in little-endian format (LSB first). That
* is, 0x01020304 will return "4.3.2.1".
- *
- * @param addr the IP address as a packed integer with LSB first.
+ *
+ * @param ipv4Address the IP address as a packed integer with LSB first.
* @return string with canonical IP address format.
+ *
+ * @deprecated this method doesn't support IPv6 addresses. Prefer {@link
+ * java.net.InetAddress#getHostAddress()}, which supports both IPv4 and
+ * IPv6 addresses.
*/
- public static String formatIpAddress(int addr) {
- StringBuffer buf = new StringBuffer();
- buf.append(addr & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff);
- return buf.toString();
+ @Deprecated
+ public static String formatIpAddress(int ipv4Address) {
+ return NetworkUtils.intToInetAddress(ipv4Address).getHostAddress();
}
}
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 6095a64..2a76e33 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -234,14 +234,6 @@
// high time constant.
private static final float MAX_DEVIATION_FROM_GRAVITY = 1.5f;
- // Minimum acceleration considered, in m/s^2. Below this threshold sensor noise will have
- // significant impact on the calculations and in case of the vector (0, 0, 0) there is no
- // defined rotation or tilt at all. Low or zero readings can happen when space travelling
- // or free falling, but more commonly when shaking or getting bad readings from the sensor.
- // The accelerometer is turned off when not used and polling it too soon after it is
- // turned on may result in (0, 0, 0).
- private static final float MIN_ABS_ACCELERATION = 1.5f;
-
// Actual sampling period corresponding to SensorManager.SENSOR_DELAY_NORMAL. There's no
// way to get this information from SensorManager.
// Note the actual period is generally 3-30ms larger than this depending on the device, but
@@ -355,9 +347,6 @@
float deviation = Math.abs(magnitude - SensorManager.STANDARD_GRAVITY);
handleAccelerationDistrust(deviation);
- if (magnitude < MIN_ABS_ACCELERATION) {
- return; // Ignore tilt and orientation when (0, 0, 0) or low reading
- }
// only filter tilt when we're accelerating
float alpha = 1;
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index 43cf06a..96b028a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -19,6 +19,16 @@
import android.content.Context;
import android.test.InstrumentationTestCase;
+/**
+ * Stress test suite for Bluetooth related functions.
+ *
+ * Includes tests for enabling/disabling bluetooth, enabling/disabling discoverable mode,
+ * starting/stopping scans, connecting/disconnecting to HFP, A2DP, HID, PAN profiles, and verifying
+ * that remote connections/disconnections occur for the PAN profile.
+ * <p>
+ * This test suite uses {@link android.bluetooth.BluetoothTestRunner} to for parameters such as the
+ * number of iterations and the addresses of remote Bluetooth devices.
+ */
public class BluetoothStressTest extends InstrumentationTestCase {
private static final String TAG = "BluetoothStressTest";
private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt";
@@ -40,6 +50,9 @@
mTestUtils.close();
}
+ /**
+ * Stress test for enabling and disabling Bluetooth.
+ */
public void testEnable() {
int iterations = BluetoothTestRunner.sEnableIterations;
if (iterations == 0) {
@@ -55,6 +68,9 @@
}
}
+ /**
+ * Stress test for putting the device in and taking the device out of discoverable mode.
+ */
public void testDiscoverable() {
int iterations = BluetoothTestRunner.sDiscoverableIterations;
if (iterations == 0) {
@@ -73,6 +89,9 @@
mTestUtils.disable(adapter);
}
+ /**
+ * Stress test for starting and stopping Bluetooth scans.
+ */
public void testScan() {
int iterations = BluetoothTestRunner.sScanIterations;
if (iterations == 0) {
@@ -91,6 +110,30 @@
mTestUtils.disable(adapter);
}
+ /**
+ * Stress test for enabling and disabling the PAN NAP profile.
+ */
+ public void testEnablePan() {
+ int iterations = BluetoothTestRunner.sEnablePanIterations;
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ mTestUtils.enable(adapter);
+
+ for (int i = 0; i < iterations; i++) {
+ mTestUtils.writeOutput("testEnablePan iteration " + (i + 1) + " of "
+ + iterations);
+ mTestUtils.enablePan(adapter);
+ mTestUtils.disablePan(adapter);
+ }
+
+ mTestUtils.disable(adapter);
+ }
+
+ /**
+ * Stress test for pairing and unpairing with a remote device.
+ * <p>
+ * In this test, the local device initiates pairing with a remote device, and then unpairs with
+ * the device after the pairing has successfully completed.
+ */
public void testPair() {
int iterations = BluetoothTestRunner.sPairIterations;
if (iterations == 0) {
@@ -110,6 +153,12 @@
mTestUtils.disable(adapter);
}
+ /**
+ * Stress test for accepting a pairing request and unpairing with a remote device.
+ * <p>
+ * In this test, the local device waits for a pairing request from a remote device. It accepts
+ * the request and then unpairs after the paring has successfully completed.
+ */
public void testAcceptPair() {
int iterations = BluetoothTestRunner.sPairIterations;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -125,6 +174,12 @@
mTestUtils.disable(adapter);
}
+ /**
+ * Stress test for connecting and disconnecting with an A2DP source.
+ * <p>
+ * In this test, the local device plays the role of an A2DP sink, and initiates connections and
+ * disconnections with an A2DP source.
+ */
public void testConnectA2dp() {
int iterations = BluetoothTestRunner.sConnectA2dpIterations;
if (iterations == 0) {
@@ -143,10 +198,16 @@
mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.A2DP);
}
- // TODO: Unpair from device if device can accept pairing after unpairing
+ mTestUtils.unpair(adapter, device);
mTestUtils.disable(adapter);
}
+ /**
+ * Stress test for connecting and disconnecting the HFP with a hands free device.
+ * <p>
+ * In this test, the local device plays the role of an HFP audio gateway, and initiates
+ * connections and disconnections with a hands free device.
+ */
public void testConnectHeadset() {
int iterations = BluetoothTestRunner.sConnectHeadsetIterations;
if (iterations == 0) {
@@ -165,7 +226,94 @@
mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.HEADSET);
}
- // TODO: Unpair from device if device can accept pairing after unpairing
+ mTestUtils.unpair(adapter, device);
+ mTestUtils.disable(adapter);
+ }
+
+ /**
+ * Stress test for connecting and disconnecting with a HID device.
+ * <p>
+ * In this test, the local device plays the role of a HID host, and initiates connections and
+ * disconnections with a HID device.
+ */
+ public void testConnectInput() {
+ int iterations = BluetoothTestRunner.sConnectInputIterations;
+ if (iterations == 0) {
+ return;
+ }
+
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sInputAddress);
+ mTestUtils.enable(adapter);
+ mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+ BluetoothTestRunner.sPairPin);
+
+ for (int i = 0; i < iterations; i++) {
+ mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
+ mTestUtils.connectInput(adapter, device);
+ mTestUtils.disconnectInput(adapter, device);
+ }
+
+ mTestUtils.unpair(adapter, device);
+ mTestUtils.disable(adapter);
+ }
+
+ /**
+ * Stress test for connecting and disconnecting with a PAN NAP.
+ * <p>
+ * In this test, the local device plays the role of a PANU, and initiates connections and
+ * disconnections with a NAP.
+ */
+ public void testConnectPan() {
+ int iterations = BluetoothTestRunner.sConnectPanIterations;
+ if (iterations == 0) {
+ return;
+ }
+
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPanAddress);
+ mTestUtils.enable(adapter);
+ mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+ BluetoothTestRunner.sPairPin);
+
+ for (int i = 0; i < iterations; i++) {
+ mTestUtils.writeOutput("connectPan iteration " + (i + 1) + " of " + iterations);
+ mTestUtils.connectPan(adapter, device);
+ mTestUtils.disconnectPan(adapter, device);
+ }
+
+ mTestUtils.unpair(adapter, device);
+ mTestUtils.disable(adapter);
+ }
+
+ /**
+ * Stress test for verifying a PANU connecting and disconnecting with the device.
+ * <p>
+ * In this test, the local device plays the role of a NAP which a remote PANU connects and
+ * disconnects from.
+ */
+ public void testIncomingPanConnection() {
+ int iterations = BluetoothTestRunner.sConnectPanIterations;
+ if (iterations == 0) {
+ return;
+ }
+
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPanAddress);
+ mTestUtils.enable(adapter);
+ mTestUtils.enablePan(adapter);
+ mTestUtils.acceptPair(adapter, device, BluetoothTestRunner.sPairPasskey,
+ BluetoothTestRunner.sPairPin);
+
+ for (int i = 0; i < iterations; i++) {
+ mTestUtils.writeOutput("incomingPanConnection iteration " + (i + 1) + " of "
+ + iterations);
+ mTestUtils.incomingPanConnection(adapter, device);
+ mTestUtils.incomingPanDisconnection(adapter, device);
+ }
+
+ mTestUtils.unpair(adapter, device);
+ mTestUtils.disablePan(adapter);
mTestUtils.disable(adapter);
}
}
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
index 3e589fc..cede05a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
@@ -23,19 +23,51 @@
import android.test.InstrumentationTestSuite;
import android.util.Log;
+/**
+ * Instrumentation test runner for Bluetooth tests.
+ * <p>
+ * To run:
+ * <pre>
+ * {@code
+ * adb shell am instrument \
+ * [-e enable_iterations <iterations>] \
+ * [-e discoverable_iterations <iterations>] \
+ * [-e scan_iterations <iterations>] \
+ * [-e enable_pan_iterations <iterations>] \
+ * [-e pair_iterations <iterations>] \
+ * [-e connect_a2dp_iterations <iterations>] \
+ * [-e connect_headset_iterations <iterations>] \
+ * [-e connect_input_iterations <iterations>] \
+ * [-e connect_pan_iterations <iterations>] \
+ * [-e pair_address <address>] \
+ * [-e headset_address <address>] \
+ * [-e a2dp_address <address>] \
+ * [-e input_address <address>] \
+ * [-e pan_address <address>] \
+ * [-e pair_pin <pin>] \
+ * [-e pair_passkey <passkey>] \
+ * -w com.android.frameworks.coretests/android.bluetooth.BluetoothTestRunner
+ * }
+ * </pre>
+ */
public class BluetoothTestRunner extends InstrumentationTestRunner {
private static final String TAG = "BluetoothTestRunner";
public static int sEnableIterations = 100;
public static int sDiscoverableIterations = 1000;
public static int sScanIterations = 1000;
+ public static int sEnablePanIterations = 1000;
public static int sPairIterations = 100;
public static int sConnectHeadsetIterations = 100;
public static int sConnectA2dpIterations = 100;
+ public static int sConnectInputIterations = 100;
+ public static int sConnectPanIterations = 100;
public static String sPairAddress = "";
public static String sHeadsetAddress = "";
public static String sA2dpAddress = "";
+ public static String sInputAddress = "";
+ public static String sPanAddress = "";
public static byte[] sPairPin = {'1', '2', '3', '4'};
public static int sPairPasskey = 123456;
@@ -81,6 +113,15 @@
}
}
+ val = arguments.getString("enable_pan_iterations");
+ if (val != null) {
+ try {
+ sEnablePanIterations = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // Invalid argument, fall back to default value
+ }
+ }
+
val = arguments.getString("pair_iterations");
if (val != null) {
try {
@@ -108,6 +149,24 @@
}
}
+ val = arguments.getString("connect_input_iterations");
+ if (val != null) {
+ try {
+ sConnectInputIterations = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // Invalid argument, fall back to default value
+ }
+ }
+
+ val = arguments.getString("connect_pan_iterations");
+ if (val != null) {
+ try {
+ sConnectPanIterations = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // Invalid argument, fall back to default value
+ }
+ }
+
val = arguments.getString("pair_address");
if (val != null) {
sPairAddress = val;
@@ -123,6 +182,16 @@
sA2dpAddress = val;
}
+ val = arguments.getString("input_address");
+ if (val != null) {
+ sInputAddress = val;
+ }
+
+ val = arguments.getString("pan_address");
+ if (val != null) {
+ sPanAddress = val;
+ }
+
val = arguments.getString("pair_pin");
if (val != null) {
sPairPin = BluetoothDevice.convertPinToBytes(val);
@@ -143,9 +212,13 @@
Log.i(TAG, String.format("pair_iterations=%d", sPairIterations));
Log.i(TAG, String.format("connect_a2dp_iterations=%d", sConnectA2dpIterations));
Log.i(TAG, String.format("connect_headset_iterations=%d", sConnectHeadsetIterations));
+ Log.i(TAG, String.format("connect_input_iterations=%d", sConnectInputIterations));
+ Log.i(TAG, String.format("connect_pan_iterations=%d", sConnectPanIterations));
Log.i(TAG, String.format("pair_address=%s", sPairAddress));
Log.i(TAG, String.format("a2dp_address=%s", sA2dpAddress));
Log.i(TAG, String.format("headset_address=%s", sHeadsetAddress));
+ Log.i(TAG, String.format("input_address=%s", sInputAddress));
+ Log.i(TAG, String.format("pan_address=%s", sPanAddress));
Log.i(TAG, String.format("pair_pin=%s", new String(sPairPin)));
Log.i(TAG, String.format("pair_passkey=%d", sPairPasskey));
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 6da38a7..effed76 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -35,49 +35,29 @@
public class BluetoothTestUtils extends Assert {
/**
- * Timeout for {@link BluetoothAdapter#disable()} in ms.
+ * Timeout for enable/disable in ms.
*/
- private static final int DISABLE_TIMEOUT = 20000;
+ private static final int ENABLE_DISABLE_TIMEOUT = 20000;
/**
- * Timeout for {@link BluetoothAdapter#enable()} in ms.
+ * Timeout for discoverable/undiscoverable in ms.
*/
- private static final int ENABLE_TIMEOUT = 20000;
+ private static final int DISCOVERABLE_UNDISCOVERABLE_TIMEOUT = 5000;
/**
- * Timeout for {@link BluetoothAdapter#setScanMode(int)} in ms.
+ * Timeout for starting/stopping a scan in ms.
*/
- private static final int SET_SCAN_MODE_TIMEOUT = 5000;
+ private static final int START_STOP_SCAN_TIMEOUT = 5000;
/**
- * Timeout for {@link BluetoothAdapter#startDiscovery()} in ms.
+ * Timeout for pair/unpair in ms.
*/
- private static final int START_DISCOVERY_TIMEOUT = 5000;
+ private static final int PAIR_UNPAIR_TIMEOUT = 20000;
/**
- * Timeout for {@link BluetoothAdapter#cancelDiscovery()} in ms.
+ * Timeout for connecting/disconnecting a profile in ms.
*/
- private static final int CANCEL_DISCOVERY_TIMEOUT = 5000;
-
- /**
- * Timeout for {@link BluetoothDevice#createBond()} in ms.
- */
- private static final int PAIR_TIMEOUT = 20000;
-
- /**
- * Timeout for {@link BluetoothDevice#removeBond()} in ms.
- */
- private static final int UNPAIR_TIMEOUT = 20000;
-
- /**
- * Timeout for {@link BluetoothProfile#connect(BluetoothDevice)} in ms.
- */
- private static final int CONNECT_PROFILE_TIMEOUT = 20000;
-
- /**
- * Timeout for {@link BluetoothProfile#disconnect(BluetoothDevice)} in ms.
- */
- private static final int DISCONNECT_PROFILE_TIMEOUT = 20000;
+ private static final int CONNECT_DISCONNECT_PROFILE_TIMEOUT = 20000;
/**
* Timeout to connect a profile proxy in ms.
@@ -265,7 +245,6 @@
@Override
public void onReceive(Context context, Intent intent) {
-
if (mConnectionAction != null && mConnectionAction.equals(intent.getAction())) {
if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
return;
@@ -291,6 +270,91 @@
}
}
+ private class ConnectInputReceiver extends FlagReceiver {
+ private static final int STATE_DISCONNECTED_FLAG = 1;
+ private static final int STATE_CONNECTING_FLAG = 1 << 1;
+ private static final int STATE_CONNECTED_FLAG = 1 << 2;
+ private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
+
+ private BluetoothDevice mDevice;
+
+ public ConnectInputReceiver(BluetoothDevice device, int expectedFlags) {
+ super(expectedFlags);
+
+ mDevice = device;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
+ return;
+ }
+
+ if (BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED.equals(intent.getAction())) {
+ int state = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, -1);
+ assertNotSame(-1, state);
+ switch (state) {
+ case BluetoothInputDevice.STATE_DISCONNECTED:
+ setFiredFlag(STATE_DISCONNECTED_FLAG);
+ break;
+ case BluetoothInputDevice.STATE_CONNECTING:
+ setFiredFlag(STATE_CONNECTING_FLAG);
+ break;
+ case BluetoothInputDevice.STATE_CONNECTED:
+ setFiredFlag(STATE_CONNECTED_FLAG);
+ break;
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ setFiredFlag(STATE_DISCONNECTING_FLAG);
+ break;
+ }
+ }
+ }
+ }
+
+ private class ConnectPanReceiver extends FlagReceiver {
+ private static final int STATE_DISCONNECTED_FLAG = 1;
+ private static final int STATE_CONNECTING_FLAG = 1 << 1;
+ private static final int STATE_CONNECTED_FLAG = 1 << 2;
+ private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
+
+ private BluetoothDevice mDevice;
+ private int mRole;
+
+ public ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) {
+ super (expectedFlags);
+
+ mDevice = device;
+ mRole = role;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
+ || mRole != intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, -1)) {
+ return;
+ }
+
+ if (BluetoothPan.ACTION_PAN_STATE_CHANGED.equals(intent.getAction())) {
+ int state = intent.getIntExtra(BluetoothPan.EXTRA_PAN_STATE, -1);
+ assertNotSame(-1, state);
+ switch (state) {
+ case BluetoothPan.STATE_DISCONNECTED:
+ setFiredFlag(STATE_DISCONNECTED_FLAG);
+ break;
+ case BluetoothPan.STATE_CONNECTING:
+ setFiredFlag(STATE_CONNECTING_FLAG);
+ break;
+ case BluetoothPan.STATE_CONNECTED:
+ setFiredFlag(STATE_CONNECTED_FLAG);
+ break;
+ case BluetoothPan.STATE_DISCONNECTING:
+ setFiredFlag(STATE_DISCONNECTING_FLAG);
+ break;
+ }
+ }
+ }
+ }
+
private BluetoothProfile.ServiceListener mServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -330,10 +394,24 @@
private BluetoothA2dp mA2dp;
private BluetoothHeadset mHeadset;
+ /**
+ * Creates a utility instance for testing Bluetooth.
+ *
+ * @param context The context of the application using the utility.
+ * @param tag The log tag of the application using the utility.
+ */
public BluetoothTestUtils(Context context, String tag) {
this(context, tag, null);
}
+ /**
+ * Creates a utility instance for testing Bluetooth.
+ *
+ * @param context The context of the application using the utility.
+ * @param tag The log tag of the application using the utility.
+ * @param outputFile The path to an output file if the utility is to write results to a
+ * separate file.
+ */
public BluetoothTestUtils(Context context, String tag, String outputFile) {
mContext = context;
mTag = tag;
@@ -352,6 +430,9 @@
}
}
+ /**
+ * Closes the utility instance and unregisters any BroadcastReceivers.
+ */
public void close() {
while (!mReceivers.isEmpty()) {
mContext.unregisterReceiver(mReceivers.remove(0));
@@ -366,6 +447,12 @@
}
}
+ /**
+ * Enables Bluetooth and checks to make sure that Bluetooth was turned on and that the correct
+ * actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ */
public void enable(BluetoothAdapter adapter) {
int mask = (BluetoothReceiver.STATE_TURNING_ON_FLAG | BluetoothReceiver.STATE_ON_FLAG
| BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG);
@@ -397,22 +484,19 @@
}
long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < ENABLE_TIMEOUT) {
+ while (System.currentTimeMillis() - s < ENABLE_DISABLE_TIMEOUT) {
state = adapter.getState();
- if (state == BluetoothAdapter.STATE_ON) {
+ if (state == BluetoothAdapter.STATE_ON
+ && (receiver.getFiredFlags() & mask) == mask) {
assertTrue(adapter.isEnabled());
- if ((receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("enable() completed in %d ms", (finish - start)));
- } else {
- writeOutput("enable() completed");
- }
- removeReceiver(receiver);
- return;
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("enable() completed in %d ms", (finish - start)));
+ } else {
+ writeOutput("enable() completed");
}
- } else {
- assertEquals(BluetoothAdapter.STATE_TURNING_ON, state);
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -423,6 +507,12 @@
state, BluetoothAdapter.STATE_ON, firedFlags, mask));
}
+ /**
+ * Disables Bluetooth and checks to make sure that Bluetooth was turned off and that the correct
+ * actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ */
public void disable(BluetoothAdapter adapter) {
int mask = (BluetoothReceiver.STATE_TURNING_OFF_FLAG | BluetoothReceiver.STATE_OFF_FLAG
| BluetoothReceiver.SCAN_MODE_NONE_FLAG);
@@ -454,23 +544,19 @@
}
long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < DISABLE_TIMEOUT) {
+ while (System.currentTimeMillis() - s < ENABLE_DISABLE_TIMEOUT) {
state = adapter.getState();
- if (state == BluetoothAdapter.STATE_OFF) {
+ if (state == BluetoothAdapter.STATE_OFF
+ && (receiver.getFiredFlags() & mask) == mask) {
assertFalse(adapter.isEnabled());
- if ((receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("disable() completed in %d ms",
- (finish - start)));
- } else {
- writeOutput("disable() completed");
- }
- removeReceiver(receiver);
- return;
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("disable() completed in %d ms", (finish - start)));
+ } else {
+ writeOutput("disable() completed");
}
- } else {
- assertEquals(BluetoothAdapter.STATE_TURNING_OFF, state);
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -481,6 +567,12 @@
state, BluetoothAdapter.STATE_OFF, firedFlags, mask));
}
+ /**
+ * Puts the local device into discoverable mode and checks to make sure that the local device
+ * is in discoverable mode and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ */
public void discoverable(BluetoothAdapter adapter) {
int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
@@ -499,17 +591,14 @@
long start = System.currentTimeMillis();
assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
- while (System.currentTimeMillis() - start < SET_SCAN_MODE_TIMEOUT) {
+ while (System.currentTimeMillis() - start < DISCOVERABLE_UNDISCOVERABLE_TIMEOUT) {
scanMode = adapter.getScanMode();
- if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
- if ((receiver.getFiredFlags() & mask) == mask) {
- writeOutput(String.format("discoverable() completed in %d ms",
- (receiver.getCompletedTime() - start)));
- removeReceiver(receiver);
- return;
- }
- } else {
- assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE, scanMode);
+ if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE
+ && (receiver.getFiredFlags() & mask) == mask) {
+ writeOutput(String.format("discoverable() completed in %d ms",
+ (receiver.getCompletedTime() - start)));
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -521,6 +610,12 @@
firedFlags, mask));
}
+ /**
+ * Puts the local device into connectable only mode and checks to make sure that the local
+ * device is in in connectable mode and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ */
public void undiscoverable(BluetoothAdapter adapter) {
int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG;
@@ -539,17 +634,14 @@
long start = System.currentTimeMillis();
assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
- while (System.currentTimeMillis() - start < SET_SCAN_MODE_TIMEOUT) {
+ while (System.currentTimeMillis() - start < DISCOVERABLE_UNDISCOVERABLE_TIMEOUT) {
scanMode = adapter.getScanMode();
- if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
- if ((receiver.getFiredFlags() & mask) == mask) {
- writeOutput(String.format("undiscoverable() completed in %d ms",
- (receiver.getCompletedTime() - start)));
- removeReceiver(receiver);
- return;
- }
- } else {
- assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, scanMode);
+ if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE
+ && (receiver.getFiredFlags() & mask) == mask) {
+ writeOutput(String.format("undiscoverable() completed in %d ms",
+ (receiver.getCompletedTime() - start)));
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -561,6 +653,12 @@
mask));
}
+ /**
+ * Starts a scan for remote devices and checks to make sure that the local device is scanning
+ * and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ */
public void startScan(BluetoothAdapter adapter) {
int mask = BluetoothReceiver.DISCOVERY_STARTED_FLAG;
@@ -577,7 +675,7 @@
long start = System.currentTimeMillis();
assertTrue(adapter.startDiscovery());
- while (System.currentTimeMillis() - start < START_DISCOVERY_TIMEOUT) {
+ while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
if (adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
writeOutput(String.format("startScan() completed in %d ms",
(receiver.getCompletedTime() - start)));
@@ -593,6 +691,12 @@
adapter.isDiscovering(), firedFlags, mask));
}
+ /**
+ * Stops a scan for remote devices and checks to make sure that the local device is not scanning
+ * and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ */
public void stopScan(BluetoothAdapter adapter) {
int mask = BluetoothReceiver.DISCOVERY_FINISHED_FLAG;
@@ -610,7 +714,7 @@
// TODO: put assertTrue() around cancelDiscovery() once it starts returning true.
adapter.cancelDiscovery();
- while (System.currentTimeMillis() - start < CANCEL_DISCOVERY_TIMEOUT) {
+ while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
writeOutput(String.format("stopScan() completed in %d ms",
(receiver.getCompletedTime() - start)));
@@ -627,20 +731,84 @@
}
+ /**
+ * Enables PAN tethering on the local device and checks to make sure that tethering is enabled.
+ *
+ * @param adapter The BT adapter.
+ */
+ public void enablePan(BluetoothAdapter adapter) {
+ BluetoothPan pan = new BluetoothPan(mContext);
+ assertNotNull(pan);
+
+ long start = System.currentTimeMillis();
+ pan.setBluetoothTethering(true);
+ long stop = System.currentTimeMillis();
+ assertTrue(pan.isTetheringOn());
+
+ writeOutput(String.format("enablePan() completed in %d ms", (stop - start)));
+ }
+
+ /**
+ * Disables PAN tethering on the local device and checks to make sure that tethering is
+ * disabled.
+ *
+ * @param adapter The BT adapter.
+ */
+ public void disablePan(BluetoothAdapter adapter) {
+ BluetoothPan pan = new BluetoothPan(mContext);
+ assertNotNull(pan);
+
+ long start = System.currentTimeMillis();
+ pan.setBluetoothTethering(false);
+ long stop = System.currentTimeMillis();
+ assertFalse(pan.isTetheringOn());
+
+ writeOutput(String.format("disablePan() completed in %d ms", (stop - start)));
+ }
+
+ /**
+ * Initiates a pairing with a remote device and checks to make sure that the devices are paired
+ * and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
+ * @param pin The pairing pin if pairing requires a pin. Any value if not.
+ */
public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
pairOrAcceptPair(adapter, device, passkey, pin, true);
}
+ /**
+ * Accepts a pairing with a remote device and checks to make sure that the devices are paired
+ * and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
+ * @param pin The pairing pin if pairing requires a pin. Any value if not.
+ */
public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
byte[] pin) {
pairOrAcceptPair(adapter, device, passkey, pin, false);
}
+ /**
+ * Helper method used by {@link #pair(BluetoothAdapter, BluetoothDevice, int, byte[])} and
+ * {@link #acceptPair(BluetoothAdapter, BluetoothDevice, int, byte[])} to either pair or accept
+ * a pairing request.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
+ * @param pin The pairing pin if pairing requires a pin. Any value if not.
+ * @param shouldPair Whether to pair or accept the pair.
+ */
private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
- byte[] pin, boolean pair) {
+ byte[] pin, boolean shouldPair) {
int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
long start = -1;
- String methodName = pair ? "pair()" : "acceptPair()";
+ String methodName = shouldPair ? "pair()" : "acceptPair()";
if (!adapter.isEnabled()) {
fail(methodName + " bluetooth not enabled");
@@ -653,7 +821,7 @@
case BluetoothDevice.BOND_NONE:
assertFalse(adapter.getBondedDevices().contains(device));
start = System.currentTimeMillis();
- if (pair) {
+ if (shouldPair) {
assertTrue(device.createBond());
}
break;
@@ -670,21 +838,19 @@
}
long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < PAIR_TIMEOUT) {
+ while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
state = device.getBondState();
- if (state == BluetoothDevice.BOND_BONDED) {
+ if (state == BluetoothDevice.BOND_BONDED && (receiver.getFiredFlags() & mask) == mask) {
assertTrue(adapter.getBondedDevices().contains(device));
- if ((receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
- (finish - start), device));
- } else {
- writeOutput(String.format("%s completed: device=%s", methodName, device));
- }
- removeReceiver(receiver);
- return;
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
+ (finish - start), device));
+ } else {
+ writeOutput(String.format("%s completed: device=%s", methodName, device));
}
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -696,6 +862,13 @@
BluetoothDevice.BOND_BONDED, firedFlags, mask));
}
+ /**
+ * Deletes a pairing with a remote device and checks to make sure that the devices are unpaired
+ * and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
int mask = PairReceiver.STATE_NONE_FLAG;
long start = -1;
@@ -727,20 +900,19 @@
}
long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < UNPAIR_TIMEOUT) {
- if (device.getBondState() == BluetoothDevice.BOND_NONE) {
+ while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
+ if (device.getBondState() == BluetoothDevice.BOND_NONE
+ && (receiver.getFiredFlags() & mask) == mask) {
assertFalse(adapter.getBondedDevices().contains(device));
- if ((receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("unpair() completed in %d ms: device=%s",
- (finish - start), device));
- } else {
- writeOutput(String.format("unpair() completed: device=%s", device));
- }
- removeReceiver(receiver);
- return;
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("unpair() completed in %d ms: device=%s",
+ (finish - start), device));
+ } else {
+ writeOutput(String.format("unpair() completed: device=%s", device));
}
+ removeReceiver(receiver);
+ return;
}
}
@@ -751,6 +923,15 @@
firedFlags, mask));
}
+ /**
+ * Connects a profile from the local device to a remote device and checks to make sure that the
+ * profile is connected and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param profile The profile to connect. One of {@link BluetoothProfile#A2DP} or
+ * {@link BluetoothProfile#HEADSET}.
+ */
public void connectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile) {
int mask = (ConnectProfileReceiver.STATE_CONNECTING_FLAG
| ConnectProfileReceiver.STATE_CONNECTED_FLAG);
@@ -794,21 +975,20 @@
}
long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_PROFILE_TIMEOUT) {
+ while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
state = proxy.getConnectionState(device);
- if (state == BluetoothProfile.STATE_CONNECTED) {
- if ((receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("connectProfile() completed in %d ms: "
- + "device=%s, profile=%d", (finish - start), device, profile));
- } else {
- writeOutput(String.format("connectProfile() completed: device=%s, "
- + "profile=%d", device, profile));
- }
- removeReceiver(receiver);
- return;
+ if (state == BluetoothProfile.STATE_CONNECTED
+ && (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("connectProfile() completed in %d ms: "
+ + "device=%s, profile=%d", (finish - start), device, profile));
+ } else {
+ writeOutput(String.format("connectProfile() completed: device=%s, "
+ + "profile=%d", device, profile));
}
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -820,6 +1000,15 @@
BluetoothProfile.STATE_CONNECTED, firedFlags, mask));
}
+ /**
+ * Disconnects a profile between the local device and a remote device and checks to make sure
+ * that the profile is disconnected and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param profile The profile to disconnect. One of {@link BluetoothProfile#A2DP} or
+ * {@link BluetoothProfile#HEADSET}.
+ */
public void disconnectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile) {
int mask = (ConnectProfileReceiver.STATE_DISCONNECTING_FLAG
| ConnectProfileReceiver.STATE_DISCONNECTED_FLAG);
@@ -863,21 +1052,20 @@
}
long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < DISCONNECT_PROFILE_TIMEOUT) {
+ while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
state = proxy.getConnectionState(device);
- if (state == BluetoothProfile.STATE_DISCONNECTED) {
- if ((receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("disconnectProfile() completed in %d ms: "
- + "device=%s, profile=%d", (finish - start), device, profile));
- } else {
- writeOutput(String.format("disconnectProfile() completed: device=%s, "
- + "profile=%d", device, profile));
- }
- removeReceiver(receiver);
- return;
+ if (state == BluetoothProfile.STATE_DISCONNECTED
+ && (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("disconnectProfile() completed in %d ms: "
+ + "device=%s, profile=%d", (finish - start), device, profile));
+ } else {
+ writeOutput(String.format("disconnectProfile() completed: device=%s, "
+ + "profile=%d", device, profile));
}
+ removeReceiver(receiver);
+ return;
}
sleep(POLL_TIME);
}
@@ -889,6 +1077,360 @@
BluetoothProfile.STATE_DISCONNECTED, firedFlags, mask));
}
+ /**
+ * Connects the local device with a remote HID device and checks to make sure that the profile
+ * is connected and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void connectInput(BluetoothAdapter adapter, BluetoothDevice device) {
+ int mask = (ConnectInputReceiver.STATE_CONNECTING_FLAG
+ | ConnectInputReceiver.STATE_CONNECTED_FLAG);
+ long start = -1;
+
+ if (!adapter.isEnabled()) {
+ fail(String.format("connectInput() bluetooth not enabled: device=%s", device));
+ }
+
+ if (!adapter.getBondedDevices().contains(device)) {
+ fail(String.format("connectInput() device not paired: device=%s", device));
+ }
+
+ BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
+ assertNotNull(inputDevice);
+ ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
+
+ int state = inputDevice.getInputDeviceState(device);
+ switch (state) {
+ case BluetoothInputDevice.STATE_CONNECTED:
+ removeReceiver(receiver);
+ return;
+ case BluetoothInputDevice.STATE_CONNECTING:
+ mask = 0; // Don't check for received intents since we might have missed them.
+ break;
+ case BluetoothInputDevice.STATE_DISCONNECTED:
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ start = System.currentTimeMillis();
+ assertTrue(inputDevice.connectInputDevice(device));
+ break;
+ default:
+ removeReceiver(receiver);
+ fail(String.format("connectInput() invalid state: device=%s, state=%d", device,
+ state));
+ }
+
+ long s = System.currentTimeMillis();
+ while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+ state = inputDevice.getInputDeviceState(device);
+ if (state == BluetoothInputDevice.STATE_CONNECTED
+ && (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("connectInput() completed in %d ms: device=%s",
+ (finish - start), device));
+ } else {
+ writeOutput(String.format("connectInput() completed: device=%s", device));
+ }
+ removeReceiver(receiver);
+ return;
+ }
+ sleep(POLL_TIME);
+ }
+
+ int firedFlags = receiver.getFiredFlags();
+ removeReceiver(receiver);
+ fail(String.format("connectInput() timeout: device=%s, state=%d (expected %d), "
+ + "flags=0x%x (expected 0x%s)", device, state, BluetoothInputDevice.STATE_CONNECTED,
+ firedFlags, mask));
+ }
+
+ /**
+ * Disconnects the local device with a remote HID device and checks to make sure that the
+ * profile is connected and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void disconnectInput(BluetoothAdapter adapter, BluetoothDevice device) {
+ int mask = (ConnectInputReceiver.STATE_DISCONNECTING_FLAG
+ | ConnectInputReceiver.STATE_DISCONNECTED_FLAG);
+ long start = -1;
+
+ if (!adapter.isEnabled()) {
+ fail(String.format("disconnectInput() bluetooth not enabled: device=%s", device));
+ }
+
+ if (!adapter.getBondedDevices().contains(device)) {
+ fail(String.format("disconnectInput() device not paired: device=%s", device));
+ }
+
+ BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
+ assertNotNull(inputDevice);
+ ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
+
+ int state = inputDevice.getInputDeviceState(device);
+ switch (state) {
+ case BluetoothInputDevice.STATE_CONNECTED:
+ case BluetoothInputDevice.STATE_CONNECTING:
+ start = System.currentTimeMillis();
+ assertTrue(inputDevice.disconnectInputDevice(device));
+ break;
+ case BluetoothInputDevice.STATE_DISCONNECTED:
+ removeReceiver(receiver);
+ return;
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ mask = 0; // Don't check for received intents since we might have missed them.
+ break;
+ default:
+ removeReceiver(receiver);
+ fail(String.format("disconnectInput() invalid state: device=%s, state=%d", device,
+ state));
+ }
+
+ long s = System.currentTimeMillis();
+ while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+ state = inputDevice.getInputDeviceState(device);
+ if (state == BluetoothInputDevice.STATE_DISCONNECTED
+ && (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("disconnectInput() completed in %d ms: device=%s",
+ (finish - start), device));
+ } else {
+ writeOutput(String.format("disconnectInput() completed: device=%s", device));
+ }
+ removeReceiver(receiver);
+ return;
+ }
+ sleep(POLL_TIME);
+ }
+
+ int firedFlags = receiver.getFiredFlags();
+ removeReceiver(receiver);
+ fail(String.format("disconnectInput() timeout: device=%s, state=%d (expected %d), "
+ + "flags=0x%x (expected 0x%s)", device, state,
+ BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
+ }
+
+ /**
+ * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
+ * the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void connectPan(BluetoothAdapter adapter, BluetoothDevice device) {
+ connectPanOrIncomingPanConnection(adapter, device, true);
+ }
+
+ /**
+ * Checks that a remote PANU connects to the local NAP correctly and that the correct actions
+ * were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void incomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device) {
+ connectPanOrIncomingPanConnection(adapter, device, false);
+ }
+
+ /**
+ * Helper method used by {@link #connectPan(BluetoothAdapter, BluetoothDevice)} and
+ * {@link #incomingPanConnection(BluetoothAdapter, BluetoothDevice)} to either connect to a
+ * remote NAP or verify that a remote device connected to the local NAP.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param connect If the method should initiate the connection (is PANU)
+ */
+ private void connectPanOrIncomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device,
+ boolean connect) {
+ long start = -1;
+ int mask, role;
+ String methodName;
+
+ if (connect) {
+ methodName = "connectPan()";
+ mask = (ConnectPanReceiver.STATE_CONNECTED_FLAG |
+ ConnectPanReceiver.STATE_CONNECTING_FLAG);
+ role = BluetoothPan.LOCAL_PANU_ROLE;
+ } else {
+ methodName = "incomingPanConnection()";
+ mask = ConnectPanReceiver.STATE_CONNECTED_FLAG;
+ role = BluetoothPan.LOCAL_NAP_ROLE;
+ }
+
+ if (!adapter.isEnabled()) {
+ fail(String.format("%s bluetooth not enabled: device=%s", methodName, device));
+ }
+
+ if (!adapter.getBondedDevices().contains(device)) {
+ fail(String.format("%s device not paired: device=%s", methodName, device));
+ }
+
+ BluetoothPan pan = new BluetoothPan(mContext);
+ assertNotNull(pan);
+ ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
+
+ int state = pan.getPanDeviceState(device);
+ switch (state) {
+ case BluetoothPan.STATE_CONNECTED:
+ removeReceiver(receiver);
+ return;
+ case BluetoothPan.STATE_CONNECTING:
+ mask = 0; // Don't check for received intents since we might have missed them.
+ break;
+ case BluetoothPan.STATE_DISCONNECTED:
+ case BluetoothPan.STATE_DISCONNECTING:
+ start = System.currentTimeMillis();
+ if (role == BluetoothPan.LOCAL_PANU_ROLE) {
+ Log.i("BT", "connect to pan");
+ assertTrue(pan.connect(device));
+ }
+ break;
+ default:
+ removeReceiver(receiver);
+ fail(String.format("%s invalid state: device=%s, state=%d", methodName, device,
+ state));
+ }
+
+ long s = System.currentTimeMillis();
+ while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+ state = pan.getPanDeviceState(device);
+ if (state == BluetoothPan.STATE_CONNECTED
+ && (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
+ (finish - start), device));
+ } else {
+ writeOutput(String.format("%s completed: device=%s", methodName, device));
+ }
+ removeReceiver(receiver);
+ return;
+ }
+ sleep(POLL_TIME);
+ }
+
+ int firedFlags = receiver.getFiredFlags();
+ removeReceiver(receiver);
+ fail(String.format("%s timeout: device=%s, state=%d (expected %d), "
+ + "flags=0x%x (expected 0x%s)", methodName, device, state,
+ BluetoothPan.STATE_CONNECTED, firedFlags, mask));
+ }
+
+ /**
+ * Disconnects the PANU from a remote NAP and checks to make sure that the PANU is disconnected
+ * and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void disconnectPan(BluetoothAdapter adapter, BluetoothDevice device) {
+ disconnectFromRemoteOrVerifyConnectNap(adapter, device, true);
+ }
+
+ /**
+ * Checks that a remote PANU disconnects from the local NAP correctly and that the correct
+ * actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void incomingPanDisconnection(BluetoothAdapter adapter, BluetoothDevice device) {
+ disconnectFromRemoteOrVerifyConnectNap(adapter, device, false);
+ }
+
+ /**
+ * Helper method used by {@link #disconnectPan(BluetoothAdapter, BluetoothDevice)} and
+ * {@link #incomingPanDisconnection(BluetoothAdapter, BluetoothDevice)} to either disconnect
+ * from a remote NAP or verify that a remote device disconnected from the local NAP.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param disconnect Whether the method should connect or verify.
+ */
+ private void disconnectFromRemoteOrVerifyConnectNap(BluetoothAdapter adapter,
+ BluetoothDevice device, boolean disconnect) {
+ long start = -1;
+ int mask, role;
+ String methodName;
+
+ if (disconnect) {
+ methodName = "disconnectPan()";
+ mask = (ConnectPanReceiver.STATE_DISCONNECTED_FLAG |
+ ConnectPanReceiver.STATE_DISCONNECTING_FLAG);
+ role = BluetoothPan.LOCAL_PANU_ROLE;
+ } else {
+ methodName = "incomingPanDisconnection()";
+ mask = ConnectPanReceiver.STATE_DISCONNECTED_FLAG;
+ role = BluetoothPan.LOCAL_NAP_ROLE;
+ }
+
+ if (!adapter.isEnabled()) {
+ fail(String.format("%s bluetooth not enabled: device=%s", methodName, device));
+ }
+
+ if (!adapter.getBondedDevices().contains(device)) {
+ fail(String.format("%s device not paired: device=%s", methodName, device));
+ }
+
+ BluetoothPan pan = new BluetoothPan(mContext);
+ assertNotNull(pan);
+ ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
+
+ int state = pan.getPanDeviceState(device);
+ switch (state) {
+ case BluetoothInputDevice.STATE_CONNECTED:
+ case BluetoothInputDevice.STATE_CONNECTING:
+ start = System.currentTimeMillis();
+ if (role == BluetoothPan.LOCAL_PANU_ROLE) {
+ assertTrue(pan.disconnect(device));
+ }
+ break;
+ case BluetoothInputDevice.STATE_DISCONNECTED:
+ removeReceiver(receiver);
+ return;
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ mask = 0; // Don't check for received intents since we might have missed them.
+ break;
+ default:
+ removeReceiver(receiver);
+ fail(String.format("%s invalid state: device=%s, state=%d", methodName, device,
+ state));
+ }
+
+ long s = System.currentTimeMillis();
+ while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+ state = pan.getPanDeviceState(device);
+ if (state == BluetoothInputDevice.STATE_DISCONNECTED
+ && (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
+ (finish - start), device));
+ } else {
+ writeOutput(String.format("%s completed: device=%s", methodName, device));
+ }
+ removeReceiver(receiver);
+ return;
+ }
+ sleep(POLL_TIME);
+ }
+
+ int firedFlags = receiver.getFiredFlags();
+ removeReceiver(receiver);
+ fail(String.format("%s timeout: device=%s, state=%d (expected %d), "
+ + "flags=0x%x (expected 0x%s)", methodName, device, state,
+ BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
+ }
+
+ /**
+ * Writes a string to the logcat and a file if a file has been specified in the constructor.
+ *
+ * @param s The string to be written.
+ */
public void writeOutput(String s) {
Log.i(mTag, s);
if (mOutputWriter == null) {
@@ -902,38 +1444,60 @@
}
}
- private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
- BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
+ private void addReceiver(BroadcastReceiver receiver, String[] actions) {
IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
- filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
- filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ for (String action: actions) {
+ filter.addAction(action);
+ }
mContext.registerReceiver(receiver, filter);
mReceivers.add(receiver);
+ }
+
+ private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
+ String[] actions = {
+ BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
+ BluetoothAdapter.ACTION_DISCOVERY_STARTED,
+ BluetoothAdapter.ACTION_SCAN_MODE_CHANGED,
+ BluetoothAdapter.ACTION_STATE_CHANGED};
+ BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
+ addReceiver(receiver, actions);
return receiver;
}
private PairReceiver getPairReceiver(BluetoothDevice device, int passkey, byte[] pin,
int expectedFlags) {
+ String[] actions = {
+ BluetoothDevice.ACTION_PAIRING_REQUEST,
+ BluetoothDevice.ACTION_BOND_STATE_CHANGED};
PairReceiver receiver = new PairReceiver(device, passkey, pin, expectedFlags);
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
- filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- mContext.registerReceiver(receiver, filter);
- mReceivers.add(receiver);
+ addReceiver(receiver, actions);
return receiver;
}
private ConnectProfileReceiver getConnectProfileReceiver(BluetoothDevice device, int profile,
int expectedFlags) {
+ String[] actions = {
+ BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
+ BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED};
ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
expectedFlags);
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
- filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
- mContext.registerReceiver(receiver, filter);
- mReceivers.add(receiver);
+ addReceiver(receiver, actions);
+ return receiver;
+ }
+
+ private ConnectInputReceiver getConnectInputReceiver(BluetoothDevice device,
+ int expectedFlags) {
+ String[] actions = {BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED};
+ ConnectInputReceiver receiver = new ConnectInputReceiver(device, expectedFlags);
+ addReceiver(receiver, actions);
+ return receiver;
+ }
+
+ private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
+ int expectedFlags) {
+ String[] actions = {BluetoothPan.ACTION_PAN_STATE_CHANGED};
+ ConnectPanReceiver receiver = new ConnectPanReceiver(device, role, expectedFlags);
+ addReceiver(receiver, actions);
return receiver;
}
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index ca934ec..746597f 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -464,37 +464,28 @@
<li><a href="<?cs var:toroot ?>guide/developing/tools/mksdcard.html">mksdcard</a></li>
<li><a href="/guide/developing/tools/monkey.html">Monkey</a></li>
- <li class="toggle-list">
- <div>
- <a href="/guide/developing/tools/monkeyrunner_concepts.html">
- <span class="en">monkeyrunner</span>
- </a>
- </div>
- <ul>
- <li>
- <a href="/guide/developing/tools/MonkeyDevice.html">
- <span class="en">MonkeyDevice</span>
- </a>
- </li>
- <li>
- <a href="/guide/developing/tools/MonkeyImage.html">
- <span class="en">MonkeyImage</span>
- </a>
- </li>
- <li>
- <a href="/guide/developing/tools/MonkeyRunner.html">
- <span class="en">MonkeyRunner</span>
- </a>
- </li>
- </ul>
- </li>
- <li><a href="<?cs var:toroot ?>guide/developing/tools/proguard.html">ProGuard</a>
-<span class="new">new!</span></li>
- <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
- <li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html" >Traceview</a></li>
- <li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html" >zipalign</a></li>
- </ul>
- </li>
+ <li class="toggle-list">
+ <div><a href="/guide/developing/tools/monkeyrunner_concepts.html">
+ <span class="en">monkeyrunner</span>
+ </a></div>
+ <ul>
+ <li><a href="/guide/developing/tools/MonkeyDevice.html">
+ <span class="en">MonkeyDevice</span>
+ </a></li>
+ <li><a href="/guide/developing/tools/MonkeyImage.html">
+ <span class="en">MonkeyImage</span>
+ </a></li>
+ <li><a href="/guide/developing/tools/MonkeyRunner.html">
+ <span class="en">MonkeyRunner</span>
+ </a></li>
+ </ul>
+ </li>
+ <li><a href="/guide/developing/tools/proguard.html">ProGuard</a></li>
+ <li><a href="/guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
+ <li><a href="/guide/developing/tools/traceview.html">Traceview</a></li>
+ <li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html">zipalign</a></li>
+ </ul>
+ </li>
</ul>
</li>
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index b6e0c30..ef7d274 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -87,7 +87,7 @@
}
status_t DrmManager::loadPlugIns() {
- String8 pluginDirPath("/system/lib/drm/plugins/native");
+ String8 pluginDirPath("/system/lib/drm");
return loadPlugIns(pluginDirPath);
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 63b87b1..a618423 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -328,6 +328,7 @@
public void run() {
Log.i(TAG, "VPN connectivity monitor running");
try {
+ mNotification.update(mStartTime); // to pop up notification
for (int i = 10; ; i--) {
long now = System.currentTimeMillis();
@@ -417,13 +418,27 @@
// Helper class for showing, updating notification.
private class NotificationHelper {
+ private NotificationManager mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ private Notification mNotification =
+ new Notification(R.drawable.vpn_connected, null, 0L);
+ private PendingIntent mPendingIntent = PendingIntent.getActivity(
+ mContext, 0,
+ new VpnManager(mContext).createSettingsActivityIntent(), 0);
+ private String mConnectedTitle;
+
void update(long now) {
- String title = getNotificationTitle(true);
- Notification n = new Notification(R.drawable.vpn_connected, title,
- mStartTime);
- n.setLatestEventInfo(mContext, title,
+ Notification n = mNotification;
+ if (now == mStartTime) {
+ // to pop up the notification for the first time
+ n.when = mStartTime;
+ n.tickerText = mConnectedTitle = getNotificationTitle(true);
+ } else {
+ n.tickerText = null;
+ }
+ n.setLatestEventInfo(mContext, mConnectedTitle,
getConnectedNotificationMessage(now),
- prepareNotificationIntent());
+ mPendingIntent);
n.flags |= Notification.FLAG_NO_CLEAR;
n.flags |= Notification.FLAG_ONGOING_EVENT;
enableNotification(n);
@@ -435,25 +450,18 @@
title, System.currentTimeMillis());
n.setLatestEventInfo(mContext, title,
getDisconnectedNotificationMessage(),
- prepareNotificationIntent());
+ mPendingIntent);
n.flags |= Notification.FLAG_AUTO_CANCEL;
disableNotification();
enableNotification(n);
}
void disableNotification() {
- ((NotificationManager) mContext.getSystemService(
- Context.NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID);
+ mNotificationManager.cancel(NOTIFICATION_ID);
}
private void enableNotification(Notification n) {
- ((NotificationManager) mContext.getSystemService(
- Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, n);
- }
-
- private PendingIntent prepareNotificationIntent() {
- return PendingIntent.getActivity(mContext, 0,
- new VpnManager(mContext).createSettingsActivityIntent(), 0);
+ mNotificationManager.notify(NOTIFICATION_ID, n);
}
private String getNotificationTitle(boolean connected) {
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 5e33f05..1f06dcc 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -221,7 +221,8 @@
final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
ab.setAdapter(mAdapter, this)
- .setInverseBackgroundForced(true);
+ .setInverseBackgroundForced(true)
+ .setTitle(R.string.global_actions);
final AlertDialog dialog = ab.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
@@ -248,7 +249,6 @@
} else {
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
}
- mDialog.setTitle(R.string.global_actions);
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 2321e30..d0df6cf 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2129,7 +2129,8 @@
if (proxy == null) proxy = new ProxyProperties("", 0, "");
log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
mContext.sendStickyBroadcast(intent);
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
old mode 100755
new mode 100644
index dbf9a96..3b1b8c4
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -9577,7 +9577,7 @@
// r.record is null if findServiceLocked() failed the caller permission check
if (r.record == null) {
throw new SecurityException(
- "Permission Denial: Accessing service "
+ "Permission Denial: Accessing service " + r.record.name
+ " from pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
+ " requires " + r.permission);
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index d0f3d24..df12153 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -17,16 +17,43 @@
package com.android.internal.telephony;
+/**
+ * This is RIL_Data_Call_Response_v5 from ril.h
+ * TODO: Rename to DataCallResponse.
+ */
public class DataCallState {
- public int cid;
- public int active;
- public String type;
- public String apn;
- public String address;
+ public int version = 0;
+ public int status = 0;
+ public int cid = 0;
+ public int active = 0;
+ public String type = "";
+ public String ifname = "";
+ public String [] addresses = new String[0];
+ public String [] dnses = new String[0];
@Override
public String toString() {
- return "DataCallState: {" + " cid: " + cid + ", active: " + active + ", type: " + type
- + ", apn: " + apn + ", address: " + address + " }";
+ StringBuffer sb = new StringBuffer();
+ sb.append("DataCallState: {")
+ .append("version=").append(version)
+ .append(" status=").append(status)
+ .append(" cid=").append(cid)
+ .append(" active=").append(active)
+ .append(" type=").append(type)
+ .append("' ifname='").append(ifname);
+ sb.append("' addresses=[");
+ for (String addr : addresses) {
+ sb.append(addr);
+ sb.append(",");
+ }
+ if (addresses.length > 0) sb.deleteCharAt(sb.length()-1);
+ sb.append("] dnses=[");
+ for (String addr : dnses) {
+ sb.append(addr);
+ sb.append(",");
+ }
+ if (dnses.length > 0) sb.deleteCharAt(sb.length()-1);
+ sb.append("]}");
+ return sb.toString();
}
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index c143424..31c89d0 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -27,13 +27,11 @@
import android.os.Message;
import android.os.SystemProperties;
import android.text.TextUtils;
-import android.util.EventLog;
import java.net.InetAddress;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
+import java.net.Inet4Address;
import java.net.UnknownHostException;
+import java.util.HashMap;
/**
* {@hide}
@@ -55,48 +53,6 @@
* <code>AsyncResult.exception = new Exception()</code>.
*
* The other public methods are provided for debugging.
- *
- * Below is the state machine description for this class.
- *
- * DataConnection {
- * + mDefaultState {
- * EVENT_RESET { clearSettings, notifiyDisconnectCompleted, >mInactiveState }.
- * EVENT_CONNECT { notifyConnectCompleted(FailCause.UNKNOWN) }.
- * EVENT_DISCONNECT { notifyDisconnectCompleted }.
- *
- * // Ignored messages
- * EVENT_SETUP_DATA_CONNECTION_DONE,
- * EVENT_GET_LAST_FAIL_DONE,
- * EVENT_DEACTIVATE_DONE.
- * }
- * ++ # mInactiveState
- * e(doNotifications)
- * x(clearNotifications) {
- * EVENT_RESET { notifiyDisconnectCompleted }.
- * EVENT_CONNECT {startConnecting, >mActivatingState }.
- * }
- * ++ mActivatingState {
- * EVENT_DISCONNECT { %EVENT_DISCONNECT }.
- * EVENT_SETUP_DATA_CONNECTION_DONE {
- * if (SUCCESS) { notifyConnectCompleted(FailCause.NONE), >mActiveState }.
- * if (ERR_BadCommand) {
- * notifyConnectCompleted(FailCause.UNKNOWN), >mInactiveState }.
- * if (ERR_BadDns) { tearDownData($DEACTIVATE_DONE), >mDisconnectingBadDnsState }.
- * if (ERR_Other) { getLastDataCallFailCause($EVENT_GET_LAST_FAIL_DONE) }.
- * if (ERR_Stale) {}.
- * }
- * EVENT_GET_LAST_FAIL_DONE { notifyConnectCompleted(result), >mInactive }.
- * }
- * ++ mActiveState {
- * EVENT_DISCONNECT { tearDownData($EVENT_DEACTIVATE_DONE), >mDisconnecting }.
- * }
- * ++ mDisconnectingState {
- * EVENT_DEACTIVATE_DONE { notifyDisconnectCompleted, >mInactiveState }.
- * }
- * ++ mDisconnectingBadDnsState {
- * EVENT_DEACTIVATE_DONE { notifyConnectComplete(FailCause.UNKNOWN), >mInactiveState }.
- * }
- * }
*/
public abstract class DataConnection extends HierarchicalStateMachine {
protected static final boolean DBG = true;
@@ -108,24 +64,22 @@
* Class returned by onSetupConnectionCompleted.
*/
protected enum SetupResult {
+ SUCCESS,
ERR_BadCommand,
- ERR_BadDns,
- ERR_Other,
+ ERR_UnacceptableParameter,
+ ERR_GetLastErrorFromRil,
ERR_Stale,
- SUCCESS;
+ ERR_RilError;
public FailCause mFailCause;
+ SetupResult() {
+ mFailCause = FailCause.fromInt(0);
+ }
+
@Override
public String toString() {
- switch (this) {
- case ERR_BadCommand: return "Bad Command";
- case ERR_BadDns: return "Bad DNS";
- case ERR_Other: return "Other error";
- case ERR_Stale: return "Stale command";
- case SUCCESS: return "SUCCESS";
- default: return "unknown";
- }
+ return name() + " SetupResult.mFailCause=" + mFailCause;
}
}
@@ -167,31 +121,66 @@
}
/**
- * Returned as the reason for a connection failure.
+ * Returned as the reason for a connection failure as defined
+ * by RIL_DataCallFailCause in ril.h and some local errors.
*/
public enum FailCause {
- NONE,
- OPERATOR_BARRED,
- INSUFFICIENT_RESOURCES,
- MISSING_UNKNOWN_APN,
- UNKNOWN_PDP_ADDRESS,
- USER_AUTHENTICATION,
- ACTIVATION_REJECT_GGSN,
- ACTIVATION_REJECT_UNSPECIFIED,
- SERVICE_OPTION_NOT_SUPPORTED,
- SERVICE_OPTION_NOT_SUBSCRIBED,
- SERVICE_OPTION_OUT_OF_ORDER,
- NSAPI_IN_USE,
- PROTOCOL_ERRORS,
- REGISTRATION_FAIL,
- GPRS_REGISTRATION_FAIL,
- UNKNOWN,
+ NONE(0),
- RADIO_NOT_AVAILABLE;
+ // This series of errors as specified by the standards
+ // specified in ril.h
+ OPERATOR_BARRED(0x08),
+ INSUFFICIENT_RESOURCES(0x1A),
+ MISSING_UNKNOWN_APN(0x1B),
+ UNKNOWN_PDP_ADDRESS_TYPE(0x1C),
+ USER_AUTHENTICATION(0x1D),
+ ACTIVATION_REJECT_GGSN(0x1E),
+ ACTIVATION_REJECT_UNSPECIFIED(0x1F),
+ SERVICE_OPTION_NOT_SUPPORTED(0x20),
+ SERVICE_OPTION_NOT_SUBSCRIBED(0x21),
+ SERVICE_OPTION_OUT_OF_ORDER(0x22),
+ NSAPI_IN_USE(0x23),
+ ONLY_IPV4_ALLOWED(0x32),
+ ONLY_IPV6_ALLOWED(0x33),
+ ONLY_SINGLE_BEARER_ALLOWED(0x34),
+ PROTOCOL_ERRORS(0x6F),
+
+ // Local errors generated by Vendor RIL
+ // specified in ril.h
+ REGISTRATION_FAIL(-1),
+ GPRS_REGISTRATION_FAIL(-2),
+ SIGNAL_LOST(-3),
+ PREF_RADIO_TECH_CHANGED(-4),
+ RADIO_POWER_OFF(-5),
+ TETHERED_CALL_ACTIVE(-6),
+ ERROR_UNSPECIFIED(0xFFFF),
+
+ // Errors generated by the Framework
+ // specified here
+ UNKNOWN(0x10000),
+ RADIO_NOT_AVAILABLE(0x10001),
+ UNACCEPTABLE_NETWORK_PARAMETER(0x10002);
+
+ private final int mErrorCode;
+ private static final HashMap<Integer, FailCause> sErrorCodeToFailCauseMap;
+ static {
+ sErrorCodeToFailCauseMap = new HashMap<Integer, FailCause>();
+ for (FailCause fc : values()) {
+ sErrorCodeToFailCauseMap.put(fc.ordinal(), fc);
+ }
+ }
+
+ FailCause(int errorCode) {
+ mErrorCode = errorCode;
+ }
+
+ int getErrorCode() {
+ return mErrorCode;
+ }
public boolean isPermanentFail() {
return (this == OPERATOR_BARRED) || (this == MISSING_UNKNOWN_APN) ||
- (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) ||
+ (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
(this == SERVICE_OPTION_NOT_SUPPORTED) ||
(this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == NSAPI_IN_USE) ||
(this == PROTOCOL_ERRORS);
@@ -199,52 +188,21 @@
public boolean isEventLoggable() {
return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
- (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) ||
+ (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
(this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
(this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
(this == SERVICE_OPTION_NOT_SUPPORTED) ||
(this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
- (this == PROTOCOL_ERRORS);
+ (this == PROTOCOL_ERRORS) ||
+ (this == UNACCEPTABLE_NETWORK_PARAMETER);
}
- @Override
- public String toString() {
- switch (this) {
- case NONE:
- return "No Error";
- case OPERATOR_BARRED:
- return "Operator Barred";
- case INSUFFICIENT_RESOURCES:
- return "Insufficient Resources";
- case MISSING_UNKNOWN_APN:
- return "Missing / Unknown APN";
- case UNKNOWN_PDP_ADDRESS:
- return "Unknown PDP Address";
- case USER_AUTHENTICATION:
- return "Error User Authentication";
- case ACTIVATION_REJECT_GGSN:
- return "Activation Reject GGSN";
- case ACTIVATION_REJECT_UNSPECIFIED:
- return "Activation Reject unspecified";
- case SERVICE_OPTION_NOT_SUPPORTED:
- return "Data Not Supported";
- case SERVICE_OPTION_NOT_SUBSCRIBED:
- return "Data Not subscribed";
- case SERVICE_OPTION_OUT_OF_ORDER:
- return "Data Services Out of Order";
- case NSAPI_IN_USE:
- return "NSAPI in use";
- case PROTOCOL_ERRORS:
- return "Protocol Errors";
- case REGISTRATION_FAIL:
- return "Network Registration Failure";
- case GPRS_REGISTRATION_FAIL:
- return "Data Network Registration Failure";
- case RADIO_NOT_AVAILABLE:
- return "Radio Not Available";
- default:
- return "Unknown Data Error";
+ public static FailCause fromInt(int errorCode) {
+ FailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
+ if (fc == null) {
+ fc = UNKNOWN;
}
+ return fc;
}
}
@@ -274,12 +232,11 @@
Object userData;
//***** Abstract methods
+ @Override
public abstract String toString();
protected abstract void onConnect(ConnectionParams cp);
- protected abstract FailCause getFailCauseFromRequest(int rilCause);
-
protected abstract boolean isDnsOk(String[] domainNameServers);
protected abstract void log(String s);
@@ -300,7 +257,7 @@
addState(mActivatingState, mDefaultState);
addState(mActiveState, mDefaultState);
addState(mDisconnectingState, mDefaultState);
- addState(mDisconnectingBadDnsState, mDefaultState);
+ addState(mDisconnectingErrorCreatingConnection, mDefaultState);
setInitialState(mInactiveState);
if (DBG) log("DataConnection constructor X");
}
@@ -408,20 +365,26 @@
* @return SetupResult.
*/
private SetupResult onSetupConnectionCompleted(AsyncResult ar) {
- SetupResult result;
- String[] response = ((String[]) ar.result);
+ DataCallState response = (DataCallState) ar.result;
ConnectionParams cp = (ConnectionParams) ar.userObj;
+ SetupResult result;
if (ar.exception != null) {
- if (DBG) log("DataConnection Init failed " + ar.exception);
+ if (DBG) {
+ log("onSetupConnectionCompleted failed, ar.exception=" + ar.exception +
+ " response=" + response);
+ }
if (ar.exception instanceof CommandException
&& ((CommandException) (ar.exception)).getCommandError()
== CommandException.Error.RADIO_NOT_AVAILABLE) {
result = SetupResult.ERR_BadCommand;
result.mFailCause = FailCause.RADIO_NOT_AVAILABLE;
+ } else if ((response == null) || (response.version < 4)) {
+ result = SetupResult.ERR_GetLastErrorFromRil;
} else {
- result = SetupResult.ERR_Other;
+ result = SetupResult.ERR_RilError;
+ result.mFailCause = FailCause.fromInt(response.status);
}
} else if (cp.tag != mTag) {
if (DBG) {
@@ -429,69 +392,93 @@
}
result = SetupResult.ERR_Stale;
} else {
-// log("onSetupConnectionCompleted received " + response.length + " response strings:");
-// for (int i = 0; i < response.length; i++) {
-// log(" response[" + i + "]='" + response[i] + "'");
-// }
+ 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.length >= 2) {
- cid = Integer.parseInt(response[0]);
- String interfaceName = response[1];
- result = SetupResult.SUCCESS;
-
+ if (response.status == FailCause.NONE.getErrorCode()) {
try {
- String prefix = "net." + interfaceName + ".";
-
- NetworkInterface networkInterface = NetworkInterface.getByName(interfaceName);
- linkProperties.setInterfaceName(interfaceName);
-
- // TODO: Get gateway and dns via RIL interface not property?
- String gatewayAddress = SystemProperties.get(prefix + "gw");
- linkProperties.setGateway(InetAddress.getByName(gatewayAddress));
-
- for (InterfaceAddress addr : networkInterface.getInterfaceAddresses()) {
- linkProperties.addLinkAddress(new LinkAddress(addr));
+ cid = response.cid;
+ linkProperties.setInterfaceName(response.ifname);
+ for (String addr : response.addresses) {
+ LinkAddress la;
+ if (!InetAddress.isNumeric(addr)) {
+ EventLogTags.writeBadIpAddress(addr);
+ throw new UnknownHostException("Non-numeric ip addr=" + addr);
+ }
+ InetAddress ia = InetAddress.getByName(addr);
+ if (ia instanceof Inet4Address) {
+ la = new LinkAddress(ia, 32);
+ } else {
+ la = new LinkAddress(ia, 128);
+ }
+ linkProperties.addLinkAddress(la);
}
- // TODO: Get gateway and dns via RIL interface not property?
- String dnsServers[] = new String[2];
- dnsServers[0] = SystemProperties.get(prefix + "dns1");
- dnsServers[1] = SystemProperties.get(prefix + "dns2");
- if (isDnsOk(dnsServers)) {
- linkProperties.addDns(InetAddress.getByName(dnsServers[0]));
- linkProperties.addDns(InetAddress.getByName(dnsServers[1]));
+
+ if (response.dnses.length != 0) {
+ for (String addr : response.dnses) {
+ if (!InetAddress.isNumeric(addr)) {
+ EventLogTags.writePdpBadDnsAddress("dns=" + addr);
+ throw new UnknownHostException("Non-numeric dns addr=" + addr);
+ }
+ InetAddress ia = InetAddress.getByName(addr);
+ linkProperties.addDns(ia);
+ }
+ result = SetupResult.SUCCESS;
} else {
- result = SetupResult.ERR_BadDns;
+ String prefix = "net." + response.ifname + ".";
+
+ String dnsServers[] = new String[2];
+ dnsServers[0] = SystemProperties.get(prefix + "dns1");
+ dnsServers[1] = SystemProperties.get(prefix + "dns2");
+ if (isDnsOk(dnsServers)) {
+ for (String dnsAddr : dnsServers) {
+ if (!InetAddress.isNumeric(dnsAddr)) {
+ EventLogTags.writePdpBadDnsAddress("dnsAddr=" + dnsAddr);
+ throw new UnknownHostException("Non-numeric dns addr="
+ + dnsAddr);
+ }
+ InetAddress ia = InetAddress.getByName(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);
+ }
}
- } catch (UnknownHostException e1) {
- log("onSetupCompleted: UnknowHostException " + e1);
- e1.printStackTrace();
- result = SetupResult.ERR_Other;
- } catch (SocketException e2) {
- log("onSetupCompleted: SocketException " + e2);
- e2.printStackTrace();
- result = SetupResult.ERR_Other;
+ } catch (UnknownHostException e) {
+ log("onSetupCompleted: UnknownHostException " + e);
+ e.printStackTrace();
+ result = SetupResult.ERR_UnacceptableParameter;
}
} else {
- log("onSetupCompleted: error; expected number of responses >= 2 was " +
- response.length);
- result = SetupResult.ERR_Other;
+ if (response.version < 4) {
+ result = SetupResult.ERR_GetLastErrorFromRil;
+ } else {
+ result = SetupResult.ERR_RilError;
+ }
}
// An error occurred so clear properties
if (result != SetupResult.SUCCESS) {
- log("onSetupCompleted with an error clearing LinkProperties");
+ log("onSetupConnectionCompleted with an error, clearing LinkProperties");
linkProperties.clear();
}
mLinkProperties = linkProperties;
}
if (DBG) {
- log("DataConnection setup result='" + result + "' on cid=" + cid);
+ log("onSetupConnectionCompleted: DataConnection setup result='"
+ + result + "' on cid=" + cid);
if (result == SetupResult.SUCCESS) {
- log("LinkProperties: " + mLinkProperties.toString());
+ log("onSetupConnectionCompleted: LinkProperties: " + mLinkProperties.toString());
}
}
return result;
@@ -640,6 +627,7 @@
cp = (ConnectionParams) ar.userObj;
SetupResult result = onSetupConnectionCompleted(ar);
+ if (DBG) log("DcActivatingState onSetupConnectionCompleted result=" + result);
switch (result) {
case SUCCESS:
// All is well
@@ -653,26 +641,21 @@
mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
transitionTo(mInactiveState);
break;
- case ERR_BadDns:
- // Connection succeeded but DNS info is bad so disconnect
- StringBuilder dnsAddressesSb = new StringBuilder();
- for (InetAddress addr : mLinkProperties.getDnses()) {
- if (dnsAddressesSb.length() != 0) dnsAddressesSb.append(" ");
- dnsAddressesSb.append(addr.toString());
- }
- if (dnsAddressesSb.length() == 0) {
- dnsAddressesSb.append("no-dns-addresses");
- }
- EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS,
- dnsAddressesSb.toString());
+ case ERR_UnacceptableParameter:
+ // The addresses given from the RIL are bad
tearDownData(cp);
- transitionTo(mDisconnectingBadDnsState);
+ transitionTo(mDisconnectingErrorCreatingConnection);
break;
- case ERR_Other:
- // Request the failure cause and process in this state
+ case ERR_GetLastErrorFromRil:
+ // Request failed and this is an old RIL
phone.mCM.getLastDataCallFailCause(
obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp));
break;
+ case ERR_RilError:
+ // Request failed and mFailCause has the reason
+ mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+ transitionTo(mInactiveState);
+ break;
case ERR_Stale:
// Request is stale, ignore.
break;
@@ -691,7 +674,7 @@
if (DBG) log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE");
if (ar.exception == null) {
int rilFailCause = ((int[]) (ar.result))[0];
- cause = getFailCauseFromRequest(rilFailCause);
+ cause = FailCause.fromInt(rilFailCause);
}
// Transition to inactive but send notifications after
// we've entered the mInactive state.
@@ -808,10 +791,9 @@
private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
/**
- * The state machine is disconnecting after a bad dns setup
- * was found in mInactivatingState.
+ * The state machine is disconnecting after an creating a connection.
*/
- private class DcDisconnectingBadDnsState extends HierarchicalState {
+ private class DcDisconnectionErrorCreatingConnection extends HierarchicalState {
@Override protected boolean processMessage(Message msg) {
boolean retVal;
@@ -820,27 +802,38 @@
AsyncResult ar = (AsyncResult) msg.obj;
ConnectionParams cp = (ConnectionParams) ar.userObj;
if (cp.tag == mTag) {
- if (DBG) log("DcDisconnectingBadDnsState msg.what=EVENT_DEACTIVATE_DONE");
+ if (DBG) {
+ log("DcDisconnectionErrorCreatingConnection" +
+ " msg.what=EVENT_DEACTIVATE_DONE");
+ }
+
// Transition to inactive but send notifications after
// we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams(cp, FailCause.UNKNOWN);
+ mInactiveState.setEnterNotificationParams(cp,
+ FailCause.UNACCEPTABLE_NETWORK_PARAMETER);
transitionTo(mInactiveState);
} else {
- if (DBG) log("DcDisconnectingBadDnsState EVENT_DEACTIVE_DONE stale dp.tag="
- + cp.tag + ", mTag=" + mTag);
+ if (DBG) {
+ log("DcDisconnectionErrorCreatingConnection EVENT_DEACTIVATE_DONE" +
+ " stale dp.tag=" + cp.tag + ", mTag=" + mTag);
+ }
}
retVal = true;
break;
default:
- if (DBG) log("DcDisconnectingBadDnsState not handled msg.what=" + msg.what);
+ if (DBG) {
+ log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+ + msg.what);
+ }
retVal = false;
break;
}
return retVal;
}
}
- private DcDisconnectingBadDnsState mDisconnectingBadDnsState = new DcDisconnectingBadDnsState();
+ private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =
+ new DcDisconnectionErrorCreatingConnection();
// ******* public interface
diff --git a/telephony/java/com/android/internal/telephony/EventLogTags.logtags b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
index b06c27d..9be7b80 100644
--- a/telephony/java/com/android/internal/telephony/EventLogTags.logtags
+++ b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
@@ -53,3 +53,6 @@
# CDMA service state transition
50116 cdma_service_state_change (oldState|1|5), (oldDataState|1|5), (newState|1|5), (newDataState|1|5)
+
+# Bad IP address
+50117 bad_ip_address (ip_address|3)
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 7506bb1..ba33454 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -2139,7 +2139,7 @@
case RIL_REQUEST_DTMF: ret = responseVoid(p); break;
case RIL_REQUEST_SEND_SMS: ret = responseSMS(p); break;
case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret = responseSMS(p); break;
- case RIL_REQUEST_SETUP_DATA_CALL: ret = responseStrings(p); break;
+ case RIL_REQUEST_SETUP_DATA_CALL: ret = responseSetupDataCall(p); break;
case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break;
case RIL_REQUEST_SEND_USSD: ret = responseVoid(p); break;
case RIL_REQUEST_CANCEL_USSD: ret = responseVoid(p); break;
@@ -2897,34 +2897,92 @@
return response;
}
- private Object
- responseDataCallList(Parcel p) {
- int num;
- ArrayList<DataCallState> response;
+ private DataCallState getDataCallState(Parcel p, int version) {
+ DataCallState dataCall = new DataCallState();
- num = p.readInt();
- response = new ArrayList<DataCallState>(num);
-
- for (int i = 0; i < num; i++) {
- DataCallState dataCall = new DataCallState();
-
+ dataCall.version = version;
+ if (version < 5) {
dataCall.cid = p.readInt();
dataCall.active = p.readInt();
dataCall.type = p.readString();
- dataCall.apn = p.readString();
- String address = p.readString();
- if (address != null) {
- address = address.split(" ")[0];
+ p.readString(); // Ignore apn
+ String addresses = p.readString();
+ if (addresses != null) {
+ dataCall.addresses = addresses.split(" ");
}
- dataCall.address = address;
+ } else {
+ dataCall.status = p.readInt();
+ dataCall.cid = p.readInt();
+ dataCall.active = p.readInt();
+ dataCall.type = p.readString();
+ dataCall.ifname = p.readString();
+ String addresses = p.readString();
+ if (addresses != null) {
+ dataCall.addresses = addresses.split(" ");
+ }
+ String dnses = p.readString();
+ if (addresses != null) {
+ dataCall.dnses = dnses.split(" ");
+ }
+ }
+ return dataCall;
+ }
- response.add(dataCall);
+ private Object
+ responseDataCallList(Parcel p) {
+ ArrayList<DataCallState> response;
+
+ int ver = p.readInt();
+ int num = p.readInt();
+ Log.d(LOG_TAG, "responseDataCallList ver=" + ver + " num=" + num);
+
+ response = new ArrayList<DataCallState>(num);
+ for (int i = 0; i < num; i++) {
+ response.add(getDataCallState(p, ver));
}
return response;
}
private Object
+ responseSetupDataCall(Parcel p) {
+ int ver = p.readInt();
+ int num = p.readInt();
+ Log.d(LOG_TAG, "responseSetupDataCall ver=" + ver + " num=" + num);
+
+ DataCallState dataCall;
+
+ if (ver < 5) {
+ if (num != 3) {
+ throw new RuntimeException(
+ "RIL_REQUEST_SETUP_DATA_CALL response expecting 3 strings got " + num);
+ }
+ dataCall = new DataCallState();
+ dataCall.cid = Integer.parseInt(p.readString());
+ dataCall.ifname = p.readString();
+ if (dataCall.ifname == null) {
+ throw new RuntimeException(
+ "RIL_REQUEST_SETUP_DATA_CALL response ifname");
+ }
+ String addresses = p.readString();
+ if (addresses == null) {
+ throw new RuntimeException(
+ "RIL_REQUEST_SETUP_DATA_CALL response no addresses");
+ }
+ dataCall.addresses = addresses.split(" ");
+ } else {
+ if (num != 1) {
+ throw new RuntimeException(
+ "RIL_REQUEST_SETUP_DATA_CALL response expecting 1 RIL_Data_Call_response_v5"
+ + " got " + num);
+ }
+ dataCall = getDataCallState(p, ver);
+ }
+
+ return dataCall;
+ }
+
+ private Object
responseNetworkInfos(Parcel p) {
String strings[] = (String [])responseStrings(p);
ArrayList<NetworkInfo> ret;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 1b2c918..1a0dbc2 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -20,6 +20,7 @@
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;
@@ -31,13 +32,6 @@
private static final String LOG_TAG = "CDMA";
- /** Fail cause of last Data Call activate from RIL_LastDataCallActivateFailCause */
- private final static int PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING = 8;
- private final static int PS_NET_DOWN_REASON_AUTH_FAILED = 29;
- private final static int PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED = 32;
- private final static int PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED = 33;
-
-
// ***** Constructor
private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
super(phone, name, rm);
@@ -104,29 +98,6 @@
}
@Override
- protected FailCause getFailCauseFromRequest(int rilCause) {
- FailCause cause;
-
- switch (rilCause) {
- case PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING:
- cause = FailCause.OPERATOR_BARRED;
- break;
- case PS_NET_DOWN_REASON_AUTH_FAILED:
- cause = FailCause.USER_AUTHENTICATION;
- break;
- case PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED:
- cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
- break;
- case PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED:
- cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
- break;
- default:
- cause = FailCause.UNKNOWN;
- }
- return cause;
- }
-
- @Override
protected boolean isDnsOk(String[] domainNameServers) {
if ((NULL_IP.equals(domainNameServers[0])
&& NULL_IP.equals(domainNameServers[1])
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index b947020..1d60bda 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -33,24 +33,6 @@
private static final String LOG_TAG = "GSM";
- /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */
- private static final int PDP_FAIL_OPERATOR_BARRED = 0x08;
- private static final int PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
- private static final int PDP_FAIL_MISSING_UKNOWN_APN = 0x1B;
- private static final int PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
- private static final int PDP_FAIL_USER_AUTHENTICATION = 0x1D;
- private static final int PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
- private static final int PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
- private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
- private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
- private static final int PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
- private static final int PDP_FAIL_NSAPI_IN_USE = 0x23;
- private static final int PDP_FAIL_PROTOCOL_ERRORS = 0x6F;
- private static final int PDP_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
- private static final int PDP_FAIL_REGISTRATION_FAIL = -1;
- private static final int PDP_FAIL_GPRS_REGISTRATION_FAIL = -2;
-
//***** Instance Variables
private ApnSetting apn;
@@ -132,62 +114,6 @@
}
@Override
- protected FailCause getFailCauseFromRequest(int rilCause) {
- FailCause cause;
-
- switch (rilCause) {
- case PDP_FAIL_OPERATOR_BARRED:
- cause = FailCause.OPERATOR_BARRED;
- break;
- case PDP_FAIL_INSUFFICIENT_RESOURCES:
- cause = FailCause.INSUFFICIENT_RESOURCES;
- break;
- case PDP_FAIL_MISSING_UKNOWN_APN:
- cause = FailCause.MISSING_UNKNOWN_APN;
- break;
- case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
- cause = FailCause.UNKNOWN_PDP_ADDRESS;
- break;
- case PDP_FAIL_USER_AUTHENTICATION:
- cause = FailCause.USER_AUTHENTICATION;
- break;
- case PDP_FAIL_ACTIVATION_REJECT_GGSN:
- cause = FailCause.ACTIVATION_REJECT_GGSN;
- break;
- case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
- cause = FailCause.ACTIVATION_REJECT_UNSPECIFIED;
- break;
- case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
- cause = FailCause.SERVICE_OPTION_OUT_OF_ORDER;
- break;
- case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
- cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
- break;
- case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
- cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
- break;
- case PDP_FAIL_NSAPI_IN_USE:
- cause = FailCause.NSAPI_IN_USE;
- break;
- case PDP_FAIL_PROTOCOL_ERRORS:
- cause = FailCause.PROTOCOL_ERRORS;
- break;
- case PDP_FAIL_ERROR_UNSPECIFIED:
- cause = FailCause.UNKNOWN;
- break;
- case PDP_FAIL_REGISTRATION_FAIL:
- cause = FailCause.REGISTRATION_FAIL;
- break;
- case PDP_FAIL_GPRS_REGISTRATION_FAIL:
- cause = FailCause.GPRS_REGISTRATION_FAIL;
- break;
- default:
- cause = FailCause.UNKNOWN;
- }
- return cause;
- }
-
- @Override
protected boolean isDnsOk(String[] domainNameServers) {
if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
&& !((GSMPhone) phone).isDnsCheckDisabled()) {