summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorWink Saville <wink@google.com>2012-07-11 15:41:29 -0700
committerWink Saville <wink@google.com>2012-07-11 15:41:29 -0700
commit0825495a331bb44df395a0cdb79fab85e68db5d5 (patch)
tree1d22c162b785b6e6663419f28d2c4d7afd97086d /tests
parentf4ba68aa88637e9df034fce94971535852cc0a7b (diff)
downloadframeworks_opt_telephony-0825495a331bb44df395a0cdb79fab85e68db5d5.zip
frameworks_opt_telephony-0825495a331bb44df395a0cdb79fab85e68db5d5.tar.gz
frameworks_opt_telephony-0825495a331bb44df395a0cdb79fab85e68db5d5.tar.bz2
Create telephony-common
telephony-common was created by moving some of frameworks/base/telephony to: frameworks/opt/telephony Change-Id: I32cbb5eec1fa239c1587e055c8f7ef4fc48fb62c
Diffstat (limited to 'tests')
-rw-r--r--tests/telephonymockriltests/Android.mk14
-rw-r--r--tests/telephonymockriltests/AndroidManifest.xml40
-rw-r--r--tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java64
-rw-r--r--tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java63
-rw-r--r--tests/telephonytests/Android.mk14
-rw-r--r--tests/telephonytests/AndroidManifest.xml44
-rw-r--r--tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java93
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java113
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java176
-rwxr-xr-xtests/telephonytests/src/com/android/internal/telephony/ApnSettingTest.java109
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java241
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java361
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java538
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java85
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java374
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java75
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java79
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java657
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java292
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java105
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java106
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java60
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java91
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java605
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java219
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java67
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/Wap230WspContentTypeTest.java853
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java746
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java887
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java1933
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java118
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java758
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java624
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java144
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java75
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java304
36 files changed, 11127 insertions, 0 deletions
diff --git a/tests/telephonymockriltests/Android.mk b/tests/telephonymockriltests/Android.mk
new file mode 100644
index 0000000..9731d0d
--- /dev/null
+++ b/tests/telephonymockriltests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_STATIC_JAVA_LIBRARIES := mockrilcontroller
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := TelephonyMockRilTests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/telephonymockriltests/AndroidManifest.xml b/tests/telephonymockriltests/AndroidManifest.xml
new file mode 100644
index 0000000..63f44a2
--- /dev/null
+++ b/tests/telephonymockriltests/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.telephonymockriltests">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:label="TelephonyMockRilTest"
+ android:name="TelephonyMockRilTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name=".TelephonyMockTestRunner"
+ android:targetPackage="com.android.telephonymockriltests"
+ android:label="Test runner for Telephony Tests Using Mock RIL"
+ />
+
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+</manifest>
diff --git a/tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java b/tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java
new file mode 100644
index 0000000..78ee738
--- /dev/null
+++ b/tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.telephonymockriltests;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import com.android.internal.telephony.mockril.MockRilController;
+import android.util.Log;
+
+import com.android.telephonymockriltests.functional.SimpleTestUsingMockRil;
+
+import java.io.IOException;
+import junit.framework.TestSuite;
+import junit.framework.TestCase;
+
+/**
+ * Test runner for telephony tests that using Mock RIL
+ *
+ */
+public class TelephonyMockTestRunner extends InstrumentationTestRunner {
+ private static final String TAG="TelephonyMockTestRunner";
+ public MockRilController mController;
+
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(SimpleTestUsingMockRil.class);
+ return suite;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ try {
+ mController = new MockRilController();
+ } catch (IOException e) {
+ e.printStackTrace();
+ TestCase.assertTrue("Create Mock RIl Controller failed", false);
+ }
+ TestCase.assertNotNull(mController);
+ super.onCreate(icicle);
+ }
+
+ @Override
+ public void finish(int resultCode, Bundle results) {
+ if (mController != null)
+ mController.closeChannel();
+ super.finish(resultCode, results);
+ }
+}
diff --git a/tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java b/tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java
new file mode 100644
index 0000000..3ea1cf2
--- /dev/null
+++ b/tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.telephonymockriltests.functional;
+
+import com.android.internal.telephony.mockril.MockRilController;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import com.android.telephonymockriltests.TelephonyMockTestRunner;
+
+/**
+ * A simple test that using Mock RIL Controller
+ */
+public class SimpleTestUsingMockRil extends InstrumentationTestCase {
+ private static final String TAG = "SimpleTestUsingMockRil";
+ private MockRilController mMockRilCtrl = null;
+ private TelephonyMockTestRunner mRunner;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mRunner = (TelephonyMockTestRunner)getInstrumentation();
+ mMockRilCtrl = mRunner.mController;
+ assertNotNull(mMockRilCtrl);
+ }
+
+ /**
+ * Get the current radio state of RIL
+ */
+ public void testGetRadioState() {
+ int state = mMockRilCtrl.getRadioState();
+ Log.v(TAG, "testGetRadioState: " + state);
+ assertTrue(state >= 0 && state <= 9);
+ }
+
+ /**
+ * Set the current radio state of RIL
+ * and verify the radio state is set correctly
+ */
+ public void testSetRadioState() {
+ for (int state = 0; state <= 9; state++) {
+ Log.v(TAG, "set radio state to be " + state);
+ assertTrue("set radio state: " + state + " failed.",
+ mMockRilCtrl.setRadioState(state));
+ }
+ assertFalse("use an invalid radio state", mMockRilCtrl.setRadioState(-1));
+ assertFalse("the radio state doesn't exist", mMockRilCtrl.setRadioState(10));
+ }
+}
diff --git a/tests/telephonytests/Android.mk b/tests/telephonytests/Android.mk
new file mode 100644
index 0000000..197cedf
--- /dev/null
+++ b/tests/telephonytests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+
+LOCAL_PACKAGE_NAME := FrameworksTelephonyTests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/telephonytests/AndroidManifest.xml b/tests/telephonytests/AndroidManifest.xml
new file mode 100644
index 0000000..ba1d957
--- /dev/null
+++ b/tests/telephonytests/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.telephonytests">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:label="TelephonyTest"
+ android:name="TelephonyTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.telephonytests"
+ android:label="Frameworks Telephony Tests">
+ </instrumentation>
+
+ <instrumentation android:name=".TelephonyMockRilTestRunner"
+ android:targetPackage="com.android.frameworks.telephonytests"
+ android:label="Test Runner for Mock Ril Tests"
+ />
+
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+</manifest>
diff --git a/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java b/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java
new file mode 100644
index 0000000..9192f57
--- /dev/null
+++ b/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworks.telephonytests;
+
+import android.os.Bundle;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import android.util.Log;
+
+import java.io.IOException;
+
+import com.android.internal.telephony.RilChannel;
+import com.android.internal.telephony.mockril.MockRilTest;
+
+import junit.framework.TestSuite;
+
+public class TelephonyMockRilTestRunner extends InstrumentationTestRunner {
+
+ public RilChannel mMockRilChannel;
+
+ @Override
+ public TestSuite getAllTests() {
+ log("getAllTests E");
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(MockRilTest.class);
+ log("getAllTests X");
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ log("getLoader EX");
+ return TelephonyMockRilTestRunner.class.getClassLoader();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ log("onCreate E");
+ try {
+ mMockRilChannel = RilChannel.makeRilChannel();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ log("onCreate X");
+
+ super.onCreate(icicle);
+ }
+
+ @Override
+ public void onDestroy() {
+ // I've not seen this called
+ log("onDestroy EX");
+ super.onDestroy();
+ }
+
+ @Override
+ public void onStart() {
+ // Called when the instrumentation thread is started.
+ // At the moment we don't need the thread so return
+ // which will shut down this unused thread.
+ log("onStart EX");
+ super.onStart();
+ }
+
+ @Override
+ public void finish(int resultCode, Bundle results) {
+ // Called when complete so I ask the mMockRilChannel to quit.
+ log("finish E");
+ mMockRilChannel.close();
+ log("finish X");
+ super.finish(resultCode, results);
+ }
+
+ private void log(String s) {
+ Log.e("TelephonyMockRilTestRunner", s);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java b/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
new file mode 100644
index 0000000..81727e4
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class ATResponseParserTest extends TestCase {
+ @SmallTest
+ public void testBasic() throws Exception {
+ ATResponseParser p = new ATResponseParser("+CREG: 0");
+
+ assertEquals(0, p.nextInt());
+
+ assertFalse(p.hasMore());
+
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0,1");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CREG: 0, 1");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CREG: 0, 1,");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ // this seems odd but is probably OK
+ assertFalse(p.hasMore());
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0, 1 ");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("0, 1 ");
+ // no prefix -> exception
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0, 1, 5");
+ assertFalse(p.nextBoolean());
+ assertTrue(p.nextBoolean());
+ try {
+ // is this over-constraining?
+ p.nextBoolean();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CLCC: 1,0,2,0,0,\"+18005551212\",145");
+
+ assertEquals(1, p.nextInt());
+ assertFalse(p.nextBoolean());
+ assertEquals(2, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals("+18005551212", p.nextString());
+ assertEquals(145, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CLCC: 1,0,2,0,0,\"+18005551212,145");
+
+ assertEquals(1, p.nextInt());
+ assertFalse(p.nextBoolean());
+ assertEquals(2, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals(0, p.nextInt());
+ try {
+ p.nextString();
+ fail("expected ex");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+FOO: \"\"");
+ assertEquals("", p.nextString());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java b/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
new file mode 100644
index 0000000..8a4a285
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * {@hide}
+ */
+public class AdnRecordTest extends TestCase {
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ AdnRecord adn;
+
+ //
+ // Typical record
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("+18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Empty records, empty strings
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ assertEquals("", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertTrue(adn.isEmpty());
+
+ //
+ // Record too short
+ //
+ adn = new AdnRecord(IccUtils.hexStringToBytes( "FF"));
+
+ assertEquals("", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertTrue(adn.isEmpty());
+
+ //
+ // TOA = 0xff ("control string")
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // TOA = 0x81 (unknown)
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is too long
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is zero (invalid)
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is 2, first number byte is FF, TOA is international
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is 2, first number digit is valid, TOA is international
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("+1", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(IccUtils.hexStringToBytes("0206092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678901234567890", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record with an invalid extension
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(IccUtils.hexStringToBytes("0106092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record with an invalid extension
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(IccUtils.hexStringToBytes("020B092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ }
+}
+
+
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ApnSettingTest.java b/tests/telephonytests/src/com/android/internal/telephony/ApnSettingTest.java
new file mode 100755
index 0000000..ac8c4c1
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/ApnSettingTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import junit.framework.TestCase;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class ApnSettingTest extends TestCase {
+
+ public static final String[] TYPES = {"default", "*"};
+
+ public static void assertApnSettingEqual(ApnSetting a1, ApnSetting a2) {
+ assertEquals(a1.carrier, a2.carrier);
+ assertEquals(a1.apn, a2.apn);
+ assertEquals(a1.proxy, a2.proxy);
+ assertEquals(a1.port, a2.port);
+ assertEquals(a1.mmsc, a2.mmsc);
+ assertEquals(a1.mmsProxy, a2.mmsProxy);
+ assertEquals(a1.mmsPort, a2.mmsPort);
+ assertEquals(a1.user, a2.user);
+ assertEquals(a1.password, a2.password);
+ assertEquals(a1.authType, a2.authType);
+ assertEquals(a1.id, a2.id);
+ assertEquals(a1.numeric, a2.numeric);
+ assertEquals(a1.protocol, a2.protocol);
+ assertEquals(a1.roamingProtocol, a2.roamingProtocol);
+ assertEquals(a1.types.length, a2.types.length);
+ int i;
+ for (i = 0; i < a1.types.length; i++) {
+ assertEquals(a1.types[i], a2.types[i]);
+ }
+ assertEquals(a1.carrierEnabled, a2.carrierEnabled);
+ assertEquals(a1.bearer, a2.bearer);
+ }
+
+ @SmallTest
+ public void testFromString() throws Exception {
+ String[] dunTypes = {"DUN"};
+ String[] mmsTypes = {"mms", "*"};
+
+ ApnSetting expected_apn;
+ String testString;
+
+ // A real-world v1 example string.
+ testString = "Vodafone IT,web.omnitel.it,,,,,,,,,222,10,,DUN";
+ expected_apn = new ApnSetting(
+ -1, "22210", "Vodafone IT", "web.omnitel.it", "", "",
+ "", "", "", "", "", 0, dunTypes, "IP", "IP",true,0);
+ assertApnSettingEqual(expected_apn, ApnSetting.fromString(testString));
+
+ // A v2 string.
+ testString = "[ApnSettingV2] Name,apn,,,,,,,,,123,45,,mms|*,IPV6,IP,true,14";
+ expected_apn = new ApnSetting(
+ -1, "12345", "Name", "apn", "", "",
+ "", "", "", "", "", 0, mmsTypes, "IPV6", "IP",true,14);
+ assertApnSettingEqual(expected_apn, ApnSetting.fromString(testString));
+
+ // A v2 string with spaces.
+ testString = "[ApnSettingV2] Name,apn, ,,,,,,,,123,45,,mms|*,IPV4V6, IP,true,14";
+ expected_apn = new ApnSetting(
+ -1, "12345", "Name", "apn", "", "",
+ "", "", "", "", "", 0, mmsTypes, "IPV4V6", "IP",true,14);
+ assertApnSettingEqual(expected_apn, ApnSetting.fromString(testString));
+
+ // Return null if insufficient fields given.
+ testString = "[ApnSettingV2] Name,apn,,,,,,,,,123, 45,,mms|*";
+ assertEquals(null, ApnSetting.fromString(testString));
+
+ testString = "Name,apn,,,,,,,,,123, 45,";
+ assertEquals(null, ApnSetting.fromString(testString));
+
+ // Parse (incorrect) V2 format without the tag as V1.
+ testString = "Name,apn,,,,,,,,,123, 45,,mms|*,IPV6,true,14";
+ String[] incorrectTypes = {"mms|*", "IPV6"};
+ expected_apn = new ApnSetting(
+ -1, "12345", "Name", "apn", "", "",
+ "", "", "", "", "", 0, incorrectTypes, "IP", "IP",true,14);
+ assertApnSettingEqual(expected_apn, ApnSetting.fromString(testString));
+ }
+
+
+ @SmallTest
+ public void testToString() throws Exception {
+ String[] types = {"default", "*"};
+ ApnSetting apn = new ApnSetting(
+ 99, "12345", "Name", "apn", "proxy", "port",
+ "mmsc", "mmsproxy", "mmsport", "user", "password", 0,
+ types, "IPV4V6", "IP", true, 14);
+ String expected = "[ApnSettingV2] Name, 99, 12345, apn, proxy, " +
+ "mmsc, mmsproxy, mmsport, port, 0, default | *, " +
+ "IPV4V6, IP, true, 14";
+ assertEquals(expected, apn.toString());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java
new file mode 100644
index 0000000..1e5dafb
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.CallerInfoAsyncQuery;
+import android.util.Log;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase;
+import android.util.StringBuilderPrinter;
+
+/*
+ * Check the CallerInfo utility class works as expected.
+ *
+ */
+
+public class CallerInfoTest extends AndroidTestCase {
+ private CallerInfo mInfo;
+ private Context mContext;
+
+ private static final String kEmergencyNumber = "Emergency Number";
+ private static final int kToken = 0xdeadbeef;
+ private static final String TAG = "CallerInfoUnitTest";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = new MockContext();
+ mInfo = new CallerInfo();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Checks the caller info instance is flagged as an emergency if
+ * the number is an emergency one. There is no test for the
+ * contact based constructors because emergency number are not in
+ * the contact DB.
+ */
+ @SmallTest
+ public void testEmergencyIsProperlySet() throws Exception {
+ assertFalse(mInfo.isEmergencyNumber());
+
+ mInfo = CallerInfo.getCallerInfo(mContext, "911");
+ assertIsValidEmergencyCallerInfo();
+
+ mInfo = CallerInfo.getCallerInfo(mContext, "tel:911");
+ assertIsValidEmergencyCallerInfo();
+
+
+ // This one hits the content resolver.
+ mInfo = CallerInfo.getCallerInfo(mContext, "18001234567");
+ assertFalse(mInfo.isEmergencyNumber());
+ }
+
+ /**
+ * Same as testEmergencyIsProperlySet but uses the async query api.
+ */
+ @SmallTest
+ public void testEmergencyIsProperlySetUsingAsyncQuery() throws Exception {
+ QueryRunner query;
+
+ query = new QueryRunner("911");
+ query.runAndCheckCompletion();
+ assertIsValidEmergencyCallerInfo();
+
+ query = new QueryRunner("tel:911");
+ query.runAndCheckCompletion();
+ assertIsValidEmergencyCallerInfo();
+
+ query = new QueryRunner("18001234567");
+ query.runAndCheckCompletion();
+ assertFalse(mInfo.isEmergencyNumber());
+ }
+
+ /**
+ * For emergency caller info, phoneNumber should be set to the
+ * string emergency_call_dialog_number_for_display and the
+ * photoResource should be set to the picture_emergency drawable.
+ */
+ @SmallTest
+ public void testEmergencyNumberAndPhotoAreSet() throws Exception {
+ mInfo = CallerInfo.getCallerInfo(mContext, "911");
+
+ assertIsValidEmergencyCallerInfo();
+ }
+
+ // TODO: Add more tests:
+ /**
+ * Check if the voice mail number cannot be retrieved that the
+ * original phone number is preserved.
+ */
+ /**
+ * Check the markAs* methods work.
+ */
+
+
+ //
+ // Helpers
+ //
+
+ // Partial implementation of MockResources.
+ public class MockResources extends android.test.mock.MockResources
+ {
+ @Override
+ public String getString(int resId) throws Resources.NotFoundException {
+ switch (resId) {
+ case com.android.internal.R.string.emergency_call_dialog_number_for_display:
+ return kEmergencyNumber;
+ default:
+ throw new UnsupportedOperationException("Missing handling for resid " + resId);
+ }
+ }
+ }
+
+ // Partial implementation of MockContext.
+ public class MockContext extends android.test.mock.MockContext {
+ private ContentResolver mResolver;
+ private Resources mResources;
+
+ public MockContext() {
+ mResolver = new android.test.mock.MockContentResolver();
+ mResources = new MockResources();
+ }
+
+ @Override
+ public ContentResolver getContentResolver() {
+ return mResolver;
+ }
+
+ @Override
+ public Resources getResources() {
+ return mResources;
+ }
+ }
+
+ /**
+ * Class to run a CallerInfoAsyncQuery in a separate thread, with
+ * its own Looper. We cannot use the main Looper because on the
+ * 1st quit the thread is maked dead, ie no further test can use
+ * it. Also there is not way to inject a Looper instance in the
+ * query, so we have to use a thread with its own looper.
+ */
+ private class QueryRunner extends Thread
+ implements CallerInfoAsyncQuery.OnQueryCompleteListener {
+ private Looper mLooper;
+ private String mNumber;
+ private boolean mAsyncCompleted;
+
+ public QueryRunner(String number) {
+ super();
+ mNumber = number;
+ }
+
+ // Run the query in the thread, wait for completion.
+ public void runAndCheckCompletion() throws InterruptedException {
+ start();
+ join();
+ assertTrue(mAsyncCompleted);
+ }
+
+ @Override
+ public void run() {
+ Looper.prepare();
+ mLooper = Looper.myLooper();
+ mAsyncCompleted = false;
+ // The query will pick the thread local looper we've just prepared.
+ CallerInfoAsyncQuery.startQuery(kToken, mContext, mNumber, this, null);
+ mLooper.loop();
+ }
+
+ // Quit the Looper on the 1st callback
+ // (EVENT_EMERGENCY_NUMBER). There is another message
+ // (EVENT_END_OF_QUEUE) that will never be delivered because
+ // the test has exited. The corresponding stack trace
+ // "Handler{xxxxx} sending message to a Handler on a dead
+ // thread" can be ignored.
+ public void onQueryComplete(int token, Object cookie, CallerInfo info) {
+ mAsyncCompleted = true;
+ mInfo = info;
+ mLooper.quit();
+ }
+ }
+
+ /**
+ * Fail if mInfo does not contain a valid emergency CallerInfo instance.
+ */
+ private void assertIsValidEmergencyCallerInfo() throws Exception {
+ assertTrue(mInfo.isEmergencyNumber());
+
+ // For emergency caller info, phoneNumber should be set to the
+ // string emergency_call_dialog_number_for_display and the
+ // photoResource should be set to the picture_emergency drawable.
+ assertEquals(kEmergencyNumber, mInfo.phoneNumber);
+ assertEquals(com.android.internal.R.drawable.picture_emergency, mInfo.photoResource);
+
+ // The name should be null
+ assertNull(mInfo.name);
+ assertEquals(0, mInfo.namePresentation);
+ assertNull(mInfo.cnapName);
+ assertEquals(0, mInfo.numberPresentation);
+
+ assertFalse(mInfo.contactExists);
+ assertEquals(0, mInfo.person_id);
+ assertFalse(mInfo.needUpdate);
+ assertNull(mInfo.contactRefUri);
+
+ assertNull(mInfo.phoneLabel);
+ assertEquals(0, mInfo.numberType);
+ assertNull(mInfo.numberLabel);
+
+ assertNull(mInfo.contactRingtoneUri);
+ assertFalse(mInfo.shouldSendToVoicemail);
+
+ assertNull(mInfo.cachedPhoto);
+ assertFalse(mInfo.isCachedPhotoCurrent);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
new file mode 100644
index 0000000..f9dc3a9
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.GsmAlphabet;
+
+import junit.framework.TestCase;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class GsmAlphabetTest extends TestCase {
+
+ private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac";
+
+ @SmallTest
+ public void test7bitWithHeader() throws Exception {
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 1;
+ concatRef.seqNumber = 2;
+ concatRef.msgCount = 2;
+ concatRef.isEightBits = true;
+ SmsHeader header = new SmsHeader();
+ header.concatRef = concatRef;
+
+ String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
+ byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message,
+ SmsHeader.toByteArray(header), 0, 0);
+ int septetCount = GsmAlphabet.countGsmSeptetsUsingTables(message, true, 0, 0);
+ String parsedMessage = GsmAlphabet.gsm7BitPackedToString(
+ userData, SmsHeader.toByteArray(header).length+2, septetCount, 1, 0, 0);
+ assertEquals(message, parsedMessage);
+ }
+
+ // TODO: This method should *really* be a series of individual test methods.
+ // However, it's a SmallTest because it executes quickly.
+ @SmallTest
+ public void testBasic() throws Exception {
+ // '@' maps to char 0
+ assertEquals(0, GsmAlphabet.charToGsm('@'));
+
+ // `a (a with grave accent) maps to last GSM character
+ assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0'));
+
+ //
+ // These are the extended chars
+ // They should all return GsmAlphabet.GSM_EXTENDED_ESCAPE
+ //
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
+ GsmAlphabet.charToGsm(sGsmExtendedChars.charAt(i)));
+
+ }
+
+ // euro symbol
+ assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
+ GsmAlphabet.charToGsm('\u20ac'));
+
+ // An unmappable char (the 'cent' char) maps to a space
+ assertEquals(GsmAlphabet.charToGsm(' '),
+ GsmAlphabet.charToGsm('\u00a2'));
+
+ // unmappable = space = 1 septet
+ assertEquals(1, GsmAlphabet.countGsmSeptets('\u00a2'));
+
+ //
+ // Test extended table
+ //
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ assertEquals(sGsmExtendedChars.charAt(i),
+ GsmAlphabet.gsmExtendedToChar(
+ GsmAlphabet.charToGsmExtended(sGsmExtendedChars.charAt(i))));
+
+ }
+
+ // Unmappable extended char
+ assertEquals(GsmAlphabet.charToGsm(' '),
+ GsmAlphabet.charToGsmExtended('@'));
+
+ //
+ // gsmToChar()
+ //
+
+ assertEquals('@', GsmAlphabet.gsmToChar(0));
+
+ // `a (a with grave accent) maps to last GSM character
+ assertEquals('\u00e0', GsmAlphabet.gsmToChar(0x7f));
+
+ assertEquals('\uffff',
+ GsmAlphabet.gsmToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Out-of-range/unmappable value
+ assertEquals(' ', GsmAlphabet.gsmToChar(0x80));
+
+ //
+ // gsmExtendedToChar()
+ //
+
+ assertEquals('{', GsmAlphabet.gsmExtendedToChar(0x28));
+
+ // No double-escapes
+ assertEquals(' ', GsmAlphabet.gsmExtendedToChar(
+ GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Reserved for extension to extension table (mapped to space)
+ assertEquals(' ', GsmAlphabet.gsmExtendedToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Unmappable (mapped to character in default or national locking shift table)
+ assertEquals('@', GsmAlphabet.gsmExtendedToChar(0));
+ assertEquals('\u00e0', GsmAlphabet.gsmExtendedToChar(0x7f));
+
+ //
+ // stringTo7BitPacked, gsm7BitPackedToString
+ //
+
+ byte[] packed;
+ StringBuilder testString = new StringBuilder(300);
+
+ // Check all alignment cases
+ for (int i = 0; i < 9; i++, testString.append('@')) {
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+ }
+
+ // Check full non-extended alphabet
+ for (int i = 0; i < 0x80; i++) {
+ char c;
+
+ if (i == GsmAlphabet.GSM_EXTENDED_ESCAPE) {
+ continue;
+ }
+
+ c = GsmAlphabet.gsmToChar(i);
+ testString.append(c);
+
+ // These are all non-extended chars, so it should be
+ // one septet per char
+ assertEquals(1, GsmAlphabet.countGsmSeptets(c));
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // Test extended chars too
+
+ testString.append(sGsmExtendedChars);
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ // These are all extended chars, so it should be
+ // two septets per char
+ assertEquals(2, GsmAlphabet.countGsmSeptets(sGsmExtendedChars.charAt(i)));
+
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // stringTo7BitPacked handles up to 255 septets
+
+ testString.setLength(0);
+ for (int i = 0; i < 255; i++) {
+ testString.append('@');
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // > 255 septets throws runtime exception
+ testString.append('@');
+
+ try {
+ GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ fail("expected exception");
+ } catch (EncodeException ex) {
+ // exception expected
+ }
+
+ // Try 254 septets with 127 extended chars
+
+ testString.setLength(0);
+ for (int i = 0; i < (255 / 2); i++) {
+ testString.append('{');
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // > 255 septets throws runtime exception
+ testString.append('{');
+
+ try {
+ GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
+ fail("expected exception");
+ } catch (EncodeException ex) {
+ // exception expected
+ }
+
+ // Reserved for extension to extension table (mapped to space)
+ packed = new byte[]{(byte)(0x1b | 0x80), 0x1b >> 1};
+ assertEquals(" ", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
+
+ // Unmappable (mapped to character in default alphabet table)
+ packed[0] = 0x1b;
+ packed[1] = 0x00;
+ assertEquals("@", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
+ packed[0] = (byte)(0x1b | 0x80);
+ packed[1] = (byte)(0x7f >> 1);
+ assertEquals("\u00e0", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
+
+ //
+ // 8 bit unpacked format
+ //
+ // Note: we compare hex strings here
+ // because Assert doesn't have array comparisons
+
+ byte unpacked[];
+
+ unpacked = IccUtils.hexStringToBytes("566F696365204D61696C");
+ assertEquals("Voice Mail",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ assertEquals(IccUtils.bytesToHexString(unpacked),
+ IccUtils.bytesToHexString(
+ GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
+
+ unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
+ // two bytes for every extended char
+ assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
+ assertEquals(sGsmExtendedChars,
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // should be two bytes per extended char
+ assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
+
+ // Test truncation of unaligned extended chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField(sGsmExtendedChars, unpacked,
+ 0, unpacked.length);
+
+ // Should be one extended char and an 0xff at the end
+
+ assertEquals(0xff, 0xff & unpacked[2]);
+ assertEquals(sGsmExtendedChars.substring(0, 1),
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test truncation of normal chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("abc",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test truncation of mixed normal and extended chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("a{cd", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("a{",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test padding after normal char
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("a", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("a",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ assertEquals(0xff, 0xff & unpacked[1]);
+ assertEquals(0xff, 0xff & unpacked[2]);
+
+ // Test malformed input -- escape char followed by end of field
+ unpacked[0] = 0;
+ unpacked[1] = 0;
+ unpacked[2] = GsmAlphabet.GSM_EXTENDED_ESCAPE;
+
+ assertEquals("@@",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // non-zero offset
+ assertEquals("@",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // test non-zero offset
+ unpacked[0] = 0;
+ GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
+ 1, unpacked.length - 1);
+
+
+ assertEquals(0, unpacked[0]);
+
+ assertEquals("ab",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // test non-zero offset with truncated extended char
+ unpacked[0] = 0;
+
+ GsmAlphabet.stringToGsm8BitUnpackedField("a{", unpacked,
+ 1, unpacked.length - 1);
+
+ assertEquals(0, unpacked[0]);
+
+ assertEquals("a",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // Reserved for extension to extension table (mapped to space)
+ unpacked[0] = 0x1b;
+ unpacked[1] = 0x1b;
+ assertEquals(" ", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
+
+ // Unmappable (mapped to character in default or national locking shift table)
+ unpacked[1] = 0x00;
+ assertEquals("@", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
+ unpacked[1] = 0x7f;
+ assertEquals("\u00e0", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
+ }
+
+ @SmallTest
+ public void testGsm8BitUpackedWithEuckr() throws Exception {
+ // Some feature phones in Korea store contacts as euc-kr.
+ // Test this situations.
+ byte unpacked[];
+
+ // Test general alphabet strings.
+ unpacked = IccUtils.hexStringToBytes("61626320646566FF");
+ assertEquals("abc def",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
+
+ // Test korean strings.
+ unpacked = IccUtils.hexStringToBytes("C5D7BDBAC6AEFF");
+ assertEquals("\uD14C\uC2A4\uD2B8",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
+
+ // Test gsm Extented Characters.
+ unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
+ assertEquals(sGsmExtendedChars,
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
new file mode 100644
index 0000000..f2e5da1
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.util.HexDump;
+
+import java.util.ArrayList;
+
+public class GsmSmsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testAddressing() throws Exception {
+ String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertEquals("+16505551111", sms.getOriginatingAddress());
+ assertEquals("Test", sms.getMessageBody());
+
+ pdu = "07914151551512f2040B916105551511f100036060924180008A0DA"
+ + "8695DAC2E8FE9296A794E07";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertEquals("+16505551111", sms.getOriginatingAddress());
+ assertEquals("(Subject)Test", sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testUdh() throws Exception {
+ String pdu = "07914140279510F6440A8111110301003BF56080207130138A8C0B05040B8423F"
+ + "000032A02010106276170706C69636174696F6E2F766E642E7761702E6D6D732D"
+ + "6D65737361676500AF848D0185B4848C8298524E453955304A6D7135514141426"
+ + "66C414141414D7741414236514141414141008D908918802B3135313232393737"
+ + "3638332F545950453D504C4D4E008A808E022B918805810306977F83687474703"
+ + "A2F2F36";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ SmsHeader header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 42);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 1);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+
+ pdu = "07914140279510F6440A8111110301003BF56080207130238A3B0B05040B8423F"
+ + "000032A0202362E3130322E3137312E3135302F524E453955304A6D7135514141"
+ + "42666C414141414D774141423651414141414100";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 42);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 2);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+ }
+
+ @SmallTest
+ public void testUcs2() throws Exception {
+ String pdu = "07912160130300F4040B914151245584F600087010807121352B1021220"
+ + "0A900AE00680065006C006C006F";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("\u2122\u00a9\u00aehello", sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testMultipart() throws Exception {
+ /*
+ * Multi-part text SMS with septet data.
+ */
+ String pdu = "07916163838408F6440B816105224431F700007060217175830AA0050003"
+ + "00020162B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals(sms.getMessageBody(),
+ "1111111111111111111111111111111111111111"
+ + "1111111111111111111111111111111111111111"
+ + "1111111111111111111111111111111111111111"
+ + "111111111111111111111111111111111");
+
+ pdu = "07916163838408F6440B816105224431F700007060217185000A23050003"
+ + "00020262B1582C168BC96432994C2693C96432994C2693C96432990C";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("1111111222222222222222222222", sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testCPHSVoiceMail() throws Exception {
+ // "set MWI flag"
+
+ String pdu = "07912160130310F20404D0110041006060627171118A0120";
+
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isReplace());
+ assertEquals("_@", sms.getOriginatingAddress());
+ assertEquals(" ", sms.getMessageBody());
+ assertTrue(sms.isMWISetMessage());
+
+ // "clear mwi flag"
+
+ pdu = "07912160130310F20404D0100041006021924193352B0120";
+
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isMWIClearMessage());
+
+ // "clear MWI flag"
+
+ pdu = "07912160130310F20404D0100041006060627161058A0120";
+
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isReplace());
+ assertEquals("\u0394@", sms.getOriginatingAddress());
+ assertEquals(" ", sms.getMessageBody());
+ assertTrue(sms.isMWIClearMessage());
+ }
+
+ @SmallTest
+ public void testCingularVoiceMail() throws Exception {
+ // "set MWI flag"
+
+ String pdu = "07912180958750F84401800500C87020026195702B06040102000200";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isMWISetMessage());
+ assertTrue(sms.isMwiDontStore());
+
+ // "clear mwi flag"
+
+ pdu = "07912180958750F84401800500C07020027160112B06040102000000";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isMWIClearMessage());
+ assertTrue(sms.isMwiDontStore());
+ }
+
+ @SmallTest
+ public void testEmailGateway() throws Exception {
+ String pdu = "07914151551512f204038105f300007011103164638a28e6f71b50c687db" +
+ "7076d9357eb7412f7a794e07cdeb6275794c07bde8e5391d247e93f3";
+
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertTrue(sms.isEmail());
+ assertEquals("foo@example.com", sms.getEmailFrom());
+ assertEquals("foo@example.com", sms.getDisplayOriginatingAddress());
+ // As of https://android-git.corp.google.com/g/#change,9324
+ // getPseudoSubject will always be empty, and any subject is not extracted.
+ assertEquals("", sms.getPseudoSubject());
+ assertEquals("test subject /test body", sms.getDisplayMessageBody());
+ assertEquals("test subject /test body", sms.getEmailBody());
+
+ // email gateway sms test, including gsm extended character set.
+ pdu = "07914151551512f204038105f400007011103105458a29e6f71b50c687db" +
+ "7076d9357eb741af0d0a442fcfe9c23739bfe16d289bdee6b5f1813629";
+
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertTrue(sms.isEmail());
+ assertEquals("foo@example.com", sms.getDisplayOriginatingAddress());
+ assertEquals("foo@example.com", sms.getEmailFrom());
+ assertEquals("{ testBody[^~\\] }", sms.getDisplayMessageBody());
+ assertEquals("{ testBody[^~\\] }", sms.getEmailBody());
+ }
+
+ @SmallTest
+ public void testExtendedCharacterTable() throws Exception {
+ String pdu = "07914151551512f2040B916105551511f100006080615131728A44D4F29C0E2" +
+ "AE3E96537B94C068DD16179784C2FCB41F4B0985D06B958ADD00FB0E94536AF9749" +
+ "74DA6D281BA00E95E26D509B946FC3DBF87A25D56A04";
+
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertEquals("+16505551111", sms.getOriginatingAddress());
+ assertEquals("Test extended character table .,-!?@~_\\/&\"';^|:()<{}>[]=%*+#",
+ sms.getMessageBody());
+ }
+
+ // GSM 7 bit tables in String form, Escape (0x1B) replaced with '@'
+ private static final String[] sBasicTables = {
+ // GSM 7 bit default alphabet
+ "@\u00a3$\u00a5\u00e8\u00e9\u00f9\u00ec\u00f2\u00c7\n\u00d8\u00f8\r\u00c5\u00e5\u0394_"
+ + "\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e@\u00c6\u00e6\u00df\u00c9"
+ + " !\"#\u00a4%&'()*+,-./0123456789:;<=>?\u00a1ABCDEFGHIJKLMNOPQRSTUVWXYZ\u00c4\u00d6"
+ + "\u00d1\u00dc\u00a7\u00bfabcdefghijklmnopqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0",
+
+ // Turkish locking shift table
+ "@\u00a3$\u00a5\u20ac\u00e9\u00f9\u0131\u00f2\u00c7\n\u011e\u011f\r\u00c5\u00e5\u0394_"
+ + "\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e@\u015e\u015f\u00df\u00c9"
+ + " !\"#\u00a4%&'()*+,-./0123456789:;<=>?\u0130ABCDEFGHIJKLMNOPQRSTUVWXYZ\u00c4\u00d6"
+ + "\u00d1\u00dc\u00a7\u00e7abcdefghijklmnopqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0",
+
+ // no locking shift table defined for Spanish
+ "",
+
+ // Portuguese locking shift table
+ "@\u00a3$\u00a5\u00ea\u00e9\u00fa\u00ed\u00f3\u00e7\n\u00d4\u00f4\r\u00c1\u00e1\u0394_"
+ + "\u00aa\u00c7\u00c0\u221e^\\\u20ac\u00d3|@\u00c2\u00e2\u00ca\u00c9 !\"#\u00ba%&'()"
+ + "*+,-./0123456789:;<=>?\u00cdABCDEFGHIJKLMNOPQRSTUVWXYZ\u00c3\u00d5\u00da\u00dc"
+ + "\u00a7~abcdefghijklmnopqrstuvwxyz\u00e3\u00f5`\u00fc\u00e0"
+ };
+
+ @SmallTest
+ public void testFragmentText() throws Exception {
+ boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() ==
+ TelephonyManager.PHONE_TYPE_GSM);
+
+ // Valid 160 character 7-bit text.
+ String text = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890";
+ GsmAlphabet.TextEncodingDetails ted = SmsMessage.calculateLength(text, false);
+ assertEquals(1, ted.msgCount);
+ assertEquals(160, ted.codeUnitCount);
+ assertEquals(1, ted.codeUnitSize);
+ assertEquals(0, ted.languageTable);
+ assertEquals(0, ted.languageShiftTable);
+ if (isGsmPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+ assertEquals(1, fragments.size());
+ }
+
+ // Valid 161 character 7-bit text.
+ text = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901";
+ ted = SmsMessage.calculateLength(text, false);
+ assertEquals(2, ted.msgCount);
+ assertEquals(161, ted.codeUnitCount);
+ assertEquals(1, ted.codeUnitSize);
+ assertEquals(0, ted.languageTable);
+ assertEquals(0, ted.languageShiftTable);
+ if (isGsmPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+ assertEquals(2, fragments.size());
+ assertEquals(text, fragments.get(0) + fragments.get(1));
+ assertEquals(153, fragments.get(0).length());
+ assertEquals(8, fragments.get(1).length());
+ }
+ }
+
+ @SmallTest
+ public void testFragmentTurkishText() throws Exception {
+ boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() ==
+ TelephonyManager.PHONE_TYPE_GSM);
+
+ int[] oldTables = GsmAlphabet.getEnabledSingleShiftTables();
+ int[] turkishTable = { 1 };
+ GsmAlphabet.setEnabledSingleShiftTables(turkishTable);
+
+ // Valid 77 character text with Turkish characters.
+ String text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" +
+ "ĞŞİğşıĞŞİğşıĞŞİğş";
+ GsmAlphabet.TextEncodingDetails ted = SmsMessage.calculateLength(text, false);
+ assertEquals(1, ted.msgCount);
+ assertEquals(154, ted.codeUnitCount);
+ assertEquals(1, ted.codeUnitSize);
+ assertEquals(0, ted.languageTable);
+ assertEquals(1, ted.languageShiftTable);
+ if (isGsmPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+ assertEquals(1, fragments.size());
+ assertEquals(text, fragments.get(0));
+ assertEquals(77, fragments.get(0).length());
+ }
+
+ // Valid 78 character text with Turkish characters.
+ text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" +
+ "ĞŞİğşıĞŞİğşıĞŞİğşı";
+ ted = SmsMessage.calculateLength(text, false);
+ assertEquals(2, ted.msgCount);
+ assertEquals(156, ted.codeUnitCount);
+ assertEquals(1, ted.codeUnitSize);
+ assertEquals(0, ted.languageTable);
+ assertEquals(1, ted.languageShiftTable);
+ if (isGsmPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+ assertEquals(2, fragments.size());
+ assertEquals(text, fragments.get(0) + fragments.get(1));
+ assertEquals(74, fragments.get(0).length());
+ assertEquals(4, fragments.get(1).length());
+ }
+
+ // Valid 160 character text with Turkish characters.
+ text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" +
+ "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğ" +
+ "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı";
+ ted = SmsMessage.calculateLength(text, false);
+ assertEquals(3, ted.msgCount);
+ assertEquals(320, ted.codeUnitCount);
+ assertEquals(1, ted.codeUnitSize);
+ assertEquals(0, ted.languageTable);
+ assertEquals(1, ted.languageShiftTable);
+ if (isGsmPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+ assertEquals(3, fragments.size());
+ assertEquals(text, fragments.get(0) + fragments.get(1) + fragments.get(2));
+ assertEquals(74, fragments.get(0).length());
+ assertEquals(74, fragments.get(1).length());
+ assertEquals(12, fragments.get(2).length());
+ }
+
+ GsmAlphabet.setEnabledSingleShiftTables(oldTables);
+ }
+
+
+ @SmallTest
+ public void testDecode() throws Exception {
+ decodeSingle(0); // default table
+ decodeSingle(1); // Turkish locking shift table
+ decodeSingle(3); // Portuguese locking shift table
+ }
+
+ private void decodeSingle(int language) throws Exception {
+ byte[] septets = new byte[(7 * 128 + 7) / 8];
+
+ int bitOffset = 0;
+
+ for (int i = 0; i < 128; i++) {
+ int v;
+ if (i == 0x1b) {
+ // extended escape char
+ v = 0;
+ } else {
+ v = i;
+ }
+
+ int byteOffset = bitOffset / 8;
+ int shift = bitOffset % 8;
+
+ septets[byteOffset] |= v << shift;
+
+ if (shift > 1) {
+ septets[byteOffset + 1] = (byte) (v >> (8 - shift));
+ }
+
+ bitOffset += 7;
+ }
+
+ String decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, 128, 0, language, 0);
+ byte[] reEncoded = GsmAlphabet.stringToGsm7BitPacked(decoded, language, 0);
+
+ assertEquals(sBasicTables[language], decoded);
+
+ // reEncoded has the count septets byte at the front
+ assertEquals(septets.length + 1, reEncoded.length);
+
+ for (int i = 0; i < septets.length; i++) {
+ assertEquals(septets[i], reEncoded[i + 1]);
+ }
+ }
+
+ private static final int GSM_ESCAPE_CHARACTER = 0x1b;
+
+ private static final String[] sExtendedTables = {
+ // GSM 7 bit default alphabet extension table
+ "\f^{}\\[~]|\u20ac",
+
+ // Turkish single shift extension table
+ "\f^{}\\[~]|\u011e\u0130\u015e\u00e7\u20ac\u011f\u0131\u015f",
+
+ // Spanish single shift extension table
+ "\u00e7\f^{}\\[~]|\u00c1\u00cd\u00d3\u00da\u00e1\u20ac\u00ed\u00f3\u00fa",
+
+ // Portuguese single shift extension table
+ "\u00ea\u00e7\f\u00d4\u00f4\u00c1\u00e1\u03a6\u0393^\u03a9\u03a0\u03a8\u03a3\u0398\u00ca"
+ + "{}\\[~]|\u00c0\u00cd\u00d3\u00da\u00c3\u00d5\u00c2\u20ac\u00ed\u00f3\u00fa\u00e3"
+ + "\u00f5\u00e2"
+ };
+
+ private static final int[][] sExtendedTableIndexes = {
+ {0x0a, 0x14, 0x28, 0x29, 0x2f, 0x3c, 0x3d, 0x3e, 0x40, 0x65},
+ {0x0a, 0x14, 0x28, 0x29, 0x2f, 0x3c, 0x3d, 0x3e, 0x40, 0x47, 0x49, 0x53, 0x63,
+ 0x65, 0x67, 0x69, 0x73},
+ {0x09, 0x0a, 0x14, 0x28, 0x29, 0x2f, 0x3c, 0x3d, 0x3e, 0x40, 0x41, 0x49, 0x4f,
+ 0x55, 0x61, 0x65, 0x69, 0x6f, 0x75},
+ {0x05, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1f, 0x28, 0x29, 0x2f, 0x3c, 0x3d, 0x3e, 0x40, 0x41, 0x49,
+ 0x4f, 0x55, 0x5b, 0x5c, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x7b, 0x7c, 0x7f}
+ };
+
+ @SmallTest
+ public void testDecodeExtended() throws Exception {
+ for (int language = 0; language < 3; language++) {
+ int[] tableIndex = sExtendedTableIndexes[language];
+ int numSeptets = tableIndex.length * 2; // two septets per extended char
+ byte[] septets = new byte[(7 * numSeptets + 7) / 8];
+
+ int bitOffset = 0;
+
+ for (int v : tableIndex) {
+ // escape character
+ int byteOffset = bitOffset / 8;
+ int shift = bitOffset % 8;
+
+ septets[byteOffset] |= GSM_ESCAPE_CHARACTER << shift;
+
+ if (shift > 1) {
+ septets[byteOffset + 1] = (byte) (GSM_ESCAPE_CHARACTER >> (8 - shift));
+ }
+
+ bitOffset += 7;
+
+ // extended table index
+ byteOffset = bitOffset / 8;
+ shift = bitOffset % 8;
+
+ septets[byteOffset] |= v << shift;
+
+ if (shift > 1) {
+ septets[byteOffset + 1] = (byte) (v >> (8 - shift));
+ }
+
+ bitOffset += 7;
+ }
+
+ String decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, numSeptets, 0,
+ 0, language);
+ byte[] reEncoded = GsmAlphabet.stringToGsm7BitPacked(decoded, 0, language);
+
+ assertEquals(sExtendedTables[language], decoded);
+
+ // reEncoded has the count septets byte at the front
+ assertEquals(septets.length + 1, reEncoded.length);
+
+ for (int i = 0; i < septets.length; i++) {
+ assertEquals(septets[i], reEncoded[i + 1]);
+ }
+ }
+ }
+
+ @SmallTest
+ public void testDecodeExtendedFallback() throws Exception {
+ // verify that unmapped characters in extension table fall back to locking shift table
+ for (int language = 0; language < 3; language++) {
+ int[] tableIndex = sExtendedTableIndexes[language];
+ int numChars = 128 - tableIndex.length;
+ int numSeptets = numChars * 2; // two septets per extended char
+ byte[] septets = new byte[(7 * numSeptets + 7) / 8];
+
+ int tableOffset = 0;
+ int bitOffset = 0;
+
+ StringBuilder defaultTable = new StringBuilder(128);
+ StringBuilder turkishTable = new StringBuilder(128);
+ StringBuilder portugueseTable = new StringBuilder(128);
+
+ for (char c = 0; c < 128; c++) {
+ // skip characters that are present in the current extension table
+ if (tableOffset < tableIndex.length && tableIndex[tableOffset] == c) {
+ tableOffset++;
+ continue;
+ }
+
+ // escape character
+ int byteOffset = bitOffset / 8;
+ int shift = bitOffset % 8;
+
+ septets[byteOffset] |= GSM_ESCAPE_CHARACTER << shift;
+
+ if (shift > 1) {
+ septets[byteOffset + 1] = (byte) (GSM_ESCAPE_CHARACTER >> (8 - shift));
+ }
+
+ bitOffset += 7;
+
+ // extended table index
+ byteOffset = bitOffset / 8;
+ shift = bitOffset % 8;
+
+ septets[byteOffset] |= c << shift;
+
+ if (shift > 1) {
+ septets[byteOffset + 1] = (byte) (c >> (8 - shift));
+ }
+
+ bitOffset += 7;
+
+ if (c == GsmAlphabet.GSM_EXTENDED_ESCAPE) {
+ // double Escape maps to space character
+ defaultTable.append(' ');
+ turkishTable.append(' ');
+ portugueseTable.append(' ');
+ } else {
+ // other unmapped chars map to the default or locking shift table
+ defaultTable.append(sBasicTables[0].charAt(c));
+ turkishTable.append(sBasicTables[1].charAt(c));
+ portugueseTable.append(sBasicTables[3].charAt(c));
+ }
+ }
+
+ String decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, numSeptets, 0,
+ 0, language);
+
+ assertEquals(defaultTable.toString(), decoded);
+
+ decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, numSeptets, 0, 1, language);
+ assertEquals(turkishTable.toString(), decoded);
+
+ decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, numSeptets, 0, 3, language);
+ assertEquals(portugueseTable.toString(), decoded);
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java
new file mode 100644
index 0000000..c89f33a
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test IccServiceTable class.
+ */
+public class IccServiceTableTest extends AndroidTestCase {
+
+ static class TestIccServiceTable extends IccServiceTable {
+ public enum TestIccService {
+ SERVICE1,
+ SERVICE2,
+ SERVICE3,
+ SERVICE4
+ }
+
+ public TestIccServiceTable(byte[] table) {
+ super(table);
+ }
+
+ public boolean isAvailable(TestIccService service) {
+ return super.isAvailable(service.ordinal());
+ }
+
+ @Override
+ protected String getTag() {
+ return "TestIccServiceTable";
+ }
+
+ @Override
+ protected Object[] getValues() {
+ return TestIccService.values();
+ }
+ }
+
+ @SmallTest
+ public void testIccServiceTable() {
+ byte[] noServices = {0x00};
+ byte[] service1 = {0x01};
+ byte[] service4 = {0x08};
+ byte[] allServices = {0x0f};
+
+ TestIccServiceTable testTable1 = new TestIccServiceTable(noServices);
+ assertFalse(testTable1.isAvailable(TestIccServiceTable.TestIccService.SERVICE1));
+ assertFalse(testTable1.isAvailable(TestIccServiceTable.TestIccService.SERVICE2));
+ assertFalse(testTable1.isAvailable(TestIccServiceTable.TestIccService.SERVICE3));
+ assertFalse(testTable1.isAvailable(TestIccServiceTable.TestIccService.SERVICE4));
+
+ TestIccServiceTable testTable2 = new TestIccServiceTable(service1);
+ assertTrue(testTable2.isAvailable(TestIccServiceTable.TestIccService.SERVICE1));
+ assertFalse(testTable2.isAvailable(TestIccServiceTable.TestIccService.SERVICE2));
+ assertFalse(testTable2.isAvailable(TestIccServiceTable.TestIccService.SERVICE3));
+ assertFalse(testTable2.isAvailable(TestIccServiceTable.TestIccService.SERVICE4));
+
+ TestIccServiceTable testTable3 = new TestIccServiceTable(service4);
+ assertFalse(testTable3.isAvailable(TestIccServiceTable.TestIccService.SERVICE1));
+ assertFalse(testTable3.isAvailable(TestIccServiceTable.TestIccService.SERVICE2));
+ assertFalse(testTable3.isAvailable(TestIccServiceTable.TestIccService.SERVICE3));
+ assertTrue(testTable3.isAvailable(TestIccServiceTable.TestIccService.SERVICE4));
+
+ TestIccServiceTable testTable4 = new TestIccServiceTable(allServices);
+ assertTrue(testTable4.isAvailable(TestIccServiceTable.TestIccService.SERVICE1));
+ assertTrue(testTable4.isAvailable(TestIccServiceTable.TestIccService.SERVICE2));
+ assertTrue(testTable4.isAvailable(TestIccServiceTable.TestIccService.SERVICE3));
+ assertTrue(testTable4.isAvailable(TestIccServiceTable.TestIccService.SERVICE4));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
new file mode 100644
index 0000000..79dca39
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.test.AndroidTestCase;
+
+import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
+
+import java.util.ArrayList;
+
+/**
+ * Test cases for the IntRangeManager class.
+ */
+public class IntRangeManagerTest extends AndroidTestCase {
+
+ private static final int SMS_CB_CODE_SCHEME_MIN = 0;
+ private static final int SMS_CB_CODE_SCHEME_MAX = 255;
+
+ private static final int FLAG_START_UPDATE_CALLED = 0x01;
+ private static final int FLAG_ADD_RANGE_CALLED = 0x02;
+ private static final int FLAG_FINISH_UPDATE_CALLED = 0x04;
+
+ private static final int ALL_FLAGS_SET = FLAG_START_UPDATE_CALLED | FLAG_ADD_RANGE_CALLED |
+ FLAG_FINISH_UPDATE_CALLED;
+
+ /** Dummy IntRangeManager for testing. */
+ class TestIntRangeManager extends IntRangeManager {
+ ArrayList<SmsBroadcastConfigInfo> mConfigList =
+ new ArrayList<SmsBroadcastConfigInfo>();
+
+ int flags;
+ boolean finishUpdateReturnValue = true;
+
+ /**
+ * Called when the list of enabled ranges has changed. This will be
+ * followed by zero or more calls to {@link #addRange} followed by
+ * a call to {@link #finishUpdate}.
+ */
+ protected void startUpdate() {
+ mConfigList.clear();
+ flags |= FLAG_START_UPDATE_CALLED;
+ }
+
+ /**
+ * Called after {@link #startUpdate} to indicate a range of enabled
+ * values.
+ * @param startId the first id included in the range
+ * @param endId the last id included in the range
+ */
+ protected void addRange(int startId, int endId, boolean selected) {
+ mConfigList.add(new SmsBroadcastConfigInfo(startId, endId,
+ SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected));
+ flags |= FLAG_ADD_RANGE_CALLED;
+ }
+
+ /**
+ * Called to indicate the end of a range update started by the
+ * previous call to {@link #startUpdate}.
+ */
+ protected boolean finishUpdate() {
+ flags |= FLAG_FINISH_UPDATE_CALLED;
+ return finishUpdateReturnValue;
+ }
+
+ /** Reset the object for the next test case. */
+ void reset() {
+ flags = 0;
+ mConfigList.clear();
+ }
+ }
+
+ public void testEmptyRangeManager() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertEquals("expecting empty configlist", 0, testManager.mConfigList.size());
+ }
+
+ private void checkConfigInfo(SmsBroadcastConfigInfo info, int fromServiceId,
+ int toServiceId, int fromCodeScheme, int toCodeScheme, boolean selected) {
+ assertEquals("fromServiceId", fromServiceId, info.getFromServiceId());
+ assertEquals("toServiceId", toServiceId, info.getToServiceId());
+ assertEquals("fromCodeScheme", fromCodeScheme, info.getFromCodeScheme());
+ assertEquals("toCodeScheme", toCodeScheme, info.getToCodeScheme());
+ assertEquals("selected", selected, info.isSelected());
+ }
+
+ public void testAddSingleChannel() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertEquals("flags before test", 0, testManager.flags);
+ assertTrue("enabling range", testManager.enableRange(123, 123, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 123, 123, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 123, 123, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ }
+
+ public void testRemoveSingleChannel() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertTrue("enabling range", testManager.enableRange(123, 123, "client1"));
+ assertEquals("flags after enable", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ testManager.reset();
+ assertTrue("disabling range", testManager.disableRange(123, 123, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 123, 123, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", FLAG_START_UPDATE_CALLED | FLAG_FINISH_UPDATE_CALLED,
+ testManager.flags);
+ assertEquals("configlist size", 0, testManager.mConfigList.size());
+ }
+
+ public void testRemoveBadChannel() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertFalse("disabling missing range", testManager.disableRange(123, 123, "client1"));
+ assertEquals("flags after test", 0, testManager.flags);
+ assertEquals("configlist size", 0, testManager.mConfigList.size());
+ }
+
+ public void testAddTwoChannels() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertEquals("flags before test", 0, testManager.flags);
+ assertTrue("enabling range 1", testManager.enableRange(100, 120, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 120, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("enabling range 2", testManager.enableRange(200, 250, "client2"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 200, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 2, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 120, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(1), 200, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ }
+
+ public void testOverlappingChannels() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertEquals("flags before test", 0, testManager.flags);
+ assertTrue("enabling range 1", testManager.enableRange(100, 200, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("enabling range 2", testManager.enableRange(150, 250, "client2"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 201, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 1", testManager.disableRange(100, 200, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 149, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("disabling range 2", testManager.disableRange(150, 250, "client2"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 150, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", FLAG_START_UPDATE_CALLED | FLAG_FINISH_UPDATE_CALLED,
+ testManager.flags);
+ assertEquals("configlist size", 0, testManager.mConfigList.size());
+ }
+
+ public void testOverlappingChannels2() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertEquals("flags before test", 0, testManager.flags);
+ assertTrue("enabling range 1", testManager.enableRange(100, 200, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("enabling range 2", testManager.enableRange(150, 250, "client2"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 201, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 2", testManager.disableRange(150, 250, "client2"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 201, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 1", testManager.disableRange(100, 200, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ }
+
+ public void testMultipleOverlappingChannels() {
+ TestIntRangeManager testManager = new TestIntRangeManager();
+ assertEquals("flags before test", 0, testManager.flags);
+ assertTrue("enabling range 1", testManager.enableRange(67, 9999, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 67, 9999, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("enabling range 2", testManager.enableRange(150, 250, "client2"));
+ assertEquals("flags after test", 0, testManager.flags);
+ assertEquals("configlist size", 0, testManager.mConfigList.size());
+ testManager.reset();
+ assertTrue("enabling range 3", testManager.enableRange(25, 75, "client3"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 25, 66, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("enabling range 4", testManager.enableRange(12, 500, "client4"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 12, 24, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("enabling range 5", testManager.enableRange(8000, 9998, "client5"));
+ assertEquals("flags after test", 0, testManager.flags);
+ assertEquals("configlist size", 0, testManager.mConfigList.size());
+ testManager.reset();
+ assertTrue("enabling range 6", testManager.enableRange(50000, 65535, "client6"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 50000, 65535, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 2, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 12, 9999, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(1), 50000, 65535, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 1", testManager.disableRange(67, 9999, "client1"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 2, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 501, 7999, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ checkConfigInfo(testManager.mConfigList.get(1), 9999, 9999, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 3, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 12, 500, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(1), 8000, 9998, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(2), 50000, 65535, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 4", testManager.disableRange(12, 500, "client4"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 3, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 12, 24, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ checkConfigInfo(testManager.mConfigList.get(1), 76, 149, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ checkConfigInfo(testManager.mConfigList.get(2), 251, 500, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 4, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(1), 150, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(2), 8000, 9998, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(3), 50000, 65535, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 5", testManager.disableRange(8000, 9998, "client5"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 8000, 9998, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 3, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(1), 150, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(2), 50000, 65535, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 6", testManager.disableRange(50000, 65535, "client6"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 50000, 65535, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 2, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ checkConfigInfo(testManager.mConfigList.get(1), 150, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 2", testManager.disableRange(150, 250, "client2"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 150, 250, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, true);
+ testManager.reset();
+ assertTrue("disabling range 3", testManager.disableRange(25, 75, "client3"));
+ assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags);
+ assertEquals("configlist size", 1, testManager.mConfigList.size());
+ checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN,
+ SMS_CB_CODE_SCHEME_MAX, false);
+ testManager.reset();
+ assertTrue("updating ranges", testManager.updateRanges());
+ assertEquals("flags after test", FLAG_START_UPDATE_CALLED | FLAG_FINISH_UPDATE_CALLED,
+ testManager.flags);
+ assertEquals("configlist size", 0, testManager.mConfigList.size());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
new file mode 100644
index 0000000..868c76d
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.MccTable;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.util.Log;
+
+public class MccTableTest extends AndroidTestCase {
+ private final static String LOG_TAG = "GSM";
+
+ @SmallTest
+ public void testTimeZone() throws Exception {
+ assertEquals(MccTable.defaultTimeZoneForMcc(208), "ECT");
+ assertEquals(MccTable.defaultTimeZoneForMcc(232), "Europe/Vienna");
+ assertEquals(MccTable.defaultTimeZoneForMcc(655), "Africa/Johannesburg");
+ assertEquals(MccTable.defaultTimeZoneForMcc(440), "Asia/Tokyo");
+ assertEquals(MccTable.defaultTimeZoneForMcc(441), "Asia/Tokyo");
+ assertEquals(MccTable.defaultTimeZoneForMcc(525), "Asia/Singapore");
+ assertEquals(MccTable.defaultTimeZoneForMcc(240), null); // tz not defined, hence default
+ assertEquals(MccTable.defaultTimeZoneForMcc(0), null); // mcc not defined, hence default
+ assertEquals(MccTable.defaultTimeZoneForMcc(2000), null); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testCountryCode() throws Exception {
+ assertEquals(MccTable.countryCodeForMcc(270), "lu");
+ assertEquals(MccTable.countryCodeForMcc(202), "gr");
+ assertEquals(MccTable.countryCodeForMcc(750), "fk");
+ assertEquals(MccTable.countryCodeForMcc(646), "mg");
+ assertEquals(MccTable.countryCodeForMcc(314), "us");
+ assertEquals(MccTable.countryCodeForMcc(300), ""); // mcc not defined, hence default
+ assertEquals(MccTable.countryCodeForMcc(0), ""); // mcc not defined, hence default
+ assertEquals(MccTable.countryCodeForMcc(2000), ""); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testLang() throws Exception {
+ assertEquals(MccTable.defaultLanguageForMcc(311), "en");
+ assertEquals(MccTable.defaultLanguageForMcc(232), "de");
+ assertEquals(MccTable.defaultLanguageForMcc(230), "cs");
+ assertEquals(MccTable.defaultLanguageForMcc(204), "nl");
+ assertEquals(MccTable.defaultLanguageForMcc(274), null); // lang not defined, hence default
+ assertEquals(MccTable.defaultLanguageForMcc(0), null); // mcc not defined, hence default
+ assertEquals(MccTable.defaultLanguageForMcc(2000), null); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testSmDigits() throws Exception {
+ assertEquals(MccTable.smallestDigitsMccForMnc(312), 3);
+ assertEquals(MccTable.smallestDigitsMccForMnc(430), 2);
+ assertEquals(MccTable.smallestDigitsMccForMnc(365), 3);
+ assertEquals(MccTable.smallestDigitsMccForMnc(536), 2);
+ assertEquals(MccTable.smallestDigitsMccForMnc(352), 2); // sd not defined, hence default
+ assertEquals(MccTable.smallestDigitsMccForMnc(0), 2); // mcc not defined, hence default
+ assertEquals(MccTable.smallestDigitsMccForMnc(2000), 2); // mcc not defined, hence default
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
new file mode 100644
index 0000000..b63dc71
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.telephony.NeighboringCellInfo;
+import android.test. suitebuilder.annotation.SmallTest;
+
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+
+public class NeighboringCellInfoTest extends AndroidTestCase {
+ @SmallTest
+ public void testConstructor() {
+ int rssi = 31;
+ NeighboringCellInfo nc;
+
+ nc = new NeighboringCellInfo(rssi, "FFFFFFF", NETWORK_TYPE_EDGE);
+ assertEquals(NETWORK_TYPE_EDGE, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(0xfff, nc.getLac());
+ assertEquals(0xffff, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+ nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UMTS);
+ assertEquals(NETWORK_TYPE_UMTS, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+ assertEquals(0x1ff, nc.getPsc());
+
+ nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UNKNOWN);
+ assertEquals(NETWORK_TYPE_UNKNOWN, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+ }
+
+ @SmallTest
+ public void testParcel() {
+ int rssi = 20;
+
+ NeighboringCellInfo nc = new NeighboringCellInfo(rssi, "12345678", NETWORK_TYPE_GPRS);
+ assertEquals(NETWORK_TYPE_GPRS, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(0x1234, nc.getLac());
+ assertEquals(0x5678, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ nc.writeToParcel(p, 0);
+
+ p.setDataPosition(0);
+ NeighboringCellInfo nw = new NeighboringCellInfo(p);
+ assertEquals(NETWORK_TYPE_GPRS, nw.getNetworkType());
+ assertEquals(rssi, nw.getRssi());
+ assertEquals(0x1234, nw.getLac());
+ assertEquals(0x5678, nw.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nw.getPsc());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
new file mode 100644
index 0000000..db670f8
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableStringBuilder;
+import android.telephony.PhoneNumberUtils;
+
+public class PhoneNumberUtilsTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testExtractNetworkPortion() throws Exception {
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortion("+17005554141")
+ );
+
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortion("+1 (700).555-4141")
+ );
+
+ assertEquals(
+ "17005554141",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-4141")
+ );
+
+ // This may seem wrong, but it's probably ok
+ assertEquals(
+ "17005554141*#",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-4141*#")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN,1234")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN;1234")
+ );
+
+ // An MMI string is unperterbed, even though it contains a
+ // (valid in this case) embedded +
+ assertEquals(
+ "**21**17005554141#",
+ PhoneNumberUtils.extractNetworkPortion("**21**+17005554141#")
+ //TODO this is the correct result, although the above
+ //result has been returned since change 31776
+ //"**21**+17005554141#"
+ );
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortion(""));
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortion(",1234"));
+
+ byte [] b = new byte[20];
+ b[0] = (byte) 0x81; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x80; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x90; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ byte[] bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("+17005550020");
+ assertEquals(7, bRet.length);
+ for (int i = 0; i < 7; i++) {
+ assertEquals(b[i], bRet[i]);
+ }
+
+ bRet = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength("+17005550020");
+ assertEquals(8, bRet.length);
+ assertEquals(bRet[0], 7);
+ for (int i = 1; i < 8; i++) {
+ assertEquals(b[i - 1], bRet[i]);
+ }
+
+ bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("7005550020");
+ assertEquals("7005550020",
+ PhoneNumberUtils.calledPartyBCDToString(bRet, 0, bRet.length));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xB0;
+ assertEquals("17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xB0;
+ assertEquals("+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1;
+ assertEquals("*21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2B; b[2] = (byte) 0xB1;
+ assertEquals("#21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1;
+ assertEquals("*21#+",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0xFB;
+ assertEquals("**21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 4));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0xFB;
+ assertEquals("**21#+",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 4));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x9A; b[2] = (byte) 0xA9; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xB0;
+ assertEquals("*99*17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x9A; b[2] = (byte) 0xA9; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xB0;
+ assertEquals("*99*+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0x1A;
+ b[4] = (byte) 0x07; b[5] = (byte) 0x50; b[6] = (byte) 0x55; b[7] = (byte) 0x00;
+ b[8] = (byte) 0x02; b[9] = (byte) 0xFB;
+ assertEquals("**21*17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 10));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0x1A;
+ b[4] = (byte) 0x07; b[5] = (byte) 0x50; b[6] = (byte) 0x55; b[7] = (byte) 0x00;
+ b[8] = (byte) 0x02; b[9] = (byte) 0xFB;
+ assertEquals("**21*+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 10));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2A; b[2] = (byte) 0xA1; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xF0;
+ assertEquals("*21*17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xF0;
+ assertEquals("*21#+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ assertNull(PhoneNumberUtils.extractNetworkPortion(null));
+ assertNull(PhoneNumberUtils.extractPostDialPortion(null));
+ assertTrue(PhoneNumberUtils.compare(null, null));
+ assertFalse(PhoneNumberUtils.compare(null, "123"));
+ assertFalse(PhoneNumberUtils.compare("123", null));
+ assertNull(PhoneNumberUtils.toCallerIDMinMatch(null));
+ assertNull(PhoneNumberUtils.getStrippedReversed(null));
+ assertNull(PhoneNumberUtils.stringFromStringAndTOA(null, 1));
+ }
+
+ @SmallTest
+ public void testExtractNetworkPortionAlt() throws Exception {
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortionAlt("+17005554141")
+ );
+
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortionAlt("+1 (700).555-4141")
+ );
+
+ assertEquals(
+ "17005554141",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-4141")
+ );
+
+ // This may seem wrong, but it's probably ok
+ assertEquals(
+ "17005554141*#",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-4141*#")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-41NN")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-41NN,1234")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-41NN;1234")
+ );
+
+ // An MMI string is unperterbed, even though it contains a
+ // (valid in this case) embedded +
+ assertEquals(
+ "**21**+17005554141#",
+ PhoneNumberUtils.extractNetworkPortionAlt("**21**+17005554141#")
+ );
+
+ assertEquals(
+ "*31#+447966164208",
+ PhoneNumberUtils.extractNetworkPortionAlt("*31#+447966164208")
+ );
+
+ assertEquals(
+ "*31#+447966164208",
+ PhoneNumberUtils.extractNetworkPortionAlt("*31# (+44) 79 6616 4208")
+ );
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortionAlt(""));
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortionAlt(",1234"));
+
+ assertNull(PhoneNumberUtils.extractNetworkPortionAlt(null));
+ }
+
+ @SmallTest
+ public void testB() throws Exception {
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+17005554141"));
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-4141"));
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN"));
+ assertEquals(",1234", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN,1234"));
+ assertEquals(";1234", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN;1234"));
+ assertEquals(";1234,;N",
+ PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN;1-2.34 ,;N"));
+ }
+
+ @SmallTest
+ public void testCompare() throws Exception {
+ // this is odd
+ assertFalse(PhoneNumberUtils.compare("", ""));
+
+ assertTrue(PhoneNumberUtils.compare("911", "911"));
+ assertFalse(PhoneNumberUtils.compare("911", "18005550911"));
+ assertTrue(PhoneNumberUtils.compare("5555", "5555"));
+ assertFalse(PhoneNumberUtils.compare("5555", "180055555555"));
+
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+17005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+1 (700).555-4141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+1 (700).555-4141,1234"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "17005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "7005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "5554141"));
+ assertTrue(PhoneNumberUtils.compare("17005554141", "5554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "01117005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "0017005554141"));
+ assertTrue(PhoneNumberUtils.compare("17005554141", "0017005554141"));
+
+
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "**31#+17005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("+1 999 7005554141", "+1 7005554141"));
+ assertTrue(PhoneNumberUtils.compare("011 1 7005554141", "7005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("011 11 7005554141", "+17005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("+17005554141", "7085882300"));
+
+ assertTrue(PhoneNumberUtils.compare("+44 207 792 3490", "0 207 792 3490"));
+
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "00 207 792 3490"));
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "011 207 792 3490"));
+
+ /***** FIXME's ******/
+ //
+ // MMI header should be ignored
+ assertFalse(PhoneNumberUtils.compare("+17005554141", "**31#17005554141"));
+
+ // It's too bad this is false
+ // +44 (0) 207 792 3490 is not a dialable number
+ // but it is commonly how European phone numbers are written
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "+44 (0) 207 792 3490"));
+
+ // The japanese international prefix, for example, messes us up
+ // But who uses a GSM phone in Japan?
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "010 44 207 792 3490"));
+
+ // The Australian one messes us up too
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "0011 44 207 792 3490"));
+
+ // The Russian trunk prefix messes us up, as does current
+ // Russian area codes (which bein with 0)
+
+ assertFalse(PhoneNumberUtils.compare("+7(095)9100766", "8(095)9100766"));
+
+ // 444 is not a valid country code, but
+ // matchIntlPrefixAndCC doesnt know this
+ assertTrue(PhoneNumberUtils.compare("+444 207 792 3490", "0 207 792 3490"));
+
+ // compare SMS short code
+ assertTrue(PhoneNumberUtils.compare("404-04", "40404"));
+ }
+
+
+ @SmallTest
+ public void testToCallerIDIndexable() throws Exception {
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("17005554141"));
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141"));
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141,1234"));
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141;1234"));
+
+ //this seems wrong, or at least useless
+ assertEquals("NN14555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-41NN"));
+
+ //<shrug> -- these are all not useful, but not terribly wrong
+ assertEquals("", PhoneNumberUtils.toCallerIDMinMatch(""));
+ assertEquals("0032", PhoneNumberUtils.toCallerIDMinMatch("2300"));
+ assertEquals("0032+", PhoneNumberUtils.toCallerIDMinMatch("+2300"));
+ assertEquals("#130#*", PhoneNumberUtils.toCallerIDMinMatch("*#031#"));
+ }
+
+ @SmallTest
+ public void testGetIndexable() throws Exception {
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141"));
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141,1234"));
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141;1234"));
+
+ //this seems wrong, or at least useless
+ assertEquals("NN145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-41NN"));
+
+ //<shrug> -- these are all not useful, but not terribly wrong
+ assertEquals("", PhoneNumberUtils.getStrippedReversed(""));
+ assertEquals("0032", PhoneNumberUtils.getStrippedReversed("2300"));
+ assertEquals("0032+", PhoneNumberUtils.getStrippedReversed("+2300"));
+ assertEquals("#130#*", PhoneNumberUtils.getStrippedReversed("*#031#"));
+ }
+
+ @SmallTest
+ public void testNanpFormatting() {
+ SpannableStringBuilder number = new SpannableStringBuilder();
+ number.append("8005551212");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-1212", number.toString());
+
+ number.clear();
+ number.append("800555121");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-121", number.toString());
+
+ number.clear();
+ number.append("555-1212");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("555-1212", number.toString());
+
+ number.clear();
+ number.append("800-55512");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-12", number.toString());
+
+ number.clear();
+ number.append("46645");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("46645", number.toString());
+ }
+
+ @SmallTest
+ public void testConvertKeypadLettersToDigits() {
+ assertEquals("1-800-4664-411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1-800-GOOG-411"));
+ assertEquals("18004664411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1800GOOG411"));
+ assertEquals("1-800-466-4411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1-800-466-4411"));
+ assertEquals("18004664411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("18004664411"));
+ assertEquals("222-333-444-555-666-7777-888-9999",
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ "ABC-DEF-GHI-JKL-MNO-PQRS-TUV-WXYZ"));
+ assertEquals("222-333-444-555-666-7777-888-9999",
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ "abc-def-ghi-jkl-mno-pqrs-tuv-wxyz"));
+ assertEquals("(800) 222-3334",
+ PhoneNumberUtils.convertKeypadLettersToDigits("(800) ABC-DEFG"));
+ }
+
+ // To run this test, the device has to be registered with network
+ public void testCheckAndProcessPlusCode() {
+ assertEquals("0118475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000"));
+ assertEquals("18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+18475797000"));
+ assertEquals("0111234567",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+1234567"));
+ assertEquals("01123456700000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+23456700000"));
+ assertEquals("01111875767800",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+11875767800"));
+ assertEquals("8475797000,18475231753",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,+18475231753"));
+ assertEquals("0118475797000,18475231753",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000,+18475231753"));
+ assertEquals("8475797000;0118469312345",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;+8469312345"));
+ assertEquals("8475797000,0111234567",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,+1234567"));
+ assertEquals("847597000;01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("847597000;+11875767000"));
+ assertEquals("8475797000,,0118469312345",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,,+8469312345"));
+ assertEquals("8475797000;,0118469312345",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,+8469312345"));
+ assertEquals("8475797000,;18475231753",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,;+18475231753"));
+ assertEquals("8475797000;,01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,+11875767000"));
+ assertEquals("8475797000,;01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,;+11875767000"));
+ assertEquals("8475797000,,,01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,,,+11875767000"));
+ assertEquals("8475797000;,,01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,,+11875767000"));
+ assertEquals("+;,8475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+;,8475797000"));
+ assertEquals("8475797000,",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,"));
+ assertEquals("847+579-7000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("847+579-7000"));
+ assertEquals(",8475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode(",8475797000"));
+ assertEquals(";;8475797000,,",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode(";;8475797000,,"));
+ assertEquals("+this+is$weird;,+",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+this+is$weird;,+"));
+ assertEquals("",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode(""));
+ assertNull(PhoneNumberUtils.cdmaCheckAndProcessPlusCode(null));
+ }
+
+ @SmallTest
+ public void testCheckAndProcessPlusCodeByNumberFormat() {
+ assertEquals("18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_NANP,PhoneNumberUtils.FORMAT_NANP));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_NANP,PhoneNumberUtils.FORMAT_JAPAN));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_NANP,PhoneNumberUtils.FORMAT_UNKNOWN));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_JAPAN,PhoneNumberUtils.FORMAT_JAPAN));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_UNKNOWN,PhoneNumberUtils.FORMAT_UNKNOWN));
+ }
+
+ /**
+ * Basic checks for the VoiceMail number.
+ */
+ @SmallTest
+ public void testWithNumberNotEqualToVoiceMail() throws Exception {
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber("911"));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911"));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567"));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber(""));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber(null));
+ // This test fails on a device without a sim card
+ /*TelephonyManager mTelephonyManager =
+ (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ String mVoiceMailNumber = mTelephonyManager.getDefault().getVoiceMailNumber();
+ assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber));
+ */
+ }
+
+ @SmallTest
+ public void testFormatNumberToE164() {
+ // Note: ISO 3166-1 only allows upper case country codes.
+ assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
+ assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
+ assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
+ }
+
+ @SmallTest
+ public void testFormatNumber() {
+ assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US"));
+ assertEquals("223-4567", PhoneNumberUtils.formatNumber("2234567", "US"));
+ assertEquals("011 86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("011861088880000", "US"));
+ assertEquals("010 8888 0000", PhoneNumberUtils.formatNumber("01088880000", "CN"));
+ // formatNumber doesn't format alpha numbers, but keep them as they are.
+ assertEquals("800-GOOG-114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US"));
+ }
+
+ @SmallTest
+ public void testFormatNumber_LeadingStarAndHash() {
+ // Numbers with a leading '*' or '#' should be left unchanged.
+ assertEquals("*650 2910000", PhoneNumberUtils.formatNumber("*650 2910000", "US"));
+ assertEquals("#650 2910000", PhoneNumberUtils.formatNumber("#650 2910000", "US"));
+ assertEquals("*#650 2910000", PhoneNumberUtils.formatNumber("*#650 2910000", "US"));
+ assertEquals("#*650 2910000", PhoneNumberUtils.formatNumber("#*650 2910000", "US"));
+ assertEquals("#650*2910000", PhoneNumberUtils.formatNumber("#650*2910000", "US"));
+ assertEquals("#650*2910000", PhoneNumberUtils.formatNumber("#650*2910000", "US"));
+ assertEquals("##650 2910000", PhoneNumberUtils.formatNumber("##650 2910000", "US"));
+ assertEquals("**650 2910000", PhoneNumberUtils.formatNumber("**650 2910000", "US"));
+ }
+
+ @SmallTest
+ public void testNormalizeNumber() {
+ assertEquals("6502910000", PhoneNumberUtils.normalizeNumber("650 2910000"));
+ assertEquals("1234567", PhoneNumberUtils.normalizeNumber("12,3#4*567"));
+ assertEquals("8004664114", PhoneNumberUtils.normalizeNumber("800-GOOG-114"));
+ assertEquals("+16502910000", PhoneNumberUtils.normalizeNumber("+1 650 2910000"));
+ }
+
+ @SmallTest
+ public void testFormatDailabeNumber() {
+ // Using the phoneNumberE164's country code
+ assertEquals("(650) 291-0000",
+ PhoneNumberUtils.formatNumber("6502910000", "+16502910000", "CN"));
+ // Using the default country code for a phone number containing the IDD
+ assertEquals("011 86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("011861088880000", "+861088880000", "US"));
+ assertEquals("00 86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("00861088880000", "+861088880000", "GB"));
+ assertEquals("+86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("+861088880000", "+861088880000", "GB"));
+ // Wrong default country, so no formatting is done
+ assertEquals("011861088880000",
+ PhoneNumberUtils.formatNumber("011861088880000", "+861088880000", "GB"));
+ // The phoneNumberE164 is null
+ assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("6502910000", null, "US"));
+ // The given number has a country code.
+ assertEquals("+1 650-291-0000", PhoneNumberUtils.formatNumber("+16502910000", null, "CN"));
+ // The given number was formatted.
+ assertEquals("650-291-0000", PhoneNumberUtils.formatNumber("650-291-0000", null, "US"));
+ // A valid Polish number should be formatted.
+ assertEquals("506 128 687", PhoneNumberUtils.formatNumber("506128687", null, "PL"));
+ // An invalid Polish number should be left as it is. Note Poland doesn't use '0' as a
+ // national prefix; therefore, the leading '0' makes the number invalid.
+ assertEquals("0506128687", PhoneNumberUtils.formatNumber("0506128687", null, "PL"));
+ // Wrong default country, so no formatting is done
+ assertEquals("011861088880000",
+ PhoneNumberUtils.formatNumber("011861088880000", "", "GB"));
+ }
+
+ @SmallTest
+ public void testIsEmergencyNumber() {
+ // There are two parallel sets of tests here: one for the
+ // regular isEmergencyNumber() method, and the other for
+ // isPotentialEmergencyNumber().
+ //
+ // (The difference is that isEmergencyNumber() will return true
+ // only if the specified number exactly matches an actual
+ // emergency number, but isPotentialEmergencyNumber() will
+ // return true if the specified number simply starts with the
+ // same digits as any actual emergency number.)
+
+ // Tests for isEmergencyNumber():
+ assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US"));
+ assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US"));
+ // The next two numbers are not valid phone numbers in the US,
+ // so do not count as emergency numbers (but they *are* "potential"
+ // emergency numbers; see below.)
+ assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "US"));
+ assertFalse(PhoneNumberUtils.isEmergencyNumber("11212345", "US"));
+ // A valid mobile phone number from Singapore shouldn't be classified as an emergency number
+ // in Singapore, as 911 is not an emergency number there.
+ assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG"));
+ // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
+ // in Brazil, as 112 is not an emergency number there.
+ assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR"));
+ // A valid local phone number from Brazil shouldn't be classified as an emergency number in
+ // Brazil.
+ assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR"));
+
+ // Tests for isPotentialEmergencyNumber():
+ // These first two are obviously emergency numbers:
+ assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("911", "US"));
+ assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("112", "US"));
+ // The next two numbers are not valid phone numbers in the US, but can be used to trick the
+ // system to dial 911 and 112, which are emergency numbers in the US. For the purpose of
+ // addressing that, they are also classified as "potential" emergency numbers in the US.
+ assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "US"));
+ assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("11212345", "US"));
+
+ // A valid mobile phone number from Singapore shouldn't be classified as an emergency number
+ // in Singapore, as 911 is not an emergency number there.
+ // This test fails on devices that have ecclist property preloaded with 911.
+ // assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91121234", "SG"));
+
+ // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
+ // in Brazil, as 112 is not an emergency number there.
+ assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("1121234567", "BR"));
+ // A valid local phone number from Brazil shouldn't be classified as an emergency number in
+ // Brazil.
+ assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "BR"));
+ }
+
+ @SmallTest
+ public void testStripSeparators() {
+ // Smoke tests which should never fail.
+ assertEquals("1234567890", PhoneNumberUtils.stripSeparators("1234567890"));
+ assertEquals("911", PhoneNumberUtils.stripSeparators("911"));
+ assertEquals("112", PhoneNumberUtils.stripSeparators("112"));
+
+ // Separators should be removed, while '+' or any other digits should not.
+ assertEquals("+16502910000", PhoneNumberUtils.stripSeparators("+1 (650) 291-0000"));
+
+ // WAIT, PAUSE should *not* be stripped
+ assertEquals("+16502910000,300;",
+ PhoneNumberUtils.stripSeparators("+1 (650) 291-0000, 300;"));
+ }
+
+ @SmallTest
+ public void testConvertAndStrip() {
+ // Smoke tests which should never fail.
+ assertEquals("1234567890", PhoneNumberUtils.convertAndStrip("1234567890"));
+ assertEquals("911", PhoneNumberUtils.convertAndStrip("911"));
+ assertEquals("112", PhoneNumberUtils.convertAndStrip("112"));
+
+ // It should convert keypad characters into digits, and strip separators
+ assertEquals("22233344455566677778889999",
+ PhoneNumberUtils.convertAndStrip("ABC DEF GHI JKL MNO PQR STUV WXYZ"));
+
+ // Test real cases.
+ assertEquals("18004664411", PhoneNumberUtils.convertAndStrip("1-800-GOOG-411"));
+ assertEquals("8002223334", PhoneNumberUtils.convertAndStrip("(800) ABC-DEFG"));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
new file mode 100644
index 0000000..a6a0fce
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony;
+
+import android.telephony.PhoneNumberFormattingTextWatcher;
+import android.test.AndroidTestCase;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+import android.text.TextWatcher;
+
+public class PhoneNumberWatcherTest extends AndroidTestCase {
+ public void testAppendChars() {
+ final String multiChars = "65012345";
+ final String formatted1 = "(650) 123-45";
+ TextWatcher textWatcher = getTextWatcher();
+ SpannableStringBuilder number = new SpannableStringBuilder();
+ // Append more than one chars
+ textWatcher.beforeTextChanged(number, 0, 0, multiChars.length());
+ number.append(multiChars);
+ Selection.setSelection(number, number.length());
+ textWatcher.onTextChanged(number, 0, 0, number.length());
+ textWatcher.afterTextChanged(number);
+ assertEquals(formatted1, number.toString());
+ assertEquals(formatted1.length(), Selection.getSelectionEnd(number));
+ // Append one chars
+ final char appendChar = '6';
+ final String formatted2 = "(650) 123-456";
+ int len = number.length();
+ textWatcher.beforeTextChanged(number, number.length(), 0, 1);
+ number.append(appendChar);
+ Selection.setSelection(number, number.length());
+ textWatcher.onTextChanged(number, len, 0, 1);
+ textWatcher.afterTextChanged(number);
+ assertEquals(formatted2, number.toString());
+ assertEquals(formatted2.length(), Selection.getSelectionEnd(number));
+ }
+
+ public void testRemoveLastChars() {
+ final String init = "65012345678";
+ final String result1 = "(650) 123-4567";
+ TextWatcher textWatcher = getTextWatcher();
+ // Remove the last char.
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+ int len = number.length();
+ textWatcher.beforeTextChanged(number, len - 1, 1, 0);
+ number.delete(len - 1, len);
+ Selection.setSelection(number, number.length());
+ textWatcher.onTextChanged(number, number.length() - 1, 1, 0);
+ textWatcher.afterTextChanged(number);
+ assertEquals(result1, number.toString());
+ assertEquals(result1.length(), Selection.getSelectionEnd(number));
+ // Remove last 5 chars
+ final String result2 = "650-123";
+ textWatcher.beforeTextChanged(number, number.length() - 4, 4, 0);
+ number.delete(number.length() - 5, number.length());
+ Selection.setSelection(number, number.length());
+ textWatcher.onTextChanged(number, number.length(), 4, 0);
+ textWatcher.afterTextChanged(number);
+ assertEquals(result2, number.toString());
+ assertEquals(result2.length(), Selection.getSelectionEnd(number));
+ }
+
+ public void testInsertChars() {
+ final String init = "650-23";
+ final String expected1 = "650-123";
+ TextWatcher textWatcher = getTextWatcher();
+
+ // Insert one char
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 3, 0, 1);
+ number.insert(3, "1"); // 6501-23
+ Selection.setSelection(number, 4); // make the cursor at right of 1
+ textWatcher.onTextChanged(number, 3, 0, 1);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected1, number.toString());
+ // the cursor should still at the right of '1'
+ assertEquals(5, Selection.getSelectionEnd(number));
+
+ // Insert multiple chars
+ final String expected2 = "(650) 145-6723";
+ textWatcher.beforeTextChanged(number, 5, 0, 4);
+ number.insert(5, "4567"); // change to 650-1456723
+ Selection.setSelection(number, 9); // the cursor is at the right of '7'.
+ textWatcher.onTextChanged(number, 7, 0, 4);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected2, number.toString());
+ // the cursor should be still at the right of '7'
+ assertEquals(12, Selection.getSelectionEnd(number));
+ }
+
+ public void testStopFormatting() {
+ final String init = "(650) 123";
+ final String expected1 = "(650) 123 4";
+ TextWatcher textWatcher = getTextWatcher();
+
+ // Append space
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 9, 0, 2);
+ number.insert(9, " 4"); // (6501) 23 4
+ Selection.setSelection(number, number.length()); // make the cursor at right of 4
+ textWatcher.onTextChanged(number, 9, 0, 2);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected1, number.toString());
+ // the cursor should still at the right of '1'
+ assertEquals(expected1.length(), Selection.getSelectionEnd(number));
+
+ // Delete a ')'
+ final String expected2 ="(650 123";
+ textWatcher = getTextWatcher();
+ number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 4, 1, 0);
+ number.delete(4, 5); // (6501 23 4
+ Selection.setSelection(number, 5); // make the cursor at right of 1
+ textWatcher.onTextChanged(number, 4, 1, 0);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected2, number.toString());
+ // the cursor should still at the right of '1'
+ assertEquals(5, Selection.getSelectionEnd(number));
+
+ // Insert a hyphen
+ final String expected3 ="(650) 12-3";
+ textWatcher = getTextWatcher();
+ number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 8, 0, 1);
+ number.insert(8, "-"); // (650) 12-3
+ Selection.setSelection(number, 9); // make the cursor at right of -
+ textWatcher.onTextChanged(number, 8, 0, 1);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected3, number.toString());
+ // the cursor should still at the right of '-'
+ assertEquals(9, Selection.getSelectionEnd(number));
+ }
+
+ public void testRestartFormatting() {
+ final String init = "(650) 123";
+ final String expected1 = "(650) 123 4";
+ TextWatcher textWatcher = getTextWatcher();
+
+ // Append space
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 9, 0, 2);
+ number.insert(9, " 4"); // (650) 123 4
+ Selection.setSelection(number, number.length()); // make the cursor at right of 4
+ textWatcher.onTextChanged(number, 9, 0, 2);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected1, number.toString());
+ // the cursor should still at the right of '4'
+ assertEquals(expected1.length(), Selection.getSelectionEnd(number));
+
+ // Clear the current string, and start formatting again.
+ int len = number.length();
+ textWatcher.beforeTextChanged(number, 0, len, 0);
+ number.delete(0, len);
+ textWatcher.onTextChanged(number, 0, len, 0);
+ textWatcher.afterTextChanged(number);
+
+ final String expected2 = "650-1234";
+ number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 9, 0, 1);
+ number.insert(9, "4"); // (650) 1234
+ Selection.setSelection(number, number.length()); // make the cursor at right of 4
+ textWatcher.onTextChanged(number, 9, 0, 1);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected2, number.toString());
+ // the cursor should still at the right of '4'
+ assertEquals(expected2.length(), Selection.getSelectionEnd(number));
+ }
+
+ public void testTextChangedByOtherTextWatcher() {
+ final TextWatcher cleanupTextWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ s.clear();
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before,
+ int count) {
+ }
+ };
+ final String init = "(650) 123";
+ final String expected1 = "";
+ TextWatcher textWatcher = getTextWatcher();
+
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+ textWatcher.beforeTextChanged(number, 5, 0, 1);
+ number.insert(5, "4"); // (6504) 123
+ Selection.setSelection(number, 5); // make the cursor at right of 4
+ textWatcher.onTextChanged(number, 5, 0, 1);
+ number.setSpan(cleanupTextWatcher, 0, number.length(), 0);
+ textWatcher.afterTextChanged(number);
+ assertEquals(expected1, number.toString());
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithFormattedNumber() {
+ String init = "650-1";
+ String expected = "+1-650-123-4567"; // Different formatting than ours
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithFormattedNameAndNumber() {
+ String init = "650-1";
+ String expected = "Test User <650-123-4567>";
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithNumericNameAndNumber() {
+ String init = "650";
+ String expected = "2nd Test User <650-123-4567>";
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithUnformattedNumber() {
+ String init = "650-1";
+ String expected = "6501234567";
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing, where
+ * the deleted text doesn't have any formatting and neither does the replacement text: in this
+ * case the replacement text should be formatted by the PhoneNumberFormattingTextWatcher.
+ */
+ public void testAutoCompleteUnformattedWithUnformattedNumber() {
+ String init = "650";
+ String replacement = "6501234567";
+ String expected = "(650) 123-4567";
+ testReplacement(init, replacement, expected);
+
+ String init2 = "650";
+ String replacement2 = "16501234567";
+ String expected2 = "1 650-123-4567";
+ testReplacement(init2, replacement2, expected2);
+ }
+
+ /**
+ * Helper method for testing replacing the entire string with another string
+ * @param init The initial string
+ * @param expected
+ */
+ private void testReplacement(String init, String replacement, String expected) {
+ TextWatcher textWatcher = getTextWatcher();
+
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+
+ // Replace entire text with the given values
+ textWatcher.beforeTextChanged(number, 0, init.length(), replacement.length());
+ number.replace(0, init.length(), replacement, 0, replacement.length());
+ Selection.setSelection(number, replacement.length()); // move the cursor to the end
+ textWatcher.onTextChanged(number, 0, init.length(), replacement.length());
+ textWatcher.afterTextChanged(number);
+
+ assertEquals(expected, number.toString());
+ // the cursor should be still at the end
+ assertEquals(expected.length(), Selection.getSelectionEnd(number));
+ }
+
+ private TextWatcher getTextWatcher() {
+ return new PhoneNumberFormattingTextWatcher("US");
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java
new file mode 100644
index 0000000..8a66614
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import com.android.internal.telephony.TestPhoneNotifier;
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.Iterator;
+
+/**
+ * {@hide}
+ */
+public class SMSDispatcherTest extends AndroidTestCase {
+ @MediumTest
+ public void testCMT1() throws Exception {
+ SmsMessage sms;
+ SmsHeader header;
+
+ String[] lines = new String[2];
+
+ lines[0] = "+CMT: ,158";
+ lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B"
+ + "8423F000035502010106276170706C69636174696F6E2F766E642E776170"
+ + "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F"
+ + "7547514D4141424C3641414141536741415A4B554141414141008D908918"
+ + "802B31363530323438363137392F545950453D504C4D4E008A808E028000"
+ + "88058103093A8083687474703A2F2F36";
+
+ sms = SmsMessage.newFromCMT(lines);
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(sms.getUserData());
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 85);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 1);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+ }
+
+ @MediumTest
+ public void testCMT2() throws Exception {
+ SmsMessage sms;
+ SmsHeader header;
+
+ String[] lines = new String[2];
+
+ lines[0] = "+CMT: ,77";
+ lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F"
+ + "00003550202362E3130322E3137312E3135302F524F347839776F7547514D4141"
+ + "424C3641414141536741415A4B55414141414100";
+
+ sms = SmsMessage.newFromCMT(lines);
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(sms.getUserData());
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 85);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 2);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+ }
+
+ @MediumTest
+ public void testEfRecord() throws Exception {
+ SmsMessage sms;
+
+ String s = "03029111000c9194981492631000f269206190022000a053e4534a05358bd3"
+ + "69f05804259da0219418a40641536a110a0aea408080604028180e888462c1"
+ + "50341c0f484432a1542c174c46b3e1743c9f9068442a994ea8946ac56ab95e"
+ + "b0986c46abd96eb89c6ec7ebf97ec0a070482c1a8fc8a472c96c3a9fd0a874"
+ + "4aad5aafd8ac76cbed7abfe0b0784c2e9bcfe8b47acd6ebbdff0b87c4eafdb"
+ + "eff8bc7ecfeffbffffffffffffffffffffffffffff";
+ byte[] data = IccUtils.hexStringToBytes(s);
+
+ sms = SmsMessage.createFromEfRecord(1, data);
+ assertNotNull(sms.getMessageBody());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
new file mode 100644
index 0000000..609e768
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@Suppress
+public class SimPhoneBookTest extends TestCase {
+
+ public void testBasic() throws Exception {
+ IIccPhoneBook simPhoneBook =
+ IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
+ assertNotNull(simPhoneBook);
+
+ int size[] = simPhoneBook.getAdnRecordsSize(IccConstants.EF_ADN);
+ assertNotNull(size);
+ assertEquals(3, size.length);
+ assertEquals(size[0] * size[2], size[1]);
+ assertTrue(size[2] >= 100);
+
+ List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ // do it twice cause the second time shall read from cache only
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ assertNotNull(adnRecordList);
+
+ // Test for phone book update
+ int adnIndex, listIndex = 0;
+ AdnRecord originalAdn = null;
+ // We need to maintain the state of the SIM before and after the test.
+ // Since this test doesn't mock the SIM we try to get a valid ADN record,
+ // for 3 tries and if this fails, we bail out.
+ for (adnIndex = 3 ; adnIndex >= 1; adnIndex--) {
+ listIndex = adnIndex - 1; // listIndex is zero based.
+ originalAdn = adnRecordList.get(listIndex);
+ assertNotNull("Original Adn is Null.", originalAdn);
+ assertNotNull("Original Adn alpha tag is null.", originalAdn.getAlphaTag());
+ assertNotNull("Original Adn number is null.", originalAdn.getNumber());
+
+ if (originalAdn.getNumber().length() > 0 &&
+ originalAdn.getAlphaTag().length() > 0) {
+ break;
+ }
+ }
+ if (adnIndex == 0) return;
+
+ AdnRecord emptyAdn = new AdnRecord("", "");
+ AdnRecord firstAdn = new AdnRecord("John", "4085550101");
+ AdnRecord secondAdn = new AdnRecord("Andy", "6505550102");
+ String pin2 = null;
+
+ // udpate by index
+ boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
+ firstAdn.getAlphaTag(), firstAdn.getNumber(), adnIndex, pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ AdnRecord tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(firstAdn.isEqual(tmpAdn));
+
+ // replace by search
+ success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
+ firstAdn.getAlphaTag(), firstAdn.getNumber(),
+ secondAdn.getAlphaTag(), secondAdn.getNumber(), pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertFalse(firstAdn.isEqual(tmpAdn));
+ assertTrue(secondAdn.isEqual(tmpAdn));
+
+ // erase be search
+ success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
+ secondAdn.getAlphaTag(), secondAdn.getNumber(),
+ emptyAdn.getAlphaTag(), emptyAdn.getNumber(), pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(tmpAdn.isEmpty());
+
+ // restore the orginial adn
+ success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
+ originalAdn.getAlphaTag(), originalAdn.getNumber(), adnIndex,
+ pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(originalAdn.isEqual(tmpAdn));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
new file mode 100644
index 0000000..1609680
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class SimSmsTest extends TestCase {
+
+ @MediumTest
+ @Suppress // TODO: suppress this test for now since it doesn't work on the emulator
+ public void testBasic() throws Exception {
+
+ ISms sms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+ assertNotNull(sms);
+
+ List<SmsRawData> records = sms.getAllMessagesFromIccEf();
+ assertNotNull(records);
+ assertTrue(records.size() >= 0);
+
+ int firstNullIndex = -1;
+ int firstValidIndex = -1;
+ byte[] pdu = null;
+ for (int i = 0; i < records.size(); i++) {
+ SmsRawData data = records.get(i);
+ if (data != null && firstValidIndex == -1) {
+ firstValidIndex = i;
+ pdu = data.getBytes();
+ }
+ if (data == null && firstNullIndex == -1) {
+ firstNullIndex = i;
+ }
+ if (firstNullIndex != -1 && firstValidIndex != -1) {
+ break;
+ }
+ }
+ if (firstNullIndex == -1 || firstValidIndex == -1)
+ return;
+ assertNotNull(pdu);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
new file mode 100644
index 0000000..ef62d85
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.gsm.SimTlv;
+import com.android.internal.telephony.IccUtils;
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+
+public class SimUtilsTest extends TestCase {
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ byte[] data, data2;
+
+ /*
+ * bcdToString()
+ */
+
+ // An EF[ICCID] record
+ data = IccUtils.hexStringToBytes("981062400510444868f2");
+ assertEquals("8901260450014484862", IccUtils.bcdToString(data, 0, data.length));
+
+ // skip the first and last bytes
+ assertEquals("0126045001448486", IccUtils.bcdToString(data, 1, data.length - 2));
+
+ // Stops on invalid BCD value
+ data = IccUtils.hexStringToBytes("98E062400510444868f2");
+ assertEquals("890", IccUtils.bcdToString(data, 0, data.length));
+
+ // skip the high nibble 'F' since some PLMNs have it
+ data = IccUtils.hexStringToBytes("98F062400510444868f2");
+ assertEquals("890260450014484862", IccUtils.bcdToString(data, 0, data.length));
+
+ /*
+ * gsmBcdByteToInt()
+ */
+
+ assertEquals(98, IccUtils.gsmBcdByteToInt((byte) 0x89));
+
+ // Out of range is treated as 0
+ assertEquals(8, IccUtils.gsmBcdByteToInt((byte) 0x8c));
+
+ /*
+ * cdmaBcdByteToInt()
+ */
+
+ assertEquals(89, IccUtils.cdmaBcdByteToInt((byte) 0x89));
+
+ // Out of range is treated as 0
+ assertEquals(80, IccUtils.cdmaBcdByteToInt((byte) 0x8c));
+
+ /*
+ * adnStringFieldToString()
+ */
+
+
+ data = IccUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
+ // Again, skip prepended 0
+ // (this is an EF[ADN] record)
+ assertEquals("Voice Mail", IccUtils.adnStringFieldToString(data, 1, data.length - 15));
+
+ data = IccUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
+ // (this is from an EF[ADN] record)
+ assertEquals("\u9673\u539A\u5764/M", IccUtils.adnStringFieldToString(data, 0, data.length));
+
+ data = IccUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
+ // (this is made up to test since I don't have a real one)
+ assertEquals("Vo\u00ECce M\u00E0il", IccUtils.adnStringFieldToString(data, 0, data.length));
+
+ data = IccUtils.hexStringToBytes("820505302D82d32d31");
+ // Example from 3GPP TS 11.11 V18.1.3.0 annex B
+ assertEquals("-\u0532\u0583-1", IccUtils.adnStringFieldToString(data, 0, data.length));
+ }
+
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
new file mode 100644
index 0000000..b848657
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.telephony.SmsMessage;
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import com.android.internal.telephony.SmsConstants;
+
+import java.util.Random;
+
+/**
+ * Test cases to verify selection of the optimal 7 bit encoding tables
+ * (for all combinations of enabled national language tables) for messages
+ * containing Turkish, Spanish, Portuguese, Greek, and other symbols
+ * present in the GSM default and national language tables defined in
+ * 3GPP TS 23.038. Also verifies correct SMS encoding for CDMA, which only
+ * supports the GSM 7 bit default alphabet, ASCII 8 bit, and UCS-2.
+ * Tests both encoding variations: unsupported characters mapped to space,
+ * and unsupported characters force entire message to UCS-2.
+ */
+public class SmsMessageBodyTest extends AndroidTestCase {
+ private static final String TAG = "SmsMessageBodyTest";
+
+ // ASCII chars in the GSM 7 bit default alphabet
+ private static final String sAsciiChars = "@$_ !\"#%&'()*+,-./0123456789" +
+ ":;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\r";
+
+ // Unicode chars in the GSM 7 bit default alphabet and both locking shift tables
+ private static final String sGsmDefaultChars = "\u00a3\u00a5\u00e9\u00c7\u0394\u00c9" +
+ "\u00dc\u00a7\u00fc\u00e0";
+
+ // Unicode chars in the GSM 7 bit default table and Turkish locking shift tables
+ private static final String sGsmDefaultAndTurkishTables = "\u00f9\u00f2\u00c5\u00e5\u00df" +
+ "\u00a4\u00c4\u00d6\u00d1\u00e4\u00f6\u00f1";
+
+ // Unicode chars in the GSM 7 bit default table but not the locking shift tables
+ private static final String sGsmDefaultTableOnly = "\u00e8\u00ec\u00d8\u00f8\u00c6\u00e6" +
+ "\u00a1\u00bf";
+
+ // ASCII chars in the GSM default extension table
+ private static final String sGsmExtendedAsciiChars = "{}[]\f";
+
+ // chars in GSM default extension table and Portuguese locking shift table
+ private static final String sGsmExtendedPortugueseLocking = "^\\|~";
+
+ // Euro currency symbol
+ private static final String sGsmExtendedEuroSymbol = "\u20ac";
+
+ // CJK ideographs, Hiragana, Katakana, full width letters, Cyrillic, etc.
+ private static final String sUnicodeChars = "\u4e00\u4e01\u4e02\u4e03" +
+ "\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d" +
+ "\u4e0e\u4e0f\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048" +
+ "\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8" +
+ "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18" +
+ "\uff70\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78" +
+ "\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408" +
+ "\u00a2\u00a9\u00ae\u2122";
+
+ // chars in Turkish single shift and locking shift tables
+ private static final String sTurkishChars = "\u0131\u011e\u011f\u015e\u015f\u0130";
+
+ // chars in Spanish single shift table and Portuguese single and locking shift tables
+ private static final String sPortugueseAndSpanishChars = "\u00c1\u00e1\u00cd\u00ed"
+ + "\u00d3\u00f3\u00da\u00fa";
+
+ // chars in all national language tables but not in the standard GSM alphabets
+ private static final String sNationalLanguageTablesOnly = "\u00e7";
+
+ // chars in Portuguese single shift and locking shift tables
+ private static final String sPortugueseChars = "\u00ea\u00d4\u00f4\u00c0\u00c2\u00e2"
+ + "\u00ca\u00c3\u00d5\u00e3\u00f5";
+
+ // chars in Portuguese locking shift table only
+ private static final String sPortugueseLockingShiftChars = "\u00aa\u221e\u00ba`";
+
+ // Greek letters in GSM alphabet missing from Portuguese locking and single shift tables
+ private static final String sGreekLettersNotInPortugueseTables = "\u039b\u039e";
+
+ // Greek letters in GSM alphabet and Portuguese single shift (but not locking shift) table
+ private static final String sGreekLettersInPortugueseShiftTable =
+ "\u03a6\u0393\u03a9\u03a0\u03a8\u03a3\u0398";
+
+ // List of classes of characters in SMS tables
+ private static final String[] sCharacterClasses = {
+ sGsmExtendedAsciiChars,
+ sGsmExtendedPortugueseLocking,
+ sGsmDefaultChars,
+ sGsmDefaultAndTurkishTables,
+ sGsmDefaultTableOnly,
+ sGsmExtendedEuroSymbol,
+ sUnicodeChars,
+ sTurkishChars,
+ sPortugueseChars,
+ sPortugueseLockingShiftChars,
+ sPortugueseAndSpanishChars,
+ sGreekLettersNotInPortugueseTables,
+ sGreekLettersInPortugueseShiftTable,
+ sNationalLanguageTablesOnly,
+ sAsciiChars
+ };
+
+ private static final int sNumCharacterClasses = sCharacterClasses.length;
+
+ // For each character class, whether it is present in a particular char table.
+ // First three entries are locking shift tables, followed by four single shift tables
+ private static final boolean[][] sCharClassPresenceInTables = {
+ // ASCII chars in all GSM extension tables
+ {false, false, false, true, true, true, true},
+ // ASCII chars in all GSM extension tables and Portuguese locking shift table
+ {false, false, true, true, true, true, true},
+ // non-ASCII chars in GSM default alphabet and all locking tables
+ {true, true, true, false, false, false, false},
+ // non-ASCII chars in GSM default alphabet and Turkish locking shift table
+ {true, true, false, false, false, false, false},
+ // non-ASCII chars in GSM default alphabet table only
+ {true, false, false, false, false, false, false},
+ // Euro symbol is present in several tables
+ {false, true, true, true, true, true, true},
+ // Unicode characters not present in any 7 bit tables
+ {false, false, false, false, false, false, false},
+ // Characters specific to Turkish language
+ {false, true, false, false, true, false, false},
+ // Characters in Portuguese single shift and locking shift tables
+ {false, false, true, false, false, false, true},
+ // Characters in Portuguese locking shift table only
+ {false, false, true, false, false, false, false},
+ // Chars in Spanish single shift and Portuguese single and locking shift tables
+ {false, false, true, false, false, true, true},
+ // Greek letters in GSM default alphabet missing from Portuguese tables
+ {true, true, false, false, false, false, false},
+ // Greek letters in GSM alphabet and Portuguese single shift table
+ {true, true, false, false, false, false, true},
+ // Chars in all national language tables but not the standard GSM tables
+ {false, true, true, false, true, true, true},
+ // ASCII chars in GSM default alphabet
+ {true, true, true, false, false, false, false}
+ };
+
+ private static final int sTestLengthCount = 12;
+
+ private static final int[] sSeptetTestLengths =
+ { 0, 1, 2, 80, 159, 160, 161, 240, 305, 306, 307, 320};
+
+ private static final int[] sUnicodeTestLengths =
+ { 0, 1, 2, 35, 69, 70, 71, 100, 133, 134, 135, 160};
+
+ private static final int[] sTestMsgCounts =
+ { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3};
+
+ private static final int[] sSeptetUnitsRemaining =
+ {160, 159, 158, 80, 1, 0, 145, 66, 1, 0, 152, 139};
+
+ private static final int[] sUnicodeUnitsRemaining =
+ { 70, 69, 68, 35, 1, 0, 63, 34, 1, 0, 66, 41};
+
+ // Combinations of enabled GSM national language single shift tables
+ private static final int[][] sEnabledSingleShiftTables = {
+ {}, // GSM default alphabet only
+ {1}, // Turkish (single shift only)
+ {1}, // Turkish (single and locking shift)
+ {2}, // Spanish
+ {3}, // Portuguese (single shift only)
+ {3}, // Portuguese (single and locking shift)
+ {1, 2}, // Turkish + Spanish (single shift only)
+ {1, 2}, // Turkish + Spanish (single and locking shift)
+ {1, 3}, // Turkish + Portuguese (single shift only)
+ {1, 3}, // Turkish + Portuguese (single and locking shift)
+ {2, 3}, // Spanish + Portuguese (single shift only)
+ {2, 3}, // Spanish + Portuguese (single and locking shift)
+ {1, 2, 3}, // Turkish, Spanish, Portuguese (single shift only)
+ {1, 2, 3}, // Turkish, Spanish, Portuguese (single and locking shift)
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables
+ };
+
+ // Combinations of enabled GSM national language locking shift tables
+ private static final int[][] sEnabledLockingShiftTables = {
+ {}, // GSM default alphabet only
+ {}, // Turkish (single shift only)
+ {1}, // Turkish (single and locking shift)
+ {}, // Spanish (no locking shift table)
+ {}, // Portuguese (single shift only)
+ {3}, // Portuguese (single and locking shift)
+ {}, // Turkish + Spanish (single shift only)
+ {1}, // Turkish + Spanish (single and locking shift)
+ {}, // Turkish + Portuguese (single shift only)
+ {1, 3}, // Turkish + Portuguese (single and locking shift)
+ {}, // Spanish + Portuguese (single shift only)
+ {3}, // Spanish + Portuguese (single and locking shift)
+ {}, // Turkish, Spanish, Portuguese (single shift only)
+ {1, 3}, // Turkish, Spanish, Portuguese (single and locking shift)
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables
+ };
+
+ // LanguagePair counter indexes to check for each entry above
+ private static final int[][] sLanguagePairIndexesByEnabledIndex = {
+ {0}, // default tables only
+ {0, 1}, // Turkish (single shift only)
+ {0, 1, 4, 5}, // Turkish (single and locking shift)
+ {0, 2}, // Spanish
+ {0, 3}, // Portuguese (single shift only)
+ {0, 3, 8, 11}, // Portuguese (single and locking shift)
+ {0, 1, 2}, // Turkish + Spanish (single shift only)
+ {0, 1, 2, 4, 5, 6}, // Turkish + Spanish (single and locking shift)
+ {0, 1, 3}, // Turkish + Portuguese (single shift only)
+ {0, 1, 3, 4, 5, 7, 8, 9, 11}, // Turkish + Portuguese (single and locking shift)
+ {0, 2, 3}, // Spanish + Portuguese (single shift only)
+ {0, 2, 3, 8, 10, 11}, // Spanish + Portuguese (single and locking shift)
+ {0, 1, 2, 3}, // all languages (single shift only)
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, // all languages (single and locking shift)
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} // all languages (no Indic chars in test)
+ };
+
+ /**
+ * User data header requires one octet for length. Count as one septet, because
+ * all combinations of header elements below will have at least one free bit
+ * when padding to the nearest septet boundary.
+ */
+ private static final int UDH_SEPTET_COST_LENGTH = 1;
+
+ /**
+ * Using a non-default language locking shift table OR single shift table
+ * requires a user data header of 3 octets, or 4 septets, plus UDH length.
+ */
+ private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4;
+
+ /**
+ * Using a non-default language locking shift table AND single shift table
+ * requires a user data header of 6 octets, or 7 septets, plus UDH length.
+ */
+ private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7;
+
+ /**
+ * Multi-part messages require a user data header of 5 octets, or 6 septets,
+ * plus UDH length.
+ */
+ private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
+
+ @SmallTest
+ public void testCalcLengthAscii() throws Exception {
+ StringBuilder sb = new StringBuilder(320);
+ int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
+ int startPos = 0;
+ int asciiCharsLen = sAsciiChars.length();
+
+ for (int i = 0; i < sTestLengthCount; i++) {
+ int len = sSeptetTestLengths[i];
+ assertTrue(sb.length() <= len);
+
+ while (sb.length() < len) {
+ int addCount = len - sb.length();
+ int endPos = (asciiCharsLen - startPos > addCount) ?
+ (startPos + addCount) : asciiCharsLen;
+ sb.append(sAsciiChars, startPos, endPos);
+ startPos = (endPos == asciiCharsLen) ? 0 : endPos;
+ }
+ assertEquals(len, sb.length());
+
+ String testStr = sb.toString();
+ values[0] = sTestMsgCounts[i];
+ values[1] = len;
+ values[2] = sSeptetUnitsRemaining[i];
+
+ callGsmLengthMethods(testStr, false, values);
+ callGsmLengthMethods(testStr, true, values);
+ callCdmaLengthMethods(testStr, false, values);
+ callCdmaLengthMethods(testStr, true, values);
+ }
+ }
+
+ @SmallTest
+ public void testCalcLengthUnicode() throws Exception {
+ StringBuilder sb = new StringBuilder(160);
+ int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0};
+ int[] values7bit = {1, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
+ int startPos = 0;
+ int unicodeCharsLen = sUnicodeChars.length();
+
+ // start with length 1: empty string uses ENCODING_7BIT
+ for (int i = 1; i < sTestLengthCount; i++) {
+ int len = sUnicodeTestLengths[i];
+ assertTrue(sb.length() <= len);
+
+ while (sb.length() < len) {
+ int addCount = len - sb.length();
+ int endPos = (unicodeCharsLen - startPos > addCount) ?
+ (startPos + addCount) : unicodeCharsLen;
+ sb.append(sUnicodeChars, startPos, endPos);
+ startPos = (endPos == unicodeCharsLen) ? 0 : endPos;
+ }
+ assertEquals(len, sb.length());
+
+ String testStr = sb.toString();
+ values[0] = sTestMsgCounts[i];
+ values[1] = len;
+ values[2] = sUnicodeUnitsRemaining[i];
+ values7bit[1] = len;
+ values7bit[2] = SmsConstants.MAX_USER_DATA_SEPTETS - len;
+
+ callGsmLengthMethods(testStr, false, values);
+ callCdmaLengthMethods(testStr, false, values);
+ callGsmLengthMethods(testStr, true, values7bit);
+ callCdmaLengthMethods(testStr, true, values7bit);
+ }
+ }
+
+ private static class LanguagePair {
+ // index is 2 for Portuguese locking shift because there is no Spanish locking shift table
+ private final int langTableIndex;
+ private final int langShiftTableIndex;
+ int length;
+ int missingChars7bit;
+
+ LanguagePair(int langTable, int langShiftTable) {
+ langTableIndex = langTable;
+ langShiftTableIndex = langShiftTable;
+ }
+
+ void clear() {
+ length = 0;
+ missingChars7bit = 0;
+ }
+
+ void addChar(boolean[] charClassTableRow) {
+ if (charClassTableRow[langTableIndex]) {
+ length++;
+ } else if (charClassTableRow[3 + langShiftTableIndex]) {
+ length += 2;
+ } else {
+ length++; // use ' ' for unmapped char in 7 bit only mode
+ missingChars7bit++;
+ }
+ }
+ }
+
+ private static class CounterHelper {
+ LanguagePair[] mCounters;
+ int[] mStatsCounters;
+ int mUnicodeCounter;
+
+ CounterHelper() {
+ mCounters = new LanguagePair[12];
+ mStatsCounters = new int[12];
+ for (int i = 0; i < 12; i++) {
+ mCounters[i] = new LanguagePair(i/4, i%4);
+ }
+ }
+
+ void clear() {
+ // Note: don't clear stats counters
+ for (int i = 0; i < 12; i++) {
+ mCounters[i].clear();
+ }
+ }
+
+ void addChar(int charClass) {
+ boolean[] charClassTableRow = sCharClassPresenceInTables[charClass];
+ for (int i = 0; i < 12; i++) {
+ mCounters[i].addChar(charClassTableRow);
+ }
+ }
+
+ void fillData(int enabledLangsIndex, boolean use7bitOnly, int[] values, int length) {
+ int[] languagePairs = sLanguagePairIndexesByEnabledIndex[enabledLangsIndex];
+ int minNumSeptets = Integer.MAX_VALUE;
+ int minNumSeptetsWithHeader = Integer.MAX_VALUE;
+ int minNumMissingChars = Integer.MAX_VALUE;
+ int langIndex = -1;
+ int langShiftIndex = -1;
+ for (int i : languagePairs) {
+ LanguagePair pair = mCounters[i];
+ int udhLength = 0;
+ if (i != 0) {
+ udhLength = UDH_SEPTET_COST_LENGTH;
+ if (i < 4 || i % 4 == 0) {
+ udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE;
+ } else {
+ udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES;
+ }
+ }
+ int numSeptetsWithHeader;
+ if (pair.length > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) {
+ if (udhLength == 0) {
+ udhLength = UDH_SEPTET_COST_LENGTH;
+ }
+ udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE;
+ int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
+ int msgCount = (pair.length + septetsPerPart - 1) / septetsPerPart;
+ numSeptetsWithHeader = udhLength * msgCount + pair.length;
+ } else {
+ numSeptetsWithHeader = udhLength + pair.length;
+ }
+
+ if (use7bitOnly) {
+ if (pair.missingChars7bit < minNumMissingChars || (pair.missingChars7bit ==
+ minNumMissingChars && numSeptetsWithHeader < minNumSeptetsWithHeader)) {
+ minNumSeptets = pair.length;
+ minNumSeptetsWithHeader = numSeptetsWithHeader;
+ minNumMissingChars = pair.missingChars7bit;
+ langIndex = pair.langTableIndex;
+ langShiftIndex = pair.langShiftTableIndex;
+ }
+ } else {
+ if (pair.missingChars7bit == 0 && numSeptetsWithHeader < minNumSeptetsWithHeader) {
+ minNumSeptets = pair.length;
+ minNumSeptetsWithHeader = numSeptetsWithHeader;
+ langIndex = pair.langTableIndex;
+ langShiftIndex = pair.langShiftTableIndex;
+ }
+ }
+ }
+ if (langIndex == -1) {
+ // nothing matches, use values for Unicode
+ int byteCount = length * 2;
+ if (byteCount > SmsConstants.MAX_USER_DATA_BYTES) {
+ values[0] = (byteCount + SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER - 1) /
+ SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
+ values[2] = ((values[0] * SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER) -
+ byteCount) / 2;
+ } else {
+ values[0] = 1;
+ values[2] = (SmsConstants.MAX_USER_DATA_BYTES - byteCount) / 2;
+ }
+ values[1] = length;
+ values[3] = SmsConstants.ENCODING_16BIT;
+ values[4] = 0;
+ values[5] = 0;
+ mUnicodeCounter++;
+ } else {
+ int udhLength = 0;
+ if (langIndex != 0 || langShiftIndex != 0) {
+ udhLength = UDH_SEPTET_COST_LENGTH;
+ if (langIndex == 0 || langShiftIndex == 0) {
+ udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE;
+ } else {
+ udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES;
+ }
+ }
+ int msgCount;
+ if (minNumSeptets > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) {
+ if (udhLength == 0) {
+ udhLength = UDH_SEPTET_COST_LENGTH;
+ }
+ udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE;
+ int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
+ msgCount = (minNumSeptets + septetsPerPart - 1) / septetsPerPart;
+ } else {
+ msgCount = 1;
+ }
+ values[0] = msgCount;
+ values[1] = minNumSeptets;
+ values[2] = (values[0] * (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) -
+ minNumSeptets;
+ values[3] = SmsConstants.ENCODING_7BIT;
+ values[4] = (langIndex == 2 ? 3 : langIndex); // Portuguese is code 3, index 2
+ values[5] = langShiftIndex;
+ assertEquals("minNumSeptetsWithHeader", minNumSeptetsWithHeader,
+ udhLength * msgCount + minNumSeptets);
+ mStatsCounters[langIndex * 4 + langShiftIndex]++;
+ }
+ }
+
+ void printStats() {
+ Log.d(TAG, "Unicode selection count: " + mUnicodeCounter);
+ for (int i = 0; i < 12; i++) {
+ Log.d(TAG, "Language pair index " + i + " count: " + mStatsCounters[i]);
+ }
+ }
+ }
+
+ @LargeTest
+ public void testCalcLengthMixed7bit() throws Exception {
+ StringBuilder sb = new StringBuilder(320);
+ CounterHelper ch = new CounterHelper();
+ Random r = new Random(0x4321); // use the same seed for reproducibility
+ int[] expectedValues = new int[6];
+ int[] origLockingShiftTables = GsmAlphabet.getEnabledLockingShiftTables();
+ int[] origSingleShiftTables = GsmAlphabet.getEnabledSingleShiftTables();
+ int enabledLanguagesTestCases = sEnabledSingleShiftTables.length;
+ long startTime = System.currentTimeMillis();
+
+ // Repeat for 10 test runs
+ for (int run = 0; run < 10; run++) {
+ sb.setLength(0);
+ ch.clear();
+ int unicodeOnlyCount = 0;
+
+ // Test incrementally from 1 to 320 character random messages
+ for (int i = 1; i < 320; i++) {
+ // 1% chance to add from each special character class, else add an ASCII char
+ int charClass = r.nextInt(100);
+ if (charClass >= sNumCharacterClasses) {
+ charClass = sNumCharacterClasses - 1; // last class is ASCII
+ }
+ int classLength = sCharacterClasses[charClass].length();
+ char nextChar = sCharacterClasses[charClass].charAt(r.nextInt(classLength));
+ sb.append(nextChar);
+ ch.addChar(charClass);
+
+// if (i % 20 == 0) {
+// Log.d(TAG, "test string: " + sb);
+// }
+
+ // Test string against all combinations of enabled languages
+ boolean unicodeOnly = true;
+ for (int j = 0; j < enabledLanguagesTestCases; j++) {
+ GsmAlphabet.setEnabledSingleShiftTables(sEnabledSingleShiftTables[j]);
+ GsmAlphabet.setEnabledLockingShiftTables(sEnabledLockingShiftTables[j]);
+ ch.fillData(j, false, expectedValues, i);
+ if (expectedValues[3] == SmsConstants.ENCODING_7BIT) {
+ unicodeOnly = false;
+ }
+ callGsmLengthMethods(sb, false, expectedValues);
+ // test 7 bit only mode
+ ch.fillData(j, true, expectedValues, i);
+ callGsmLengthMethods(sb, true, expectedValues);
+ }
+ // after 10 iterations with a Unicode-only string, skip to next test string
+ // so we can spend more time testing strings that do encode into 7 bits.
+ if (unicodeOnly && ++unicodeOnlyCount == 10) {
+// Log.d(TAG, "Unicode only: skipping to next test string");
+ break;
+ }
+ }
+ }
+ ch.printStats();
+ Log.d(TAG, "Completed in " + (System.currentTimeMillis() - startTime) + " ms");
+ GsmAlphabet.setEnabledLockingShiftTables(origLockingShiftTables);
+ GsmAlphabet.setEnabledSingleShiftTables(origSingleShiftTables);
+ }
+
+ private void callGsmLengthMethods(CharSequence msgBody, boolean use7bitOnly,
+ int[] expectedValues)
+ {
+ // deprecated GSM-specific method
+ int[] values = android.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ assertEquals("msgCount", expectedValues[0], values[0]);
+ assertEquals("codeUnitCount", expectedValues[1], values[1]);
+ assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
+ assertEquals("codeUnitSize", expectedValues[3], values[3]);
+
+ int activePhone = TelephonyManager.getDefault().getPhoneType();
+ if (TelephonyManager.PHONE_TYPE_GSM == activePhone) {
+ values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ assertEquals("msgCount", expectedValues[0], values[0]);
+ assertEquals("codeUnitCount", expectedValues[1], values[1]);
+ assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
+ assertEquals("codeUnitSize", expectedValues[3], values[3]);
+ }
+
+ GsmAlphabet.TextEncodingDetails ted =
+ com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ assertEquals("msgCount", expectedValues[0], ted.msgCount);
+ assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount);
+ assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
+ assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize);
+ assertEquals("languageTable", expectedValues[4], ted.languageTable);
+ assertEquals("languageShiftTable", expectedValues[5], ted.languageShiftTable);
+ }
+
+ private void callCdmaLengthMethods(CharSequence msgBody, boolean use7bitOnly,
+ int[] expectedValues)
+ {
+ int activePhone = TelephonyManager.getDefault().getPhoneType();
+ if (TelephonyManager.PHONE_TYPE_CDMA == activePhone) {
+ int[] values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ assertEquals("msgCount", expectedValues[0], values[0]);
+ assertEquals("codeUnitCount", expectedValues[1], values[1]);
+ assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
+ assertEquals("codeUnitSize", expectedValues[3], values[3]);
+ }
+
+ GsmAlphabet.TextEncodingDetails ted =
+ com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ assertEquals("msgCount", expectedValues[0], ted.msgCount);
+ assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount);
+ assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
+ assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize);
+
+ ted = com.android.internal.telephony.cdma.sms.BearerData.calcTextEncodingDetails(msgBody, use7bitOnly);
+ assertEquals("msgCount", expectedValues[0], ted.msgCount);
+ assertEquals("codeUnitCount", expectedValues[1], ted.codeUnitCount);
+ assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
+ assertEquals("codeUnitSize", expectedValues[3], ted.codeUnitSize);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java
new file mode 100644
index 0000000..3757017
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java
@@ -0,0 +1,219 @@
+/**
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.RetryManager;
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class TelephonyUtilsTest extends TestCase {
+
+ /**
+ * After first creating the RetryManager
+ * isRetryNeeded should be false and the time 0
+ */
+ @SmallTest
+ public void testRetryManagerEmpty() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertEquals(0, rm.getRetryCount());
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.setRetryCount(123);
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.retryForeverUsingLastTimeout();
+ assertTrue(rm.isRetryForever());
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.setRetryCount(2);
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+ }
+
+ /**
+ * A simple test and that randomization is doing something.
+ */
+ @SmallTest
+ public void testRetryManagerSimplest() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure(1, 500, 10));
+ int loops = 10;
+ int count = 0;
+ for (int i = 0; i < loops; i++) {
+ assertTrue(rm.isRetryNeeded());
+ int time = rm.getRetryTimer();
+ assertTrue((time >= 500) && (time < 600));
+ if (time == 500) {
+ count++;
+ }
+ }
+ assertFalse(count == loops);
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ rm.setRetryCount(0);
+ assertTrue(rm.isRetryNeeded());
+ }
+
+ /**
+ * Test multiple values using simple configuration.
+ */
+ @SmallTest
+ public void testRetryManagerSimple() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure(3, 1000, 0));
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ assertEquals(rm.getRetryTimer(), 1000);
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ }
+
+ /**
+ * Test string configuration, simplest
+ */
+ @SmallTest
+ public void testRetryManageSimpleString() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure("101"));
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(101, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ }
+
+ /**
+ * Test infinite retires
+ */
+ @SmallTest
+ public void testRetryManageInfinite() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure("1000,2000,3000,max_retries=infinite"));
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(2000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ // All others are 3000 and isRetryNeeded is always true
+ for (int i=0; i < 100; i++) {
+ assertEquals(3000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ }
+ }
+
+ /**
+ * Test string configuration using all options and with quotes.
+ */
+ @SmallTest
+ public void testRetryManageString() throws Exception {
+ RetryManager rm = new RetryManager();
+ int time;
+
+ assertTrue(rm.configure(
+ "\"max_retries=4, default_randomization=100,1000, 2000 :200 , 3000\""));
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 1000) && (time < 1100));
+
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 2000) && (time < 2200));
+
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 3000) && (time < 3100));
+
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 3000) && (time < 3100));
+
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ }
+
+ /**
+ * Test string configuration using all options.
+ */
+ @SmallTest
+ public void testRetryManageForever() throws Exception {
+ RetryManager rm = new RetryManager();
+ int time;
+
+ assertTrue(rm.configure("1000, 2000, 3000"));
+ assertTrue(rm.isRetryNeeded());
+ assertFalse(rm.isRetryForever());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(1000, rm.getRetryTimer());
+
+ rm.retryForeverUsingLastTimeout();
+ rm.increaseRetryCount();
+ rm.increaseRetryCount();
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertTrue(rm.isRetryForever());
+ assertEquals(3, rm.getRetryCount());
+ assertEquals(3000, rm.getRetryTimer());
+
+ rm.setRetryCount(1);
+ assertTrue(rm.isRetryNeeded());
+ assertFalse(rm.isRetryForever());
+ assertEquals(1, rm.getRetryCount());
+ assertEquals(2000, rm.getRetryTimer());
+
+ rm.retryForeverUsingLastTimeout();
+ assertTrue(rm.isRetryNeeded());
+ assertTrue(rm.isRetryForever());
+ rm.resetRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertFalse(rm.isRetryForever());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(1000, rm.getRetryTimer());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java b/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
new file mode 100644
index 0000000..b8f0568
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import android.telephony.CellInfo;
+
+/**
+ * Stub class used for unit tests
+ */
+
+public class TestPhoneNotifier implements PhoneNotifier {
+ public TestPhoneNotifier() {
+ }
+
+ public void notifyPhoneState(Phone sender) {
+ }
+
+ public void notifyServiceState(Phone sender) {
+ }
+
+ public void notifyCellLocation(Phone sender) {
+ }
+
+ public void notifySignalStrength(Phone sender) {
+ }
+
+ public void notifyMessageWaitingChanged(Phone sender) {
+ }
+
+ public void notifyCallForwardingChanged(Phone sender) {
+ }
+
+ public void notifyDataConnection(Phone sender, String reason, String apnType) {
+ }
+
+ public void notifyDataConnection(Phone sender, String reason, String apnType,
+ PhoneConstants.DataState state) {
+ }
+
+ public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) {
+ }
+
+ public void notifyDataActivity(Phone sender) {
+ }
+
+ public void notifyOtaspChanged(Phone sender, int otaspMode) {
+ }
+
+ public void notifyCellInfo(Phone sender, CellInfo cellInfo) {
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/Wap230WspContentTypeTest.java b/tests/telephonytests/src/com/android/internal/telephony/Wap230WspContentTypeTest.java
new file mode 100644
index 0000000..d31b294
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/Wap230WspContentTypeTest.java
@@ -0,0 +1,853 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.WspTypeDecoder;
+import com.android.internal.util.HexDump;
+
+import java.io.ByteArrayOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+public class Wap230WspContentTypeTest extends TestCase {
+
+ public static final Map<Integer, String> WELL_KNOWN_SHORT_MIME_TYPES
+ = new HashMap<Integer, String>();
+ public static final Map<Integer, String> WELL_KNOWN_LONG_MIME_TYPES
+ = new HashMap<Integer, String>();
+ public static final Map<Integer, String> WELL_KNOWN_PARAMETERS
+ = new HashMap<Integer, String>();
+
+ static {
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x00, "*/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x01, "text/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x02, "text/html");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x03, "text/plain");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x04, "text/x-hdml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x05, "text/x-ttml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x06, "text/x-vCalendar");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x07, "text/x-vCard");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x08, "text/vnd.wap.wml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x09, "text/vnd.wap.wmlscript");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x0A, "text/vnd.wap.wta-event");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x0B, "multipart/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x0C, "multipart/mixed");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x0D, "multipart/form-data");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x0E, "multipart/byterantes");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x0F, "multipart/alternative");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x10, "application/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x11, "application/java-vm");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x12, "application/x-www-form-urlencoded");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x13, "application/x-hdmlc");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x14, "application/vnd.wap.wmlc");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x15, "application/vnd.wap.wmlscriptc");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x16, "application/vnd.wap.wta-eventc");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x17, "application/vnd.wap.uaprof");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x18, "application/vnd.wap.wtls-ca-certificate");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x19, "application/vnd.wap.wtls-user-certificate");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x1A, "application/x-x509-ca-cert");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x1B, "application/x-x509-user-cert");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x1C, "image/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x1D, "image/gif");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x1E, "image/jpeg");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x1F, "image/tiff");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x20, "image/png");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x21, "image/vnd.wap.wbmp");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x22, "application/vnd.wap.multipart.*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x23, "application/vnd.wap.multipart.mixed");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x24, "application/vnd.wap.multipart.form-data");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x25, "application/vnd.wap.multipart.byteranges");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x26, "application/vnd.wap.multipart.alternative");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x27, "application/xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x28, "text/xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x29, "application/vnd.wap.wbxml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x2A, "application/x-x968-cross-cert");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x2B, "application/x-x968-ca-cert");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x2C, "application/x-x968-user-cert");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x2D, "text/vnd.wap.si");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x2E, "application/vnd.wap.sic");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x2F, "text/vnd.wap.sl");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x30, "application/vnd.wap.slc");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x31, "text/vnd.wap.co");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x32, "application/vnd.wap.coc");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x33, "application/vnd.wap.multipart.related");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x34, "application/vnd.wap.sia");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x35, "text/vnd.wap.connectivity-xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x36, "application/vnd.wap.connectivity-wbxml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x37, "application/pkcs7-mime");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x38, "application/vnd.wap.hashed-certificate");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x39, "application/vnd.wap.signed-certificate");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x3A, "application/vnd.wap.cert-response");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x3B, "application/xhtml+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x3C, "application/wml+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x3D, "text/css");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x3E, "application/vnd.wap.mms-message");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x3F, "application/vnd.wap.rollover-certificate");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x40, "application/vnd.wap.locc+wbxml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x41, "application/vnd.wap.loc+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x42, "application/vnd.syncml.dm+wbxml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x43, "application/vnd.syncml.dm+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x44, "application/vnd.syncml.notification");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x45, "application/vnd.wap.xhtml+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x46, "application/vnd.wv.csp.cir");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x47, "application/vnd.oma.dd+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x48, "application/vnd.oma.drm.message");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x49, "application/vnd.oma.drm.content");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x4A, "application/vnd.oma.drm.rights+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x4B, "application/vnd.oma.drm.rights+wbxml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x4C, "application/vnd.wv.csp+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x4D, "application/vnd.wv.csp+wbxml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x4E, "application/vnd.syncml.ds.notification");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x4F, "audio/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x50, "video/*");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x51, "application/vnd.oma.dd2+xml");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x52, "application/mikey");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x53, "application/vnd.oma.dcd");
+ WELL_KNOWN_SHORT_MIME_TYPES.put(0x54, "application/vnd.oma.dcdc");
+
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0201, "application/vnd.uplanet.cacheop-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0202, "application/vnd.uplanet.signal");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0203, "application/vnd.uplanet.alert-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0204, "application/vnd.uplanet.list-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0205, "application/vnd.uplanet.listcmd-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0206, "application/vnd.uplanet.channel-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0207, "application/vnd.uplanet.provisioning-status-uri");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0208, "x-wap.multipart/vnd.uplanet.header-set");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0209, "application/vnd.uplanet.bearer-choice-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x020A, "application/vnd.phonecom.mmc-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x020B, "application/vnd.nokia.syncset+wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x020C, "image/x-up-wpng");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0300, "application/iota.mmc-wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0301, "application/iota.mmc-xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0302, "application/vnd.syncml+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0303, "application/vnd.syncml+wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0304, "text/vnd.wap.emn+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0305, "text/calendar");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0306, "application/vnd.omads-email+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0307, "application/vnd.omads-file+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0308, "application/vnd.omads-folder+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0309, "text/directory;profile=vCard");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x030A, "application/vnd.wap.emn+wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x030B, "application/vnd.nokia.ipdc-purchase-response");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x030C, "application/vnd.motorola.screen3+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x030D, "application/vnd.motorola.screen3+gzip");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x030E, "application/vnd.cmcc.setting+wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x030F, "application/vnd.cmcc.bombing+wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0310, "application/vnd.docomo.pf");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0311, "application/vnd.docomo.ub");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0312, "application/vnd.omaloc-supl-init");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0313, "application/vnd.oma.group-usage-list+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0314, "application/oma-directory+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0315, "application/vnd.docomo.pf2");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0316, "application/vnd.oma.drm.roap-trigger+wbxml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0317, "application/vnd.sbm.mid2");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0318, "application/vnd.wmf.bootstrap");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x0319, "application/vnc.cmcc.dcd+xml");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x031A, "application/vnd.sbm.cid");
+ WELL_KNOWN_LONG_MIME_TYPES.put(0x031B, "application/vnd.oma.bcast.provisioningtrigger");
+
+ WELL_KNOWN_PARAMETERS.put(0x00, "Q");
+ WELL_KNOWN_PARAMETERS.put(0x01, "Charset");
+ WELL_KNOWN_PARAMETERS.put(0x02, "Level");
+ WELL_KNOWN_PARAMETERS.put(0x03, "Type");
+ WELL_KNOWN_PARAMETERS.put(0x07, "Differences");
+ WELL_KNOWN_PARAMETERS.put(0x08, "Padding");
+ WELL_KNOWN_PARAMETERS.put(0x09, "Type");
+ WELL_KNOWN_PARAMETERS.put(0x0E, "Max-Age");
+ WELL_KNOWN_PARAMETERS.put(0x10, "Secure");
+ WELL_KNOWN_PARAMETERS.put(0x11, "SEC");
+ WELL_KNOWN_PARAMETERS.put(0x12, "MAC");
+ WELL_KNOWN_PARAMETERS.put(0x13, "Creation-date");
+ WELL_KNOWN_PARAMETERS.put(0x14, "Modification-date");
+ WELL_KNOWN_PARAMETERS.put(0x15, "Read-date");
+ WELL_KNOWN_PARAMETERS.put(0x16, "Size");
+ WELL_KNOWN_PARAMETERS.put(0x17, "Name");
+ WELL_KNOWN_PARAMETERS.put(0x18, "Filename");
+ WELL_KNOWN_PARAMETERS.put(0x19, "Start");
+ WELL_KNOWN_PARAMETERS.put(0x1A, "Start-info");
+ WELL_KNOWN_PARAMETERS.put(0x1B, "Comment");
+ WELL_KNOWN_PARAMETERS.put(0x1C, "Domain");
+ WELL_KNOWN_PARAMETERS.put(0x1D, "Path");
+
+ }
+
+ final int WSP_DEFINED_SHORT_MIME_TYPE_COUNT = 85;
+ final int WSP_DEFINED_LONG_MIME_TYPE_COUNT = 85;
+
+ private static final byte WSP_STRING_TERMINATOR = 0x00;
+ private static final byte WSP_SHORT_INTEGER_MASK = (byte) 0x80;
+ private static final byte WSP_LENGTH_QUOTE = 0x1F;
+ private static final byte WSP_QUOTE = 0x22;
+
+ private static final short LONG_MIME_TYPE_OMA_DIRECTORY_XML = 0x0314;
+ private static final short LONG_MIME_TYPE_UNASSIGNED = 0x052C;
+
+ private static final byte SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE = 0x3F;
+ private static final byte SHORT_MIME_TYPE_UNASSIGNED = 0x60;
+
+ private static final String STRING_MIME_TYPE_ROLLOVER_CERTIFICATE
+ = "application/vnd.wap.rollover-certificate";
+
+ private static final byte TYPED_PARAM_Q = 0x00;
+ private static final byte TYPED_PARAM_DOMAIN = 0x1C;
+ private static final byte PARAM_UNASSIGNED = 0x42;
+ private static final byte PARAM_NO_VALUE = 0x00;
+ private static final byte TYPED_PARAM_SEC = 0x11;
+ private static final byte TYPED_PARAM_MAC = 0x12;
+
+ public void testHasExpectedNumberOfShortMimeTypes() {
+ assertEquals(WSP_DEFINED_SHORT_MIME_TYPE_COUNT, WELL_KNOWN_SHORT_MIME_TYPES.size());
+ }
+
+ public void testHasExpectedNumberOfLongMimeTypes() {
+ assertEquals(WSP_DEFINED_LONG_MIME_TYPE_COUNT, WELL_KNOWN_LONG_MIME_TYPES.size());
+ }
+
+ public void testWellKnownShortIntegerMimeTypeValues() {
+
+ for (int value : Wap230WspContentTypeTest.WELL_KNOWN_SHORT_MIME_TYPES.keySet()) {
+ WspTypeDecoder unit = new WspTypeDecoder(
+ HexDump.toByteArray((byte) (value | WSP_SHORT_INTEGER_MASK)));
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+ int wellKnownValue = (int) unit.getValue32();
+ assertEquals(Wap230WspContentTypeTest.WELL_KNOWN_SHORT_MIME_TYPES.get(value), mimeType);
+ assertEquals(value, wellKnownValue);
+ assertEquals(1, unit.getDecodedDataLength());
+ }
+ }
+
+ public void testWellKnownLongIntegerMimeTypeValues() {
+ byte headerLength = 3;
+ byte typeLength = 2;
+ for (int value : Wap230WspContentTypeTest.WELL_KNOWN_SHORT_MIME_TYPES.keySet()) {
+ byte[] data = new byte[10];
+ data[0] = headerLength;
+ data[1] = typeLength;
+ data[2] = (byte) (value >> 8);
+ data[3] = (byte) (value & 0xFF);
+ WspTypeDecoder unit = new WspTypeDecoder(data);
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+ int wellKnownValue = (int) unit.getValue32();
+ assertEquals(Wap230WspContentTypeTest.WELL_KNOWN_SHORT_MIME_TYPES.get(value), mimeType);
+ assertEquals(value, wellKnownValue);
+ assertEquals(4, unit.getDecodedDataLength());
+ }
+ }
+
+ public void testDecodeReturnsFalse_WhenOnlyAZeroBytePresent() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x00);
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertFalse(unit.decodeContentType(0));
+ }
+
+ public void testConstrainedMediaExtensionMedia() throws Exception {
+
+ String testType = "application/wibble";
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(testType.getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+ assertEquals(testType, mimeType);
+ assertEquals(-1, unit.getValue32());
+ assertEquals(19, unit.getDecodedDataLength());
+ }
+
+ public void testGeneralFormShortLengthExtensionMedia() throws Exception {
+
+ String testType = "12345678901234567890123456789";
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(testType.length() + 1);
+ out.write(testType.getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+ assertEquals(testType, mimeType);
+ assertEquals(-1, unit.getValue32());
+ assertEquals(31, unit.getDecodedDataLength());
+ }
+
+ public void testGeneralFormShortLengthWellKnownShortInteger() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x01);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(2, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormShortLengthWellKnownShortIntegerWithUnknownValue() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x01);
+ out.write(SHORT_MIME_TYPE_UNASSIGNED | WSP_SHORT_INTEGER_MASK);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+ assertNull(mimeType);
+ assertEquals(SHORT_MIME_TYPE_UNASSIGNED, unit.getValue32());
+ assertEquals(2, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormShortLengthWellKnownLongInteger() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(0x03); // header length
+ out.write(0x02); // type length (2 octets)
+ out.write(LONG_MIME_TYPE_OMA_DIRECTORY_XML >> 8);
+ out.write(LONG_MIME_TYPE_OMA_DIRECTORY_XML & 0xFF);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals("application/oma-directory+xml", mimeType);
+ assertEquals(LONG_MIME_TYPE_OMA_DIRECTORY_XML, unit.getValue32());
+ assertEquals(4, unit.getDecodedDataLength());
+ }
+
+ public void testGeneralFormShortLengthWellKnownLongIntegerWithUnknownValue() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(0x03); // Value-length, short-length
+ out.write(0x02); // long-integer length (2 octets)
+ out.write(LONG_MIME_TYPE_UNASSIGNED >> 8);
+ out.write(LONG_MIME_TYPE_UNASSIGNED & 0xFF);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertNull(mimeType);
+ assertEquals(LONG_MIME_TYPE_UNASSIGNED, unit.getValue32());
+ assertEquals(4, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormLengthQuoteWellKnownShortInteger() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(WSP_LENGTH_QUOTE);
+ out.write(0x01); // Length as UINTVAR
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(3, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormLengthQuoteWellKnownShortIntegerWithUnknownValue() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(WSP_LENGTH_QUOTE);
+ out.write(0x01); // Length as UINTVAR
+ out.write(SHORT_MIME_TYPE_UNASSIGNED | WSP_SHORT_INTEGER_MASK);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+ assertNull(mimeType);
+ assertEquals(SHORT_MIME_TYPE_UNASSIGNED, unit.getValue32());
+ assertEquals(3, unit.getDecodedDataLength());
+ }
+
+ public void testGeneralFormLengthQuoteWellKnownLongInteger() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(WSP_LENGTH_QUOTE);
+ out.write(0x03); // Length as UINTVAR
+ out.write(0x02); // long-integer length (2 octets)
+ out.write(LONG_MIME_TYPE_OMA_DIRECTORY_XML >> 8);
+ out.write(LONG_MIME_TYPE_OMA_DIRECTORY_XML & 0xFF);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals("application/oma-directory+xml", mimeType);
+ assertEquals(LONG_MIME_TYPE_OMA_DIRECTORY_XML, unit.getValue32());
+ assertEquals(5, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormLengthQuoteWellKnownLongIntegerWithUnknownValue() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(WSP_LENGTH_QUOTE);
+ out.write(0x03); // Length as UINTVAR
+ out.write(0x02); // long-integer length (2 octets)
+ out.write(LONG_MIME_TYPE_UNASSIGNED >> 8);
+ out.write(LONG_MIME_TYPE_UNASSIGNED & 0xFF);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertNull(mimeType);
+ assertEquals(LONG_MIME_TYPE_UNASSIGNED, unit.getValue32());
+ assertEquals(5, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormLengthQuoteExtensionMedia() throws Exception {
+
+ String testType = "application/wibble";
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(WSP_LENGTH_QUOTE);
+ out.write(testType.length() + 1); // Length as UINTVAR
+
+ out.write(testType.getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(testType, mimeType);
+ assertEquals(-1, unit.getValue32());
+ assertEquals(21, unit.getDecodedDataLength());
+
+ }
+
+ public void testGeneralFormLengthQuoteExtensionMediaWithNiceLongMimeType() throws Exception {
+
+ String testType =
+ "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
+ +"01234567890123456789012345678901234567890123456789012345678901234567890123456789";
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ out.write(WSP_LENGTH_QUOTE);
+ out.write(0x81); // Length as UINTVAR (161 decimal, 0xA1), 2 bytes
+ out.write(0x21);
+
+ out.write(testType.getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(testType, mimeType);
+ assertEquals(-1, unit.getValue32());
+ assertEquals(164, unit.getDecodedDataLength());
+
+ }
+
+ public void testConstrainedMediaExtensionMediaWithSpace() throws Exception {
+
+ String testType = " application/wibble";
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(testType.getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(testType, mimeType);
+ assertEquals(-1, unit.getValue32());
+ assertEquals(20, unit.getDecodedDataLength());
+
+ }
+
+ public void testTypedParamWellKnownShortIntegerNoValue() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x03); // Value-length, short-length
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_DOMAIN | WSP_SHORT_INTEGER_MASK);
+ out.write(PARAM_NO_VALUE);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+
+ assertEquals(4, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals(null, params.get("Domain"));
+
+ }
+
+ public void testTypedParamWellKnownShortIntegerTokenText() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x14); // Value-length, short-length
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_DOMAIN | WSP_SHORT_INTEGER_MASK);
+ out.write("wdstechnology.com".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+
+ assertEquals(out.toByteArray().length, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("wdstechnology.com", params.get("Domain"));
+
+ }
+
+ public void testTypedParamWellKnownLongIntegerTokenText() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x15);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(0x01);
+ out.write(TYPED_PARAM_DOMAIN);
+ out.write("wdstechnology.com".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+
+ assertEquals(22, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("wdstechnology.com", params.get("Domain"));
+
+ }
+
+ public void testTypedParamWellKnownShortIntegerQuotedText() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x15);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_DOMAIN | WSP_SHORT_INTEGER_MASK);
+ out.write(WSP_QUOTE);
+ out.write("wdstechnology.com".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(0x3F, unit.getValue32());
+ assertEquals(22, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("wdstechnology.com", params.get("Domain"));
+
+ }
+
+ public void testTypedParamWellKnownShortIntegerCompactIntegerValue() {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x3);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_SEC | WSP_SHORT_INTEGER_MASK);
+ out.write(0x01 | WSP_SHORT_INTEGER_MASK);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(0x3F, unit.getValue32());
+ assertEquals(4, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("1", params.get("SEC"));
+
+ }
+
+ public void testTypedParamWellKnownShortIntegerMultipleParameters() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x0B);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_SEC | WSP_SHORT_INTEGER_MASK);
+ out.write(0x01 | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_MAC | WSP_SHORT_INTEGER_MASK);
+ out.write(WSP_QUOTE);
+ out.write("imapc".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(12, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("1", params.get("SEC"));
+ assertEquals("imapc", params.get("MAC"));
+ }
+
+ public void testUntypedParamIntegerValueShortInteger() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x0A);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write("MYPARAM".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR); // EOS
+ out.write(0x45 | WSP_SHORT_INTEGER_MASK);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(11, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("69", params.get("MYPARAM"));
+ }
+
+ public void testUntypedParamIntegerValueLongInteger() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x0C);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write("MYPARAM".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+ out.write(0x02); // Short Length
+ out.write(0x42); // Long Integer byte 1
+ out.write(0x69); // Long Integer byte 2
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(0x3F, unit.getValue32());
+ assertEquals(13, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("17001", params.get("MYPARAM"));
+ }
+
+ public void testUntypedParamTextNoValue() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x0A);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write("MYPARAM".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+ out.write(PARAM_NO_VALUE);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(11, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals(null, params.get("MYPARAM"));
+
+ }
+
+ public void testUntypedParamTextTokenText() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x11);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write("MYPARAM".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+ out.write("myvalue".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(18, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("myvalue", params.get("MYPARAM"));
+ }
+
+ public void testUntypedParamTextQuotedString() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x11);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write("MYPARAM".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+ out.write(WSP_QUOTE);
+ out.write("myvalue".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+ assertEquals(19, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("myvalue", params.get("MYPARAM"));
+
+ }
+
+ public void testDecodesReturnsFalse_ForParamWithMissingValue() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x09);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write("MYPARAM".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertFalse(unit.decodeContentType(0));
+ }
+
+ public void testTypedParamTextQValue() {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x04);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(TYPED_PARAM_Q);
+ out.write(0x83); // Q value byte 1
+ out.write(0x31); // Q value byte 2
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(0x3F, unit.getValue32());
+ assertEquals(5, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("433", params.get("Q"));
+
+ }
+
+ public void testTypedParamUnassignedWellKnownShortIntegerTokenText() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x14);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(PARAM_UNASSIGNED | WSP_SHORT_INTEGER_MASK);
+ out.write("wdstechnology.com".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+
+ assertEquals(21, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("wdstechnology.com", params.get("unassigned/0x42"));
+
+ }
+
+ public void testTypedParamUnassignedWellKnownLongIntegerTokenText() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x15);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(0x01); // Short-length of well-known parameter token
+ out.write(PARAM_UNASSIGNED);
+ out.write("wdstechnology.com".getBytes("US-ASCII"));
+ out.write(WSP_STRING_TERMINATOR);
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertTrue(unit.decodeContentType(0));
+
+ String mimeType = unit.getValueString();
+
+ assertEquals(STRING_MIME_TYPE_ROLLOVER_CERTIFICATE, mimeType);
+ assertEquals(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE, unit.getValue32());
+
+ assertEquals(22, unit.getDecodedDataLength());
+
+ Map<String, String> params = unit.getContentParameters();
+ assertEquals("wdstechnology.com", params.get("unassigned/0x42"));
+ }
+
+ public void testDecodesReturnsFalse_WhenParamValueNotTerminated() throws Exception {
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x15);
+ out.write(SHORT_MIME_TYPE_ROLLOVER_CERTIFICATE | WSP_SHORT_INTEGER_MASK);
+ out.write(0x01);
+ out.write(PARAM_UNASSIGNED);
+ out.write("wdstechnology.com".getBytes("US-ASCII"));
+
+ WspTypeDecoder unit = new WspTypeDecoder(out.toByteArray());
+ assertFalse(unit.decodeContentType(0));
+ }
+} \ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
new file mode 100644
index 0000000..d2faceb
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
@@ -0,0 +1,746 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.Parcel;
+import android.telephony.SmsCbCmasInfo;
+import android.telephony.SmsCbMessage;
+import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.util.BitwiseOutputStream;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Test cases for basic SmsCbMessage operation for CDMA.
+ */
+public class CdmaSmsCbTest extends AndroidTestCase {
+
+ /* Copy of private subparameter identifier constants from BearerData class. */
+ private static final byte SUBPARAM_MESSAGE_IDENTIFIER = (byte) 0x00;
+ private static final byte SUBPARAM_USER_DATA = (byte) 0x01;
+ private static final byte SUBPARAM_PRIORITY_INDICATOR = (byte) 0x08;
+ private static final byte SUBPARAM_LANGUAGE_INDICATOR = (byte) 0x0D;
+ private static final byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA = 0x12;
+
+ /**
+ * Initialize a Parcel for an incoming CDMA cell broadcast. The caller will write the
+ * bearer data and then convert it to an SmsMessage.
+ * @param serviceCategory the CDMA service category
+ * @return the initialized Parcel
+ */
+ private static Parcel createBroadcastParcel(int serviceCategory) {
+ Parcel p = Parcel.obtain();
+
+ p.writeInt(SmsEnvelope.TELESERVICE_NOT_SET);
+ p.writeByte((byte) 1); // non-zero for MESSAGE_TYPE_BROADCAST
+ p.writeInt(serviceCategory);
+
+ // dummy address (RIL may generate a different dummy address for broadcasts)
+ p.writeInt(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF); // sAddress.digit_mode
+ p.writeInt(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK); // sAddress.number_mode
+ p.writeInt(CdmaSmsAddress.TON_UNKNOWN); // sAddress.number_type
+ p.writeInt(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY); // sAddress.number_plan
+ p.writeByte((byte) 0); // sAddress.number_of_digits
+ p.writeInt((byte) 0); // sSubAddress.subaddressType
+ p.writeByte((byte) 0); // sSubAddress.odd
+ p.writeByte((byte) 0); // sSubAddress.number_of_digits
+ return p;
+ }
+
+ /**
+ * Initialize a BitwiseOutputStream with the CDMA bearer data subparameters except for
+ * user data. The caller will append the user data and add it to the parcel.
+ * @param messageId the 16-bit message identifier
+ * @param priority message priority
+ * @param language message language code
+ * @return the initialized BitwiseOutputStream
+ */
+ private static BitwiseOutputStream createBearerDataStream(int messageId, int priority,
+ int language) throws BitwiseOutputStream.AccessException {
+ BitwiseOutputStream bos = new BitwiseOutputStream(10);
+ bos.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
+ bos.write(8, 3); // length: 3 bytes
+ bos.write(4, BearerData.MESSAGE_TYPE_DELIVER);
+ bos.write(8, ((messageId >>> 8) & 0xff));
+ bos.write(8, (messageId & 0xff));
+ bos.write(1, 0); // no User Data Header
+ bos.write(3, 0); // reserved
+
+ if (priority != -1) {
+ bos.write(8, SUBPARAM_PRIORITY_INDICATOR);
+ bos.write(8, 1); // length: 1 byte
+ bos.write(2, (priority & 0x03));
+ bos.write(6, 0); // reserved
+ }
+
+ if (language != -1) {
+ bos.write(8, SUBPARAM_LANGUAGE_INDICATOR);
+ bos.write(8, 1); // length: 1 byte
+ bos.write(8, (language & 0xff));
+ }
+
+ return bos;
+ }
+
+ /**
+ * Write the bearer data array to the parcel, then return a new SmsMessage from the parcel.
+ * @param p the parcel containing the CDMA SMS headers
+ * @param bearerData the bearer data byte array to append to the parcel
+ * @return the new SmsMessage created from the parcel
+ */
+ private static SmsMessage createMessageFromParcel(Parcel p, byte[] bearerData) {
+ p.writeInt(bearerData.length);
+ for (byte b : bearerData) {
+ p.writeByte(b);
+ }
+ p.setDataPosition(0); // reset position for reading
+ SmsMessage message = SmsMessage.newFromParcel(p);
+ p.recycle();
+ return message;
+ }
+
+ /**
+ * Create a parcel for an incoming CMAS broadcast, then return a new SmsMessage created
+ * from the parcel.
+ * @param serviceCategory the CDMA service category
+ * @param messageId the 16-bit message identifier
+ * @param priority message priority
+ * @param language message language code
+ * @param body message body
+ * @param cmasCategory CMAS category (or -1 to skip adding CMAS type 1 elements record)
+ * @param responseType CMAS response type
+ * @param severity CMAS severity
+ * @param urgency CMAS urgency
+ * @param certainty CMAS certainty
+ * @return the newly created SmsMessage object
+ */
+ private static SmsMessage createCmasSmsMessage(int serviceCategory, int messageId, int priority,
+ int language, int encoding, String body, int cmasCategory, int responseType,
+ int severity, int urgency, int certainty) throws Exception {
+ BitwiseOutputStream cmasBos = new BitwiseOutputStream(10);
+ cmasBos.write(8, 0); // CMAE protocol version 0
+
+ if (body != null) {
+ cmasBos.write(8, 0); // Type 0 elements (alert text)
+ encodeBody(encoding, body, true, cmasBos);
+ }
+
+ if (cmasCategory != SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN) {
+ cmasBos.write(8, 1); // Type 1 elements
+ cmasBos.write(8, 4); // length: 4 bytes
+ cmasBos.write(8, (cmasCategory & 0xff));
+ cmasBos.write(8, (responseType & 0xff));
+ cmasBos.write(4, (severity & 0x0f));
+ cmasBos.write(4, (urgency & 0x0f));
+ cmasBos.write(4, (certainty & 0x0f));
+ cmasBos.write(4, 0); // pad to octet boundary
+ }
+
+ byte[] cmasUserData = cmasBos.toByteArray();
+
+ Parcel p = createBroadcastParcel(serviceCategory);
+ BitwiseOutputStream bos = createBearerDataStream(messageId, priority, language);
+
+ bos.write(8, SUBPARAM_USER_DATA);
+ bos.write(8, cmasUserData.length + 2); // add 2 bytes for msg_encoding and num_fields
+ bos.write(5, UserData.ENCODING_OCTET);
+ bos.write(8, cmasUserData.length);
+ bos.writeByteArray(cmasUserData.length * 8, cmasUserData);
+ bos.write(3, 0); // pad to byte boundary
+
+ return createMessageFromParcel(p, bos.toByteArray());
+ }
+
+ /**
+ * Create a parcel for an incoming CDMA cell broadcast, then return a new SmsMessage created
+ * from the parcel.
+ * @param serviceCategory the CDMA service category
+ * @param messageId the 16-bit message identifier
+ * @param priority message priority
+ * @param language message language code
+ * @param encoding user data encoding method
+ * @param body the message body
+ * @return the newly created SmsMessage object
+ */
+ private static SmsMessage createBroadcastSmsMessage(int serviceCategory, int messageId,
+ int priority, int language, int encoding, String body) throws Exception {
+ Parcel p = createBroadcastParcel(serviceCategory);
+ BitwiseOutputStream bos = createBearerDataStream(messageId, priority, language);
+
+ bos.write(8, SUBPARAM_USER_DATA);
+ encodeBody(encoding, body, false, bos);
+
+ return createMessageFromParcel(p, bos.toByteArray());
+ }
+
+ /**
+ * Append the message length, encoding, and body to the BearerData output stream.
+ * This is used for writing the User Data subparameter for non-CMAS broadcasts and for
+ * writing the alert text for CMAS broadcasts.
+ * @param encoding one of the CDMA UserData encoding values
+ * @param body the message body
+ * @param isCmasRecord true if this is a CMAS type 0 elements record; false for user data
+ * @param bos the BitwiseOutputStream to write to
+ * @throws Exception on any encoding error
+ */
+ private static void encodeBody(int encoding, String body, boolean isCmasRecord,
+ BitwiseOutputStream bos) throws Exception {
+ if (encoding == UserData.ENCODING_7BIT_ASCII || encoding == UserData.ENCODING_IA5) {
+ int charCount = body.length();
+ int recordBits = (charCount * 7) + 5; // add 5 bits for char set field
+ int recordOctets = (recordBits + 7) / 8; // round up to octet boundary
+ int padBits = (recordOctets * 8) - recordBits;
+
+ if (!isCmasRecord) {
+ recordOctets++; // add 8 bits for num_fields
+ }
+
+ bos.write(8, recordOctets);
+ bos.write(5, (encoding & 0x1f));
+
+ if (!isCmasRecord) {
+ bos.write(8, charCount);
+ }
+
+ for (int i = 0; i < charCount; i++) {
+ bos.write(7, body.charAt(i));
+ }
+
+ bos.write(padBits, 0); // pad to octet boundary
+ } else if (encoding == UserData.ENCODING_GSM_7BIT_ALPHABET
+ || encoding == UserData.ENCODING_GSM_DCS) {
+ // convert to 7-bit packed encoding with septet count in index 0 of byte array
+ byte[] encodedBody = GsmAlphabet.stringToGsm7BitPacked(body);
+
+ int charCount = encodedBody[0]; // septet count
+ int recordBits = (charCount * 7) + 5; // add 5 bits for char set field
+ int recordOctets = (recordBits + 7) / 8; // round up to octet boundary
+ int padBits = (recordOctets * 8) - recordBits;
+
+ if (!isCmasRecord) {
+ recordOctets++; // add 8 bits for num_fields
+ if (encoding == UserData.ENCODING_GSM_DCS) {
+ recordOctets++; // add 8 bits for DCS (message type)
+ }
+ }
+
+ bos.write(8, recordOctets);
+ bos.write(5, (encoding & 0x1f));
+
+ if (!isCmasRecord && encoding == UserData.ENCODING_GSM_DCS) {
+ bos.write(8, 0); // GSM DCS: 7 bit default alphabet, no msg class
+ }
+
+ if (!isCmasRecord) {
+ bos.write(8, charCount);
+ }
+ byte[] bodySeptets = Arrays.copyOfRange(encodedBody, 1, encodedBody.length);
+ bos.writeByteArray(charCount * 7, bodySeptets);
+ bos.write(padBits, 0); // pad to octet boundary
+ } else if (encoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) {
+ // 6 bit packed encoding with 0x20 offset (ASCII 0x20 - 0x60)
+ int charCount = body.length();
+ int recordBits = (charCount * 6) + 21; // add 21 bits for header fields
+ int recordOctets = (recordBits + 7) / 8; // round up to octet boundary
+ int padBits = (recordOctets * 8) - recordBits;
+
+ bos.write(8, recordOctets);
+
+ bos.write(5, (encoding & 0x1f));
+ bos.write(8, UserData.IS91_MSG_TYPE_SHORT_MESSAGE);
+ bos.write(8, charCount);
+
+ for (int i = 0; i < charCount; i++) {
+ bos.write(6, ((int) body.charAt(i) - 0x20));
+ }
+
+ bos.write(padBits, 0); // pad to octet boundary
+ } else {
+ byte[] encodedBody;
+ switch (encoding) {
+ case UserData.ENCODING_UNICODE_16:
+ encodedBody = body.getBytes("UTF-16BE");
+ break;
+
+ case UserData.ENCODING_SHIFT_JIS:
+ encodedBody = body.getBytes("Shift_JIS");
+ break;
+
+ case UserData.ENCODING_KOREAN:
+ encodedBody = body.getBytes("KSC5601");
+ break;
+
+ case UserData.ENCODING_LATIN_HEBREW:
+ encodedBody = body.getBytes("ISO-8859-8");
+ break;
+
+ case UserData.ENCODING_LATIN:
+ default:
+ encodedBody = body.getBytes("ISO-8859-1");
+ break;
+ }
+ int charCount = body.length(); // use actual char count for num fields
+ int recordOctets = encodedBody.length + 1; // add 1 byte for encoding and pad bits
+ if (!isCmasRecord) {
+ recordOctets++; // add 8 bits for num_fields
+ }
+ bos.write(8, recordOctets);
+ bos.write(5, (encoding & 0x1f));
+ if (!isCmasRecord) {
+ bos.write(8, charCount);
+ }
+ bos.writeByteArray(encodedBody.length * 8, encodedBody);
+ bos.write(3, 0); // pad to octet boundary
+ }
+ }
+
+ private static final String TEST_TEXT = "This is a test CDMA cell broadcast message..."
+ + "678901234567890123456789012345678901234567890";
+
+ private static final String PRES_ALERT =
+ "THE PRESIDENT HAS ISSUED AN EMERGENCY ALERT. CHECK LOCAL MEDIA FOR MORE DETAILS";
+
+ private static final String EXTREME_ALERT = "FLASH FLOOD WARNING FOR SOUTH COCONINO COUNTY"
+ + " - NORTH CENTRAL ARIZONA UNTIL 415 PM MST";
+
+ private static final String SEVERE_ALERT = "SEVERE WEATHER WARNING FOR SOMERSET COUNTY"
+ + " - NEW JERSEY UNTIL 415 PM MST";
+
+ private static final String AMBER_ALERT =
+ "AMBER ALERT:Mountain View,CA VEH'07 Blue Honda Civic CA LIC 5ABC123";
+
+ private static final String MONTHLY_TEST_ALERT = "This is a test of the emergency alert system."
+ + " This is only a test. 89012345678901234567890";
+
+ private static final String IS91_TEXT = "IS91 SHORT MSG"; // max length 14 chars
+
+ /**
+ * Verify that the SmsCbMessage has the correct values for CDMA.
+ * @param cbMessage the message to test
+ */
+ private static void verifyCbValues(SmsCbMessage cbMessage) {
+ assertEquals(SmsCbMessage.MESSAGE_FORMAT_3GPP2, cbMessage.getMessageFormat());
+ assertEquals(SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, cbMessage.getGeographicalScope());
+ assertEquals(false, cbMessage.isEtwsMessage()); // ETWS on CDMA not currently supported
+ }
+
+ private static void doTestNonEmergencyBroadcast(int encoding) throws Exception {
+ SmsMessage msg = createBroadcastSmsMessage(123, 456, BearerData.PRIORITY_NORMAL,
+ BearerData.LANGUAGE_ENGLISH, encoding, TEST_TEXT);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ verifyCbValues(cbMessage);
+ assertEquals(123, cbMessage.getServiceCategory());
+ assertEquals(456, cbMessage.getSerialNumber());
+ assertEquals(SmsCbMessage.MESSAGE_PRIORITY_NORMAL, cbMessage.getMessagePriority());
+ assertEquals("en", cbMessage.getLanguageCode());
+ assertEquals(TEST_TEXT, cbMessage.getMessageBody());
+ assertEquals(false, cbMessage.isEmergencyMessage());
+ assertEquals(false, cbMessage.isCmasMessage());
+ }
+
+ public void testNonEmergencyBroadcast7bitAscii() throws Exception {
+ doTestNonEmergencyBroadcast(UserData.ENCODING_7BIT_ASCII);
+ }
+
+ public void testNonEmergencyBroadcast7bitGsm() throws Exception {
+ doTestNonEmergencyBroadcast(UserData.ENCODING_GSM_7BIT_ALPHABET);
+ }
+
+ public void testNonEmergencyBroadcast16bitUnicode() throws Exception {
+ doTestNonEmergencyBroadcast(UserData.ENCODING_UNICODE_16);
+ }
+
+ public void testNonEmergencyBroadcastIs91Extended() throws Exception {
+ // IS-91 doesn't support language or priority subparameters, max 14 chars text
+ SmsMessage msg = createBroadcastSmsMessage(987, 654, -1, -1,
+ UserData.ENCODING_IS91_EXTENDED_PROTOCOL, IS91_TEXT);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ verifyCbValues(cbMessage);
+ assertEquals(987, cbMessage.getServiceCategory());
+ assertEquals(654, cbMessage.getSerialNumber());
+ assertEquals(SmsCbMessage.MESSAGE_PRIORITY_NORMAL, cbMessage.getMessagePriority());
+ assertEquals(null, cbMessage.getLanguageCode());
+ assertEquals(IS91_TEXT, cbMessage.getMessageBody());
+ assertEquals(false, cbMessage.isEmergencyMessage());
+ assertEquals(false, cbMessage.isCmasMessage());
+ }
+
+ private static void doTestCmasBroadcast(int serviceCategory, int messageClass, String body)
+ throws Exception {
+ SmsMessage msg = createCmasSmsMessage(
+ serviceCategory, 1234, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
+ UserData.ENCODING_7BIT_ASCII, body, -1, -1, -1, -1, -1);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ verifyCbValues(cbMessage);
+ assertEquals(serviceCategory, cbMessage.getServiceCategory());
+ assertEquals(1234, cbMessage.getSerialNumber());
+ assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, cbMessage.getMessagePriority());
+ assertEquals("en", cbMessage.getLanguageCode());
+ assertEquals(body, cbMessage.getMessageBody());
+ assertEquals(true, cbMessage.isEmergencyMessage());
+ assertEquals(true, cbMessage.isCmasMessage());
+ SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
+ assertEquals(messageClass, cmasInfo.getMessageClass());
+ assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN, cmasInfo.getCategory());
+ assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, cmasInfo.getResponseType());
+ assertEquals(SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN, cmasInfo.getSeverity());
+ assertEquals(SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN, cmasInfo.getUrgency());
+ assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN, cmasInfo.getCertainty());
+ }
+
+ public void testCmasPresidentialAlert() throws Exception {
+ doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
+ SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT, PRES_ALERT);
+ }
+
+ public void testCmasExtremeAlert() throws Exception {
+ doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
+ SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT, EXTREME_ALERT);
+ }
+
+ public void testCmasSevereAlert() throws Exception {
+ doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
+ SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT, SEVERE_ALERT);
+ }
+
+ public void testCmasAmberAlert() throws Exception {
+ doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
+ SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY, AMBER_ALERT);
+ }
+
+ public void testCmasTestMessage() throws Exception {
+ doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
+ SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST, MONTHLY_TEST_ALERT);
+ }
+
+ public void testCmasExtremeAlertType1Elements() throws Exception {
+ SmsMessage msg = createCmasSmsMessage(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
+ 5678, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
+ UserData.ENCODING_7BIT_ASCII, EXTREME_ALERT, SmsCbCmasInfo.CMAS_CATEGORY_ENV,
+ SmsCbCmasInfo.CMAS_RESPONSE_TYPE_MONITOR, SmsCbCmasInfo.CMAS_SEVERITY_SEVERE,
+ SmsCbCmasInfo.CMAS_URGENCY_EXPECTED, SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ verifyCbValues(cbMessage);
+ assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
+ cbMessage.getServiceCategory());
+ assertEquals(5678, cbMessage.getSerialNumber());
+ assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, cbMessage.getMessagePriority());
+ assertEquals("en", cbMessage.getLanguageCode());
+ assertEquals(EXTREME_ALERT, cbMessage.getMessageBody());
+ assertEquals(true, cbMessage.isEmergencyMessage());
+ assertEquals(true, cbMessage.isCmasMessage());
+ SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
+ assertEquals(SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT, cmasInfo.getMessageClass());
+ assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_ENV, cmasInfo.getCategory());
+ assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_MONITOR, cmasInfo.getResponseType());
+ assertEquals(SmsCbCmasInfo.CMAS_SEVERITY_SEVERE, cmasInfo.getSeverity());
+ assertEquals(SmsCbCmasInfo.CMAS_URGENCY_EXPECTED, cmasInfo.getUrgency());
+ assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY, cmasInfo.getCertainty());
+ }
+
+ // VZW requirement is to discard message with unsupported charset. Verify that we return null
+ // for this unsupported character set.
+ public void testCmasUnsupportedCharSet() throws Exception {
+ SmsMessage msg = createCmasSmsMessage(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
+ 12345, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
+ UserData.ENCODING_GSM_DCS, EXTREME_ALERT, -1, -1, -1, -1, -1);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ assertNull("expected null for unsupported charset", cbMessage);
+ }
+
+ // VZW requirement is to discard message with unsupported charset. Verify that we return null
+ // for this unsupported character set.
+ public void testCmasUnsupportedCharSet2() throws Exception {
+ SmsMessage msg = createCmasSmsMessage(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
+ 67890, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
+ UserData.ENCODING_KOREAN, EXTREME_ALERT, -1, -1, -1, -1, -1);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ assertNull("expected null for unsupported charset", cbMessage);
+ }
+
+ // VZW requirement is to discard message without record type 0. The framework will decode it
+ // and the app will discard it.
+ public void testCmasNoRecordType0() throws Exception {
+ SmsMessage msg = createCmasSmsMessage(
+ SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT, 1234,
+ BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
+ UserData.ENCODING_7BIT_ASCII, null, -1, -1, -1, -1, -1);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ verifyCbValues(cbMessage);
+ assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
+ cbMessage.getServiceCategory());
+ assertEquals(1234, cbMessage.getSerialNumber());
+ assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, cbMessage.getMessagePriority());
+ assertEquals("en", cbMessage.getLanguageCode());
+ assertEquals(null, cbMessage.getMessageBody());
+ assertEquals(true, cbMessage.isEmergencyMessage());
+ assertEquals(true, cbMessage.isCmasMessage());
+ SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
+ assertEquals(SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT, cmasInfo.getMessageClass());
+ assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN, cmasInfo.getCategory());
+ assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, cmasInfo.getResponseType());
+ assertEquals(SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN, cmasInfo.getSeverity());
+ assertEquals(SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN, cmasInfo.getUrgency());
+ assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN, cmasInfo.getCertainty());
+ }
+
+ // Make sure we don't throw an exception if we feed completely random data to BearerStream.
+ public void testRandomBearerStreamData() {
+ Random r = new Random(54321);
+ for (int run = 0; run < 1000; run++) {
+ int len = r.nextInt(140);
+ byte[] data = new byte[len];
+ for (int i = 0; i < len; i++) {
+ data[i] = (byte) r.nextInt(256);
+ }
+ // Log.d("CdmaSmsCbTest", "trying random bearer data run " + run + " length " + len);
+ try {
+ int category = 0x0ff0 + r.nextInt(32); // half CMAS, half non-CMAS
+ Parcel p = createBroadcastParcel(category);
+ SmsMessage msg = createMessageFromParcel(p, data);
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ // with random input, cbMessage will almost always be null (log when it isn't)
+ if (cbMessage != null) {
+ Log.d("CdmaSmsCbTest", "success: " + cbMessage);
+ }
+ } catch (Exception e) {
+ Log.d("CdmaSmsCbTest", "exception thrown", e);
+ fail("Exception in decoder at run " + run + " length " + len + ": " + e);
+ }
+ }
+ }
+
+ // Make sure we don't throw an exception if we put random data in the UserData subparam.
+ public void testRandomUserData() {
+ Random r = new Random(94040);
+ for (int run = 0; run < 1000; run++) {
+ int category = 0x0ff0 + r.nextInt(32); // half CMAS, half non-CMAS
+ Parcel p = createBroadcastParcel(category);
+ int len = r.nextInt(140);
+ // Log.d("CdmaSmsCbTest", "trying random user data run " + run + " length " + len);
+
+ try {
+ BitwiseOutputStream bos = createBearerDataStream(r.nextInt(65536), r.nextInt(4),
+ r.nextInt(256));
+
+ bos.write(8, SUBPARAM_USER_DATA);
+ bos.write(8, len);
+
+ for (int i = 0; i < len; i++) {
+ bos.write(8, r.nextInt(256));
+ }
+
+ SmsMessage msg = createMessageFromParcel(p, bos.toByteArray());
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ } catch (Exception e) {
+ Log.d("CdmaSmsCbTest", "exception thrown", e);
+ fail("Exception in decoder at run " + run + " length " + len + ": " + e);
+ }
+ }
+ }
+
+ /**
+ * Initialize a Parcel for incoming Service Category Program Data teleservice. The caller will
+ * write the bearer data and then convert it to an SmsMessage.
+ * @return the initialized Parcel
+ */
+ private static Parcel createServiceCategoryProgramDataParcel() {
+ Parcel p = Parcel.obtain();
+
+ p.writeInt(SmsEnvelope.TELESERVICE_SCPT);
+ p.writeByte((byte) 0); // non-zero for MESSAGE_TYPE_BROADCAST
+ p.writeInt(0);
+
+ // dummy address (RIL may generate a different dummy address for broadcasts)
+ p.writeInt(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF); // sAddress.digit_mode
+ p.writeInt(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK); // sAddress.number_mode
+ p.writeInt(CdmaSmsAddress.TON_UNKNOWN); // sAddress.number_type
+ p.writeInt(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY); // sAddress.number_plan
+ p.writeByte((byte) 0); // sAddress.number_of_digits
+ p.writeInt((byte) 0); // sSubAddress.subaddressType
+ p.writeByte((byte) 0); // sSubAddress.odd
+ p.writeByte((byte) 0); // sSubAddress.number_of_digits
+ return p;
+ }
+
+ private static final String CAT_EXTREME_THREAT = "Extreme Threat to Life and Property";
+ private static final String CAT_SEVERE_THREAT = "Severe Threat to Life and Property";
+ private static final String CAT_AMBER_ALERTS = "AMBER Alerts";
+
+ public void testServiceCategoryProgramDataAddCategory() throws Exception {
+ Parcel p = createServiceCategoryProgramDataParcel();
+ BitwiseOutputStream bos = createBearerDataStream(123, -1, -1);
+
+ int categoryNameLength = CAT_EXTREME_THREAT.length();
+ int subparamLengthBits = (53 + (categoryNameLength * 7));
+ int subparamLengthBytes = (subparamLengthBits + 7) / 8;
+ int subparamPadBits = (subparamLengthBytes * 8) - subparamLengthBits;
+
+ bos.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA);
+ bos.write(8, subparamLengthBytes);
+ bos.write(5, UserData.ENCODING_7BIT_ASCII);
+
+ bos.write(4, CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY);
+ bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT >>> 8));
+ bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT & 0xff));
+ bos.write(8, BearerData.LANGUAGE_ENGLISH);
+ bos.write(8, 100); // max messages
+ bos.write(4, CdmaSmsCbProgramData.ALERT_OPTION_DEFAULT_ALERT);
+
+ bos.write(8, categoryNameLength);
+ for (int i = 0; i < categoryNameLength; i++) {
+ bos.write(7, CAT_EXTREME_THREAT.charAt(i));
+ }
+ bos.write(subparamPadBits, 0);
+
+ SmsMessage msg = createMessageFromParcel(p, bos.toByteArray());
+ assertNotNull(msg);
+ msg.parseSms();
+ List<CdmaSmsCbProgramData> programDataList = msg.getSmsCbProgramData();
+ assertNotNull(programDataList);
+ assertEquals(1, programDataList.size());
+ CdmaSmsCbProgramData programData = programDataList.get(0);
+ assertEquals(CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY, programData.getOperation());
+ assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, programData.getCategory());
+ assertEquals(CAT_EXTREME_THREAT, programData.getCategoryName());
+ assertEquals("en", programData.getLanguageCode());
+ assertEquals(100, programData.getMaxMessages());
+ assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_DEFAULT_ALERT, programData.getAlertOption());
+ }
+
+ public void testServiceCategoryProgramDataDeleteTwoCategories() throws Exception {
+ Parcel p = createServiceCategoryProgramDataParcel();
+ BitwiseOutputStream bos = createBearerDataStream(456, -1, -1);
+
+ int category1NameLength = CAT_SEVERE_THREAT.length();
+ int category2NameLength = CAT_AMBER_ALERTS.length();
+
+ int subparamLengthBits = (101 + (category1NameLength * 7) + (category2NameLength * 7));
+ int subparamLengthBytes = (subparamLengthBits + 7) / 8;
+ int subparamPadBits = (subparamLengthBytes * 8) - subparamLengthBits;
+
+ bos.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA);
+ bos.write(8, subparamLengthBytes);
+ bos.write(5, UserData.ENCODING_7BIT_ASCII);
+
+ bos.write(4, CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY);
+ bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT >>> 8));
+ bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT & 0xff));
+ bos.write(8, BearerData.LANGUAGE_ENGLISH);
+ bos.write(8, 0); // max messages
+ bos.write(4, CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT);
+
+ bos.write(8, category1NameLength);
+ for (int i = 0; i < category1NameLength; i++) {
+ bos.write(7, CAT_SEVERE_THREAT.charAt(i));
+ }
+
+ bos.write(4, CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY);
+ bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY >>> 8));
+ bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY & 0xff));
+ bos.write(8, BearerData.LANGUAGE_ENGLISH);
+ bos.write(8, 0); // max messages
+ bos.write(4, CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT);
+
+ bos.write(8, category2NameLength);
+ for (int i = 0; i < category2NameLength; i++) {
+ bos.write(7, CAT_AMBER_ALERTS.charAt(i));
+ }
+
+ bos.write(subparamPadBits, 0);
+
+ SmsMessage msg = createMessageFromParcel(p, bos.toByteArray());
+ assertNotNull(msg);
+ msg.parseSms();
+ List<CdmaSmsCbProgramData> programDataList = msg.getSmsCbProgramData();
+ assertNotNull(programDataList);
+ assertEquals(2, programDataList.size());
+
+ CdmaSmsCbProgramData programData = programDataList.get(0);
+ assertEquals(CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY, programData.getOperation());
+ assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, programData.getCategory());
+ assertEquals(CAT_SEVERE_THREAT, programData.getCategoryName());
+ assertEquals("en", programData.getLanguageCode());
+ assertEquals(0, programData.getMaxMessages());
+ assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption());
+
+ programData = programDataList.get(1);
+ assertEquals(CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY, programData.getOperation());
+ assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
+ programData.getCategory());
+ assertEquals(CAT_AMBER_ALERTS, programData.getCategoryName());
+ assertEquals("en", programData.getLanguageCode());
+ assertEquals(0, programData.getMaxMessages());
+ assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption());
+ }
+
+ private static final byte[] CMAS_TEST_BEARER_DATA = {
+ 0x00, 0x03, 0x1C, 0x78, 0x00, 0x01, 0x59, 0x02, (byte) 0xB8, 0x00, 0x02, 0x10, (byte) 0xAA,
+ 0x68, (byte) 0xD3, (byte) 0xCD, 0x06, (byte) 0x9E, 0x68, 0x30, (byte) 0xA0, (byte) 0xE9,
+ (byte) 0x97, (byte) 0x9F, 0x44, 0x1B, (byte) 0xF3, 0x20, (byte) 0xE9, (byte) 0xA3,
+ 0x2A, 0x08, 0x7B, (byte) 0xF6, (byte) 0xED, (byte) 0xCB, (byte) 0xCB, 0x1E, (byte) 0x9C,
+ 0x3B, 0x10, 0x4D, (byte) 0xDF, (byte) 0x8B, 0x4E,
+ (byte) 0xCC, (byte) 0xA8, 0x20, (byte) 0xEC, (byte) 0xCB, (byte) 0xCB, (byte) 0xA2, 0x0A,
+ 0x7E, 0x79, (byte) 0xF4, (byte) 0xCB, (byte) 0xB5, 0x72, 0x0A, (byte) 0x9A, 0x34,
+ (byte) 0xF3, 0x41, (byte) 0xA7, (byte) 0x9A, 0x0D, (byte) 0xFB, (byte) 0xB6, 0x79, 0x41,
+ (byte) 0x85, 0x07, 0x4C, (byte) 0xBC, (byte) 0xFA, 0x2E, 0x00, 0x08, 0x20, 0x58, 0x38,
+ (byte) 0x88, (byte) 0x80, 0x10, 0x54, 0x06, 0x38, 0x20, 0x60,
+ 0x30, (byte) 0xA8, (byte) 0x81, (byte) 0x90, 0x20, 0x08
+ };
+
+ // Test case for CMAS test message received on the Sprint network.
+ public void testDecodeRawBearerData() throws Exception {
+ Parcel p = createBroadcastParcel(SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE);
+ SmsMessage msg = createMessageFromParcel(p, CMAS_TEST_BEARER_DATA);
+
+ SmsCbMessage cbMessage = msg.parseBroadcastSms();
+ assertNotNull("expected non-null for bearer data", cbMessage);
+ assertEquals("geoScope", cbMessage.getGeographicalScope(), 1);
+ assertEquals("serialNumber", cbMessage.getSerialNumber(), 51072);
+ assertEquals("serviceCategory", cbMessage.getServiceCategory(),
+ SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE);
+ assertEquals("payload", cbMessage.getMessageBody(),
+ "This is a test of the Commercial Mobile Alert System. This is only a test.");
+
+ SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
+ assertNotNull("expected non-null for CMAS info", cmasInfo);
+ assertEquals("category", cmasInfo.getCategory(), SmsCbCmasInfo.CMAS_CATEGORY_OTHER);
+ assertEquals("responseType", cmasInfo.getResponseType(),
+ SmsCbCmasInfo.CMAS_RESPONSE_TYPE_NONE);
+ assertEquals("severity", cmasInfo.getSeverity(), SmsCbCmasInfo.CMAS_SEVERITY_SEVERE);
+ assertEquals("urgency", cmasInfo.getUrgency(), SmsCbCmasInfo.CMAS_URGENCY_EXPECTED);
+ assertEquals("certainty", cmasInfo.getCertainty(), SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
new file mode 100644
index 0000000..bb37b65
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
@@ -0,0 +1,887 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.cdma.SmsMessage;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+import com.android.internal.util.HexDump;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class CdmaSmsTest extends AndroidTestCase {
+ private final static String LOG_TAG = "XXX CdmaSmsTest XXX";
+
+ @SmallTest
+ public void testCdmaSmsAddrParsing() throws Exception {
+ CdmaSmsAddress addr = CdmaSmsAddress.parse("6502531000");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 10);
+ assertEquals(addr.origBytes.length, 10);
+ byte[] data = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+ for (int i = 0; i < data.length; i++) {
+ assertEquals(addr.origBytes[i], data[i]);
+ }
+ addr = CdmaSmsAddress.parse("(650) 253-1000");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 10);
+ assertEquals(addr.origBytes.length, 10);
+ byte[] data2 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+ for (int i = 0; i < data2.length; i++) {
+ assertEquals(addr.origBytes[i], data2[i]);
+ }
+ addr = CdmaSmsAddress.parse("650.253.1000");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 10);
+ assertEquals(addr.origBytes.length, 10);
+ byte[] data5 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+ for (int i = 0; i < data2.length; i++) {
+ assertEquals(addr.origBytes[i], data5[i]);
+ }
+ addr = CdmaSmsAddress.parse("(+886) 917 222 555");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_INTERNATIONAL_OR_IP);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 12);
+ assertEquals(addr.origBytes.length, 12);
+ byte[] data3 = {8, 8, 6, 9, 1, 7, 2, 2, 2, 5, 5, 5};
+ for (int i = 0; i < data3.length; i++) {
+ assertEquals(addr.origBytes[i], data3[i]);
+ }
+ addr = CdmaSmsAddress.parse("(650) *253-1000 #600");
+ byte[] data4 = {6, 5, 10, 11, 2, 5, 3, 1, 10, 10, 10, 12, 6, 10, 10};
+ for (int i = 0; i < data4.length; i++) {
+ assertEquals(addr.origBytes[i], data4[i]);
+ }
+ String input = "x@y.com,a@b.com";
+ addr = CdmaSmsAddress.parse(input);
+ assertEquals(addr.ton, CdmaSmsAddress.TON_NATIONAL_OR_EMAIL);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 15);
+ assertEquals(addr.origBytes.length, 15);
+ assertEquals(new String(addr.origBytes), input);
+ addr = CdmaSmsAddress.parse("foo bar");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 6);
+ assertEquals(addr.origBytes.length, 6);
+ assertEquals(new String(addr.origBytes), "foobar");
+ addr = CdmaSmsAddress.parse("f\noo\tb a\rr");
+ assertEquals(new String(addr.origBytes), "foobar");
+ assertEquals(CdmaSmsAddress.parse("f\u0000oo bar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u0007oo bar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u1ECFboo\u001fbar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
+ }
+
+ @SmallTest
+ public void testUserData7bitGsm() throws Exception {
+ String pdu = "00031040900112488ea794e074d69e1b7392c270326cde9e98";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("Test standard SMS", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitAscii() throws Exception {
+ String pdu = "0003100160010610262d5ab500";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("bjjj", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitAsciiTwo() throws Exception {
+ String pdu = "00031001d00109104539b4d052ebb3d0";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("SMS Rulz", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserDataIa5() throws Exception {
+ String pdu = "00031002100109184539b4d052ebb3d0";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("SMS Rulz", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitAsciiFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "Test standard SMS";
+ userData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+ userData.msgEncodingSet = true;
+ bearerData.userData = userData;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "Test \u007f standard \u0000 SMS";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals("Test standard SMS", revBearerData.userData.payloadStr);
+ userData.payloadStr = "Test \n standard \r SMS";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitGsmFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "Test standard SMS";
+ userData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+ userData.msgEncodingSet = true;
+ bearerData.userData = userData;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "1234567";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "12345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789012345678901234567890" +
+ "1234567890";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "Test \u007f illegal \u0000 SMS chars";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals("Test illegal SMS chars", revBearerData.userData.payloadStr);
+ userData.payloadStr = "More @ testing\nis great^|^~woohoo";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ userData.userDataHeader = smsHeader;
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ SmsHeader decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ }
+
+ @SmallTest
+ public void testUserDataUtf16Feedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "\u0160u\u1E5B\u0301r\u1ECFg\uD835\uDC1At\u00E9\u4E002\u3042";
+ userData.msgEncoding = UserData.ENCODING_UNICODE_16;
+ userData.msgEncodingSet = true;
+ bearerData.userData = userData;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.msgEncoding = UserData.ENCODING_OCTET;
+ userData.msgEncodingSet = false;
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "1234567";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testMonolithicOne() throws Exception {
+ String pdu = "0003200010010410168d2002010503060812011101590501c706069706180000000701c108" +
+ "01c00901800a01e00b01030c01c00d01070e05039acc13880f018011020566";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals(bearerData.messageType, BearerData.MESSAGE_TYPE_SUBMIT);
+ assertEquals(bearerData.messageId, 1);
+ assertEquals(bearerData.priority, BearerData.PRIORITY_EMERGENCY);
+ assertEquals(bearerData.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ assertEquals(bearerData.userAckReq, true);
+ assertEquals(bearerData.readAckReq, true);
+ assertEquals(bearerData.deliveryAckReq, true);
+ assertEquals(bearerData.reportReq, false);
+ assertEquals(bearerData.numberOfMessages, 3);
+ assertEquals(bearerData.alert, BearerData.ALERT_HIGH_PRIO);
+ assertEquals(bearerData.language, BearerData.LANGUAGE_HEBREW);
+ assertEquals(bearerData.callbackNumber.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(bearerData.callbackNumber.numberMode,
+ CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(bearerData.callbackNumber.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberPlan, CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberOfDigits, 7);
+ assertEquals(bearerData.callbackNumber.address, "3598271");
+ assertEquals(bearerData.displayMode, BearerData.DISPLAY_MODE_USER);
+ assertEquals(bearerData.depositIndex, 1382);
+ assertEquals(bearerData.userResponseCode, 5);
+ assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
+ assertEquals(bearerData.msgCenterTimeStamp.month, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.second, 59);
+ assertEquals(bearerData.validityPeriodAbsolute, null);
+ assertEquals(bearerData.validityPeriodRelative, 193);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.month, 5);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.second, 0);
+ assertEquals(bearerData.deferredDeliveryTimeRelative, 199);
+ assertEquals(bearerData.hasUserDataHeader, false);
+ assertEquals(bearerData.userData.msgEncoding, UserData.ENCODING_7BIT_ASCII);
+ assertEquals(bearerData.userData.numFields, 2);
+ assertEquals(bearerData.userData.payloadStr, "hi");
+ }
+
+ @SmallTest
+ public void testMonolithicTwo() throws Exception {
+ String pdu = "0003200010010410168d200201050306081201110159050192060697061800000007013d0" +
+ "801c00901800a01e00b01030c01c00d01070e05039acc13880f018011020566";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals(bearerData.messageType, BearerData.MESSAGE_TYPE_SUBMIT);
+ assertEquals(bearerData.messageId, 1);
+ assertEquals(bearerData.priority, BearerData.PRIORITY_EMERGENCY);
+ assertEquals(bearerData.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ assertEquals(bearerData.userAckReq, true);
+ assertEquals(bearerData.readAckReq, true);
+ assertEquals(bearerData.deliveryAckReq, true);
+ assertEquals(bearerData.reportReq, false);
+ assertEquals(bearerData.numberOfMessages, 3);
+ assertEquals(bearerData.alert, BearerData.ALERT_HIGH_PRIO);
+ assertEquals(bearerData.language, BearerData.LANGUAGE_HEBREW);
+ assertEquals(bearerData.callbackNumber.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(bearerData.callbackNumber.numberMode,
+ CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(bearerData.callbackNumber.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberPlan, CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberOfDigits, 7);
+ assertEquals(bearerData.callbackNumber.address, "3598271");
+ assertEquals(bearerData.displayMode, BearerData.DISPLAY_MODE_USER);
+ assertEquals(bearerData.depositIndex, 1382);
+ assertEquals(bearerData.userResponseCode, 5);
+ assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
+ assertEquals(bearerData.msgCenterTimeStamp.month, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.second, 59);
+ assertEquals(bearerData.validityPeriodAbsolute, null);
+ assertEquals(bearerData.validityPeriodRelative, 61);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.month, 5);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.second, 0);
+ assertEquals(bearerData.deferredDeliveryTimeRelative, 146);
+ assertEquals(bearerData.hasUserDataHeader, false);
+ assertEquals(bearerData.userData.msgEncoding, UserData.ENCODING_7BIT_ASCII);
+ assertEquals(bearerData.userData.numFields, 2);
+ assertEquals(bearerData.userData.payloadStr, "hi");
+ }
+
+ @SmallTest
+ public void testUserDataHeaderConcatRefFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs, null);
+ UserData userData = new UserData();
+ userData.payloadStr = "User Data Header (UDH) feedback test";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs, null);
+ }
+
+ @SmallTest
+ public void testUserDataHeaderIllegalConcatRef() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0x10;
+ concatRef.msgCount = 0;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.isEightBits = false;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.msgCount = 1;
+ concatRef.seqNumber = 2;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.msgCount = 1;
+ concatRef.seqNumber = 0;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 1;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.msgCount, 2);
+ assertEquals(decodedHeader.concatRef.seqNumber, 1);
+ }
+
+ @SmallTest
+ public void testUserDataHeaderMixedFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 42;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0x34;
+ concatRef.msgCount = 5;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = false;
+ SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+ portAddrs.destPort = 88;
+ portAddrs.origPort = 66;
+ portAddrs.areEightBits = false;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ smsHeader.portAddrs = portAddrs;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
+ assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
+ assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
+ UserData userData = new UserData();
+ userData.payloadStr = "User Data Header (UDH) feedback test";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
+ assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
+ assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
+ }
+
+ @SmallTest
+ public void testReplyOption() throws Exception {
+ String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("Test Acknowledgement 1", bd1.userData.payloadStr);
+ assertEquals(true, bd1.userAckReq);
+ assertEquals(false, bd1.deliveryAckReq);
+ assertEquals(false, bd1.readAckReq);
+ assertEquals(false, bd1.reportReq);
+ String pdu2 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87490080a0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals("Test Acknowledgement 2", bd2.userData.payloadStr);
+ assertEquals(false, bd2.userAckReq);
+ assertEquals(true, bd2.deliveryAckReq);
+ assertEquals(false, bd2.readAckReq);
+ assertEquals(false, bd2.reportReq);
+ String pdu3 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d874d0080a0120";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals("Test Acknowledgement 3", bd3.userData.payloadStr);
+ assertEquals(false, bd3.userAckReq);
+ assertEquals(false, bd3.deliveryAckReq);
+ assertEquals(true, bd3.readAckReq);
+ assertEquals(false, bd3.reportReq);
+ String pdu4 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87510080a0110";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals("Test Acknowledgement 4", bd4.userData.payloadStr);
+ assertEquals(false, bd4.userAckReq);
+ assertEquals(false, bd4.deliveryAckReq);
+ assertEquals(false, bd4.readAckReq);
+ assertEquals(true, bd4.reportReq);
+ }
+
+ @SmallTest
+ public void testReplyOptionFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test reply option";
+ bearerData.userData = userData;
+ bearerData.userAckReq = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(true, revBearerData.userAckReq);
+ assertEquals(false, revBearerData.deliveryAckReq);
+ assertEquals(false, revBearerData.readAckReq);
+ assertEquals(false, revBearerData.reportReq);
+ bearerData.userAckReq = false;
+ bearerData.deliveryAckReq = true;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(false, revBearerData.userAckReq);
+ assertEquals(true, revBearerData.deliveryAckReq);
+ assertEquals(false, revBearerData.readAckReq);
+ assertEquals(false, revBearerData.reportReq);
+ bearerData.deliveryAckReq = false;
+ bearerData.readAckReq = true;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(false, revBearerData.userAckReq);
+ assertEquals(false, revBearerData.deliveryAckReq);
+ assertEquals(true, revBearerData.readAckReq);
+ assertEquals(false, revBearerData.reportReq);
+ bearerData.readAckReq = false;
+ bearerData.reportReq = true;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(false, revBearerData.userAckReq);
+ assertEquals(false, revBearerData.deliveryAckReq);
+ assertEquals(false, revBearerData.readAckReq);
+ assertEquals(true, revBearerData.reportReq);
+ }
+
+ @SmallTest
+ public void testNumberOfMessages() throws Exception {
+ // Note that the message text below does not properly reflect
+ // the message count. The author of these messages was
+ // apparently unaware that the values are bcd encoded, and the
+ // values being tested against (not the ones in the message
+ // text) are actually correct.
+ String pdu1 = "000310409001124896a794e07595f69f199540ea759a0dc8e00b0163";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("Test Voice mail 99", bd1.userData.payloadStr);
+ assertEquals(63, bd1.numberOfMessages);
+ String pdu2 = "00031040900113489ea794e07595f69f199540ea759a0988c0600b0164";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals("Test Voice mail 100", bd2.userData.payloadStr);
+ assertEquals(64, bd2.numberOfMessages);
+ }
+
+ @SmallTest
+ public void testCallbackNum() throws Exception {
+ String pdu1 = "00031040900112488ea794e070d436cb638bc5e035ce2f97900e06910431323334";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("Test Callback nbr", bd1.userData.payloadStr);
+ assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, bd1.callbackNumber.digitMode);
+ assertEquals(CdmaSmsAddress.TON_INTERNATIONAL_OR_IP, bd1.callbackNumber.ton);
+ assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
+ assertEquals(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY, bd1.callbackNumber.numberPlan);
+ assertEquals("1234", bd1.callbackNumber.address);
+ }
+
+ @SmallTest
+ public void testCallbackNumDtmf() throws Exception {
+ String pdu1 = "00031002300109104539b4d052ebb3d00e07052d4c90a55080";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("SMS Rulz", bd1.userData.payloadStr);
+ assertEquals(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF, bd1.callbackNumber.digitMode);
+ assertEquals(CdmaSmsAddress.TON_UNKNOWN, bd1.callbackNumber.ton);
+ assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
+ assertEquals(CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN, bd1.callbackNumber.numberPlan);
+ assertEquals("5099214001", bd1.callbackNumber.address);
+ }
+
+ @SmallTest
+ public void testCallbackNumFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test callback number";
+ bearerData.userData = userData;
+ CdmaSmsAddress addr = new CdmaSmsAddress();
+ addr.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
+ addr.ton = CdmaSmsAddress.TON_NATIONAL_OR_EMAIL;
+ addr.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
+ addr.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN;
+ addr.address = "8005551212";
+ addr.numberOfDigits = (byte)addr.address.length();
+ bearerData.callbackNumber = addr;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ CdmaSmsAddress revAddr = revBearerData.callbackNumber;
+ assertEquals(addr.digitMode, revAddr.digitMode);
+ assertEquals(addr.ton, revAddr.ton);
+ assertEquals(addr.numberMode, revAddr.numberMode);
+ assertEquals(addr.numberPlan, revAddr.numberPlan);
+ assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+ assertEquals(addr.address, revAddr.address);
+ addr.address = "8*55#1012";
+ addr.numberOfDigits = (byte)addr.address.length();
+ addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ revAddr = revBearerData.callbackNumber;
+ assertEquals(addr.digitMode, revAddr.digitMode);
+ assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+ assertEquals(addr.address, revAddr.address);
+ }
+
+ @SmallTest
+ public void testPrivacyIndicator() throws Exception {
+ String pdu1 = "0003104090010c485f4194dfea34becf61b840090140";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.privacy, BearerData.PRIVACY_RESTRICTED);
+ String pdu2 = "0003104090010c485f4194dfea34becf61b840090180";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ String pdu3 = "0003104090010c485f4194dfea34becf61b8400901c0";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.privacy, BearerData.PRIVACY_SECRET);
+ }
+
+ @SmallTest
+ public void testPrivacyIndicatorFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test privacy indicator";
+ bearerData.userData = userData;
+ bearerData.privacy = BearerData.PRIVACY_SECRET;
+ bearerData.privacyIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.privacyIndicatorSet, true);
+ assertEquals(revBearerData.privacy, BearerData.PRIVACY_SECRET);
+ bearerData.privacy = BearerData.PRIVACY_RESTRICTED;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.privacy, BearerData.PRIVACY_RESTRICTED);
+ }
+
+ @SmallTest
+ public void testMsgDeliveryAlert() throws Exception {
+ String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.alert, 0);
+ assertEquals(bd1.userData.payloadStr, "Test Alert 0");
+ String pdu2 = "0003104090010d4866a794e07055965b91d140300c0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.alert, 1);
+ assertEquals(bd2.userData.payloadStr, "Test Alert 1");
+ String pdu3 = "0003104090010d4866a794e07055965b91d240300c0180";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.alert, 2);
+ assertEquals(bd3.userData.payloadStr, "Test Alert 2");
+ String pdu4 = "0003104090010d4866a794e07055965b91d340300c01c0";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.alert, 3);
+ assertEquals(bd4.userData.payloadStr, "Test Alert 3");
+ String pdu5 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
+ "69ED979794187665E5D1028EFA7A6840E1062D3D39A900C028000";
+ BearerData bd5 = BearerData.decode(HexDump.hexStringToByteArray(pdu5));
+ assertEquals(bd5.alert, BearerData.ALERT_MEDIUM_PRIO);
+ assertEquals(bd5.userData.payloadStr, "test message delivery alert (with 8 bits)");
+ String pdu6 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
+ "69ED979794187665E5D1028EFA7A6840C1062D3D39A900C00";
+ BearerData bd6 = BearerData.decode(HexDump.hexStringToByteArray(pdu6));
+ assertEquals(bd6.userData.payloadStr, "test message delivery alert (with 0 bits)");
+ assertEquals(bd6.alertIndicatorSet, false);
+ }
+
+ @SmallTest
+ public void testMiscParams() throws Exception {
+ String pdu1 = "00031002400109104539b4d052ebb3d00c0180";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.alert, BearerData.ALERT_MEDIUM_PRIO);
+ assertEquals(bd1.userData.payloadStr, "SMS Rulz");
+ String pdu2 = "00031002500109104539b4d052ebb3d00801800901c0";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.priority, BearerData.PRIORITY_URGENT);
+ assertEquals(bd2.privacy, BearerData.PRIVACY_SECRET);
+ assertEquals(bd2.userData.payloadStr, "SMS Rulz");
+ String pdu3 = "00031002600109104539b4d052ebb3d00901400c01c0";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.privacy, BearerData.PRIVACY_RESTRICTED);
+ assertEquals(bd3.alert, BearerData.ALERT_HIGH_PRIO);
+ assertEquals(bd3.userData.payloadStr, "SMS Rulz");
+ String pdu4 = "00031002700109104539b4d052ebb3d00f0105";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
+ assertEquals(bd4.userData.payloadStr, "SMS Rulz");
+ }
+ @SmallTest
+ public void testMsgDeliveryAlertFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test message delivery alert";
+ bearerData.userData = userData;
+ bearerData.alert = BearerData.ALERT_MEDIUM_PRIO;
+ bearerData.alertIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.alertIndicatorSet, true);
+ assertEquals(revBearerData.alert, bearerData.alert);
+ bearerData.alert = BearerData.ALERT_HIGH_PRIO;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.alertIndicatorSet, true);
+ assertEquals(revBearerData.alert, bearerData.alert);
+ }
+
+ @SmallTest
+ public void testLanguageIndicator() throws Exception {
+ String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.userData.payloadStr, "Test Language indicator");
+ assertEquals(bd1.language, BearerData.LANGUAGE_ENGLISH);
+ String pdu2 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0106";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.userData.payloadStr, "Test Language indicator");
+ assertEquals(bd2.language, BearerData.LANGUAGE_CHINESE);
+ }
+
+ @SmallTest
+ public void testLanguageIndicatorFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test language indicator";
+ bearerData.userData = userData;
+ bearerData.language = BearerData.LANGUAGE_ENGLISH;
+ bearerData.languageIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.languageIndicatorSet, true);
+ assertEquals(revBearerData.language, bearerData.language);
+ bearerData.language = BearerData.LANGUAGE_KOREAN;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.languageIndicatorSet, true);
+ assertEquals(revBearerData.language, bearerData.language);
+ }
+
+ @SmallTest
+ public void testDisplayMode() throws Exception {
+ String pdu1 = "0003104090010c485f4194dfea34becf61b8400f0100";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
+ String pdu2 = "0003104090010c485f4194dfea34becf61b8400f0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.displayMode, BearerData.DISPLAY_MODE_DEFAULT);
+ String pdu3 = "0003104090010c485f4194dfea34becf61b8400f0180";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.displayMode, BearerData.DISPLAY_MODE_USER);
+ }
+
+ @SmallTest
+ public void testDisplayModeFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test display mode";
+ bearerData.userData = userData;
+ bearerData.displayMode = BearerData.DISPLAY_MODE_IMMEDIATE;
+ bearerData.displayModeSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.displayModeSet, true);
+ assertEquals(revBearerData.displayMode, bearerData.displayMode);
+ bearerData.displayMode = BearerData.DISPLAY_MODE_USER;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.displayModeSet, true);
+ assertEquals(revBearerData.displayMode, bearerData.displayMode);
+ }
+
+ @SmallTest
+ public void testIs91() throws Exception {
+ String pdu1 = "000320001001070c2039acc13880";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.callbackNumber.address, "3598271");
+ String pdu4 = "000320001001080c283c314724b34e";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.userData.payloadStr, "ABCDEFG");
+ }
+
+ @SmallTest
+ public void testUserDataHeaderWithEightCharMsg() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ UserData userData = new UserData();
+ userData.payloadStr = "01234567";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testFragmentText() throws Exception {
+ boolean isCdmaPhone = (TelephonyManager.getDefault().getPhoneType() ==
+ TelephonyManager.PHONE_TYPE_CDMA);
+ // Valid 160 character ASCII text.
+ String text1 = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789[";
+ TextEncodingDetails ted = SmsMessage.calculateLength(text1, false);
+ assertEquals(ted.msgCount, 1);
+ assertEquals(ted.codeUnitCount, 160);
+ assertEquals(ted.codeUnitSize, 1);
+ if (isCdmaPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text1);
+ assertEquals(fragments.size(), 1);
+ }
+
+ /*
+ This is not a valid test: we will never encode a single-segment
+ EMS message. Leaving this here, since we may try to support
+ this in the future.
+
+ // Valid 160 character GSM text -- the last character is
+ // non-ASCII, and so this will currently generate a singleton
+ // EMS message, which is not necessarily supported by Verizon.
+ String text2 = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789\u00a3"; // Trailing pound-currency sign.
+ ted = SmsMessage.calculateLength(text2, false);
+ assertEquals(ted.msgCount, 1);
+ assertEquals(ted.codeUnitCount, 160);
+ assertEquals(ted.codeUnitSize, 1);
+ if (isCdmaPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
+ assertEquals(fragments.size(), 1);
+ }
+ */
+
+ // *IF* we supported single-segment EMS, this text would result in a
+ // single fragment with 7-bit encoding. But we don't, so this text
+ // results in three fragments of 16-bit encoding.
+ String text2 = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789\u00a3"; // Trailing pound-currency sign.
+ ted = SmsMessage.calculateLength(text2, false);
+ assertEquals(3, ted.msgCount);
+ assertEquals(160, ted.codeUnitCount);
+ assertEquals(3, ted.codeUnitSize);
+ if (isCdmaPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
+ assertEquals(3, fragments.size());
+ }
+
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java
new file mode 100644
index 0000000..699f113
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java
@@ -0,0 +1,1933 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF GSMTestHandler.ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.telephony.ServiceState;
+import android.test.AndroidTestCase;
+import android.test.PerformanceTestCase;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.gsm.CallFailCause;
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.gsm.GSMTestHandler;
+import com.android.internal.telephony.gsm.GsmMmiCode;
+import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+
+import java.util.List;
+
+
+public class GSMPhoneTest extends AndroidTestCase implements PerformanceTestCase {
+ private SimulatedRadioControl mRadioControl;
+ private GSMPhone mGSMPhone;
+ private GSMTestHandler mGSMTestHandler;
+ private Handler mHandler;
+
+ private static final int EVENT_PHONE_STATE_CHANGED = 1;
+ private static final int EVENT_DISCONNECT = 2;
+ private static final int EVENT_RINGING = 3;
+ private static final int EVENT_CHANNEL_OPENED = 4;
+ private static final int EVENT_POST_DIAL = 5;
+ private static final int EVENT_DONE = 6;
+ private static final int EVENT_SSN = 7;
+ private static final int EVENT_MMI_INITIATE = 8;
+ private static final int EVENT_MMI_COMPLETE = 9;
+ private static final int EVENT_IN_SERVICE = 10;
+ private static final int SUPP_SERVICE_FAILED = 11;
+ private static final int SERVICE_STATE_CHANGED = 12;
+ private static final int EVENT_OEM_RIL_MESSAGE = 13;
+ public static final int ANY_MESSAGE = -1;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mGSMTestHandler = new GSMTestHandler(mContext);
+
+ mGSMTestHandler.start();
+ synchronized (mGSMTestHandler) {
+ do {
+ mGSMTestHandler.wait();
+ } while (mGSMTestHandler.getGSMPhone() == null);
+ }
+
+ mGSMPhone = mGSMTestHandler.getGSMPhone();
+ mRadioControl = mGSMTestHandler.getSimulatedCommands();
+
+ mHandler = mGSMTestHandler.getHandler();
+ mGSMPhone.registerForPreciseCallStateChanged(mHandler, EVENT_PHONE_STATE_CHANGED, null);
+ mGSMPhone.registerForNewRingingConnection(mHandler, EVENT_RINGING, null);
+ mGSMPhone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null);
+
+ mGSMPhone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL, null);
+
+ mGSMPhone.registerForSuppServiceNotification(mHandler, EVENT_SSN, null);
+ mGSMPhone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null);
+ mGSMPhone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
+ mGSMPhone.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);
+
+ mGSMPhone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);
+
+ // wait until we get phone in both voice and data service
+ Message msg;
+ ServiceState state;
+
+ do {
+ msg = mGSMTestHandler.waitForMessage(SERVICE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+ state = (ServiceState) ((AsyncResult) msg.obj).result;
+ } while (state.getState() != ServiceState.STATE_IN_SERVICE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mRadioControl.shutdown();
+
+ mGSMPhone.unregisterForPreciseCallStateChanged(mHandler);
+ mGSMPhone.unregisterForNewRingingConnection(mHandler);
+ mGSMPhone.unregisterForDisconnect(mHandler);
+ mGSMPhone.setOnPostDialCharacter(mHandler, 0, null);
+ mGSMPhone.unregisterForSuppServiceNotification(mHandler);
+ mGSMPhone.unregisterForMmiInitiate(mHandler);
+ mGSMPhone.unregisterForMmiComplete(mHandler);
+
+ mGSMPhone = null;
+ mRadioControl = null;
+ mHandler = null;
+ mGSMTestHandler.cleanup();
+
+ super.tearDown();
+ }
+
+ // These test can only be run once.
+ public int startPerformance(Intermediates intermediates) {
+ return 1;
+ }
+
+ public boolean isPerformanceOnly() {
+ return false;
+ }
+
+
+ //This test is causing the emulator screen to turn off. I don't understand
+ //why, but I'm removing it until we can figure it out.
+ public void brokenTestGeneral() throws Exception {
+ Connection cn;
+ Message msg;
+ AsyncResult ar;
+
+ // IDLE state
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ assertFalse(mGSMPhone.canConference());
+
+ // One DIALING connection
+
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ mGSMPhone.dial("+13125551212");
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.DIALING, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ /*do {
+ mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ } while (mGSMPhone.getForegroundCall().getConnections().size() == 0);*/
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DIALING,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One ALERTING connection
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ALERTING, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+ assertFalse(mGSMPhone.canConference());
+
+ // One ACTIVE connection
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.COMPLETE, cn.getPostDialState());
+ assertFalse(mGSMPhone.canConference());
+
+ // One disconnected connection
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ assertFalse(mGSMPhone.canConference());
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // cn left over from before phone.clearDisconnected();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing (INCOMING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ ar = (AsyncResult) msg.obj;
+ cn = (Connection) ar.result;
+ assertTrue(cn.isRinging());
+ assertEquals(mGSMPhone.getRingingCall(), cn.getCall());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getRingingCall().getConnections().get(0);
+ assertTrue(cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One mobile terminated active call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().size() == 1);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One disconnected (local hangup) call
+
+ try {
+ Connection conn;
+ conn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ conn.hangup();
+ } catch (CallStateException ex) {
+ ex.printStackTrace();
+ fail("unexpected ex");
+ }
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // cn left over from before phone.clearDisconnected();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().isEmpty());
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One rejected call
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().isEmpty());
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ // Ringing call disconnects
+
+ mRadioControl.triggerHangupForeground();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.IDLE);
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+
+ // One Ringing Call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.RINGING);
+
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ // One answered call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // one holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // one active call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // One disconnected call in the foreground slot
+
+ mRadioControl.triggerHangupAll();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.IDLE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ // Test missed calls
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.RINGING);
+
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (msg.what != EVENT_DISCONNECT);
+
+ ar = (AsyncResult) msg.obj;
+ cn = (Connection) ar.result;
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+
+ // Test incoming not missed calls
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.RINGING);
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);
+
+ assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+
+ try {
+ mGSMPhone.getForegroundCall().hangup();
+ } catch (CallStateException ex) {
+ ex.printStackTrace();
+ fail("unexpected ex");
+ }
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState()
+ != Call.State.DISCONNECTED);
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ //
+ // Test held and hangup held calls
+ //
+
+ // One ALERTING call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);
+
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ mRadioControl.progressConnectingCallState();
+ mRadioControl.progressConnectingCallState();
+
+ // One ACTIVE call
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ // One ACTIVE call, one ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.RINGING);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ // One HOLDING call, one ACTIVE call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertTrue(mGSMPhone.canConference());
+
+ // Conference the two
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getForegroundCall().isMultiparty());
+ assertFalse(mGSMPhone.canConference());
+
+ // Hold the multiparty call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
+ assertFalse(mGSMPhone.canConference());
+
+ // Multiparty call on hold, call waiting added
+
+ mRadioControl.triggerRing("18005558355");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.RINGING);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertFalse(mGSMPhone.canConference());
+
+ // Hangup conference call, ringing call still around
+ mGSMPhone.getBackgroundCall().hangup();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.DISCONNECTED);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ // Reject waiting call
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ }
+
+ public void testOutgoingCallFailImmediately() throws Exception {
+ Message msg;
+
+ // Test outgoing call fail-immediately edge case
+ // This happens when a call terminated before ever appearing in a
+ // call list
+ // This should land the immediately-failing call in the
+ // ForegroundCall list as an IDLE call
+ mRadioControl.setNextDialFailImmediately(true);
+
+ Connection cn = mGSMPhone.dial("+13125551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ }
+
+ public void testHangupOnOutgoing() throws Exception {
+ Connection cn;
+ Message msg;
+
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ // Test 1: local hangup in "DIALING" state
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.DIALING);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ // Test 2: local hangup in "ALERTING" state
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ // Test 3: local immediate hangup before GSM index is
+ // assigned (CallTracker.hangupPendingMO case)
+
+ mRadioControl.pauseResponses();
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ cn.hangup();
+
+ mRadioControl.resumeResponses();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+
+ assertEquals(Connection.DisconnectCause.LOCAL,
+ mGSMPhone.getForegroundCall().getEarliestConnection().getDisconnectCause());
+ }
+
+ public void testHangupOnChannelClose() throws Exception {
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getConnections().isEmpty());
+
+ mRadioControl.shutdown();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ mGSMPhone.clearDisconnected();
+ } while (!mGSMPhone.getForegroundCall().getConnections().isEmpty());
+ }
+
+ public void testIncallMmiCallDeflection() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 0 followed by SEND: release all held calls
+ // or sets UDUB for a waiting call.
+ mGSMPhone.handleInCallMmiCommands("0");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // change the active call to holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 0 followed by SEND: release all held calls
+ // or sets UDUB for a waiting call.
+ mGSMPhone.handleInCallMmiCommands("0");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testIncallMmiCallWaiting() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (msg.what != EVENT_RINGING);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // change the active call to holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // at this point, the active call with number==18005551212 should
+ // have the gsm index of 2
+
+ mRadioControl.triggerRing("16505550100");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering "12" followed by SEND: release the call with
+ // gsm index equals to 2.
+ mGSMPhone.handleInCallMmiCommands("12");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // at this point, the call with number==16505550100 should
+ // have the gsm index of 1
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE ||
+ mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // at this point, the active call with number==13125551212 should
+ // have the gsm index of 2
+
+ // Simulate entering "11" followed by SEND: release the call with
+ // gsm index equals to 1. This should not be allowed, and a
+ // Supplementary Service notification must be received.
+ mGSMPhone.handleInCallMmiCommands("11");
+
+ msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
+ assertNotNull("Message Time Out", msg);
+ assertFalse("IncallMmiCallWaiting: command should not work on holding call", msg == null);
+
+ // Simulate entering "12" followed by SEND: release the call with
+ // gsm index equals to 2.
+ mGSMPhone.handleInCallMmiCommands("12");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550100",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // Simulate entering "11" followed by SEND: release the call with
+ // gsm index equals to 1.
+ mGSMPhone.handleInCallMmiCommands("11");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testIncallMmiCallHold() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // simulate entering 2 followed by SEND: place all active calls
+ // (if any exist) on hold and accepts the other (held or waiting)
+ // call
+
+ mGSMPhone.handleInCallMmiCommands("2");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ // swap the active and holding calls
+ mGSMPhone.handleInCallMmiCommands("2");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ // merge the calls
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals(2, mGSMPhone.getForegroundCall().getConnections().size());
+
+ // at this point, we have an active conference call, with
+ // call(1) = 13125551212 and call(2) = 18005551212
+
+ // Simulate entering "23" followed by SEND: places all active call
+ // on hold except call 3. This should fail and a supplementary service
+ // failed notification should be received.
+
+ mGSMPhone.handleInCallMmiCommands("23");
+
+ msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
+ assertNotNull("Message Time Out", msg);
+ assertFalse("IncallMmiCallHold: separate should have failed!", msg == null);
+
+ // Simulate entering "21" followed by SEND: places all active call
+ // on hold except call 1.
+ mGSMPhone.handleInCallMmiCommands("21");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+ }
+
+ public void testIncallMmiMultipartyServices() throws Exception {
+ // establish an active call
+ mGSMPhone.dial("13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // dial another call
+ mGSMPhone.dial("18005551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.handleInCallMmiCommands("3");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(PhoneConstants.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(1).getAddress());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testCallIndex() throws Exception {
+ Message msg;
+
+ // establish the first call
+ mGSMPhone.dial("16505550100");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ String baseNumber = "1650555010";
+
+ for (int i = 1; i < 6; i++) {
+ String number = baseNumber + i;
+
+ mGSMPhone.dial(number);
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ if (mGSMPhone.getBackgroundCall().getConnections().size() >= 5) {
+ break;
+ }
+
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // create an incoming call, this call should have the call index
+ // of 7
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(PhoneConstants.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // hangup the background call and accept the ringing call
+ mGSMPhone.getBackgroundCall().hangup();
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ mGSMPhone.handleInCallMmiCommands("17");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).
+ getAddress());
+
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.handleInCallMmiCommands("16");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testPostDialSequences() throws Exception {
+ Message msg;
+ AsyncResult ar;
+ Connection cn;
+
+ mGSMPhone.dial("+13125551212,1234;5N8xx");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(',', msg.arg1);
+ assertEquals("1234;5N8", cn.getRemainingPostDialString());
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('1', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('2', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('3', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('4', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(';', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WAIT, ar.userObj);
+ cn.proceedAfterWaitChar();
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('5', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertEquals('N', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WILD, ar.userObj);
+ cn.proceedAfterWildChar(",6;7");
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(',', msg.arg1);
+ assertEquals("6;78", cn.getRemainingPostDialString());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('6', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(';', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WAIT, ar.userObj);
+ cn.proceedAfterWaitChar();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('7', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('8', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ // Bogus chars at end should be ignored
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(0, msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.COMPLETE,
+ cn.getPostDialState());
+ assertEquals(Connection.PostDialState.COMPLETE, ar.userObj);
+ }
+
+ public void testPostDialCancel() throws Exception {
+ Message msg;
+ AsyncResult ar;
+ Connection cn;
+
+ mGSMPhone.dial("+13125551212,N");
+ mRadioControl.progressConnectingToActive();
+
+ mRadioControl.progressConnectingToActive();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(',', msg.arg1);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertEquals('N', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
+ cn.cancelPostDial();
+
+ assertEquals(Connection.PostDialState.CANCELLED, cn.getPostDialState());
+ }
+
+ public void testOutgoingCallFail() throws Exception {
+ Message msg;
+ /*
+ * normal clearing
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.NORMAL_CLEARING);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ Connection cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ /*
+ * busy
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.USER_BUSY);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.BUSY, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ /*
+ * congestion
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.NO_CIRCUIT_AVAIL);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+
+ // Unlike the while loops above, this one waits
+ // for a "phone state changed" message back to "idle"
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (!(msg.what == EVENT_PHONE_STATE_CHANGED
+ && mGSMPhone.getState() == PhoneConstants.State.IDLE));
+
+ assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.CONGESTION, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ }
+
+ public void testSSNotification() throws Exception {
+ // MO
+ runTest(0, SuppServiceNotification.MO_CODE_UNCONDITIONAL_CF_ACTIVE);
+ runTest(0, SuppServiceNotification.MO_CODE_CALL_IS_WAITING);
+ runTest(0, SuppServiceNotification.MO_CODE_CALL_DEFLECTED);
+
+ // MT
+ runTest(1, SuppServiceNotification.MT_CODE_FORWARDED_CALL);
+ runTest(1, SuppServiceNotification.MT_CODE_CALL_CONNECTED_ECT);
+ runTest(1, SuppServiceNotification.MT_CODE_ADDITIONAL_CALL_FORWARDED);
+ }
+
+ private void runTest(int type, int code) {
+ Message msg;
+
+ mRadioControl.triggerSsn(type, code);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_SSN);
+ assertNotNull("Message Time Out", msg);
+ AsyncResult ar = (AsyncResult) msg.obj;
+
+ assertNull(ar.exception);
+
+ SuppServiceNotification notification =
+ (SuppServiceNotification) ar.result;
+
+ assertEquals(type, notification.notificationType);
+ assertEquals(code, notification.code);
+ }
+
+ public void testUssd() throws Exception {
+ // Quick hack to work around a race condition in this test:
+ // We may initiate a USSD MMI before GSMPhone receives its initial
+ // GSMTestHandler.EVENT_RADIO_OFF_OR_NOT_AVAILABLE event. When the phone sees this
+ // event, it will cancel the just issued USSD MMI, which we don't
+ // want. So sleep a little first.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ // do nothing
+ }
+
+ verifyNormal();
+ verifyCancel();
+ varifyNetworkInitiated();
+ }
+
+ private void varifyNetworkInitiated() {
+ Message msg;
+ AsyncResult ar;
+ MmiCode mmi;
+
+ // Receive an incoming NOTIFY
+ mRadioControl.triggerIncomingUssd("0", "NOTIFY message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertFalse(mmi.isUssdRequest());
+
+ // Receive a REQUEST and send response
+ mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertTrue(mmi.isUssdRequest());
+
+ mGSMPhone.sendUssdResponse("## TEST: TEST_GSMPhone responding...");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ GsmMmiCode gsmMmi = (GsmMmiCode) mmi;
+ assertTrue(gsmMmi.isPendingUSSD());
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertNull(ar.exception);
+ assertFalse(mmi.isUssdRequest());
+
+ // Receive a REQUEST and cancel
+ mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertTrue(mmi.isUssdRequest());
+
+ mmi.cancel();
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertNull(ar.exception);
+ assertEquals(MmiCode.State.CANCELLED, mmi.getState());
+
+ List mmiList = mGSMPhone.getPendingMmiCodes();
+ assertEquals(0, mmiList.size());
+ }
+
+ private void verifyNormal() throws CallStateException {
+ Message msg;
+ AsyncResult ar;
+ MmiCode mmi;
+
+ mGSMPhone.dial("#646#");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+ assertEquals(MmiCode.State.COMPLETE, mmi.getState());
+ }
+
+
+ private void verifyCancel() throws CallStateException {
+ /**
+ * This case makes an assumption that dial() will add the USSD
+ * to the "pending MMI codes" list before it returns. This seems
+ * like reasonable semantics. It also assumes that the USSD
+ * request in question won't complete until we get back to the
+ * event loop, thus cancel() is safe.
+ */
+ Message msg;
+
+ mGSMPhone.dial("#646#");
+
+ List<? extends MmiCode> pendingMmis = mGSMPhone.getPendingMmiCodes();
+
+ assertEquals(1, pendingMmis.size());
+
+ MmiCode mmi = pendingMmis.get(0);
+ assertTrue(mmi.isCancelable());
+ mmi.cancel();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertEquals(MmiCode.State.CANCELLED, mmi.getState());
+ }
+
+ public void testRilHooks() throws Exception {
+ //
+ // These test cases all assume the RIL OEM hooks
+ // just echo back their input
+ //
+
+ Message msg;
+ AsyncResult ar;
+
+ // null byte array
+
+ mGSMPhone.invokeOemRilRequestRaw(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertNull(ar.result);
+ assertNull(ar.exception);
+
+ // empty byte array
+
+ mGSMPhone.invokeOemRilRequestRaw(new byte[0], mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals(0, ((byte[]) (ar.result)).length);
+ assertNull(ar.exception);
+
+ // byte array with data
+
+ mGSMPhone.invokeOemRilRequestRaw("Hello".getBytes("utf-8"),
+ mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals("Hello", new String(((byte[]) (ar.result)), "utf-8"));
+ assertNull(ar.exception);
+
+ // null strings
+
+ mGSMPhone.invokeOemRilRequestStrings(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertNull(ar.result);
+ assertNull(ar.exception);
+
+ // empty byte array
+
+ mGSMPhone.invokeOemRilRequestStrings(new String[0],
+ mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals(0, ((String[]) (ar.result)).length);
+ assertNull(ar.exception);
+
+ // Strings with data
+
+ String s[] = new String[1];
+
+ s[0] = "Hello";
+
+ mGSMPhone.invokeOemRilRequestStrings(s, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals("Hello", ((String[]) (ar.result))[0]);
+ assertEquals(1, ((String[]) (ar.result)).length);
+ assertNull(ar.exception);
+ }
+
+ public void testMmi() throws Exception {
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ // "valid" MMI sequences
+ runValidMmi("*#67#", false);
+ runValidMmi("##43*11#", false);
+ runValidMmi("#33*1234*11#", false);
+ runValidMmi("*21*6505551234**5#", false);
+ runValidMmi("**03**1234*4321*4321#", false);
+ // pound string
+ runValidMmi("5308234092307540923#", true);
+ // short code
+ runValidMmi("22", true);
+ // as part of call setup
+ runValidMmiWithConnect("*31#6505551234");
+
+ // invalid MMI sequences
+ runNotMmi("6505551234");
+ runNotMmi("1234#*12#34566654");
+ runNotMmi("*#*#12#*");
+ }
+
+ private void runValidMmi(String dialString, boolean cancelable) throws CallStateException {
+ Connection c = mGSMPhone.dial(dialString);
+ assertNull(c);
+ Message msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+ // Should not be cancelable.
+ AsyncResult ar = (AsyncResult) msg.obj;
+ MmiCode mmi = (MmiCode) ar.result;
+ assertEquals(cancelable, mmi.isCancelable());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ }
+
+ private void runValidMmiWithConnect(String dialString) throws CallStateException {
+ mRadioControl.pauseResponses();
+
+ Connection c = mGSMPhone.dial(dialString);
+ assertNotNull(c);
+
+ hangup(c);
+ }
+
+ private void hangup(Connection cn) throws CallStateException {
+ cn.hangup();
+
+ mRadioControl.resumeResponses();
+ assertNotNull(mGSMTestHandler.waitForMessage(EVENT_DISCONNECT));
+
+ }
+
+ private void runNotMmi(String dialString) throws CallStateException {
+ mRadioControl.pauseResponses();
+
+ Connection c = mGSMPhone.dial(dialString);
+ assertNotNull(c);
+
+ hangup(c);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java
new file mode 100644
index 0000000..fb8a5d9
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.content.Context;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.TestPhoneNotifier;
+
+/**
+ * This class creates a HandlerThread which waits for the various messages.
+ */
+public class GSMTestHandler extends HandlerThread implements Handler.Callback {
+
+ private Handler mHandler;
+ private Message mCurrentMessage;
+
+ private Boolean mMsgConsumed;
+ private SimulatedCommands sc;
+ private GSMPhone mGSMPhone;
+ private Context mContext;
+
+ private static final int FAIL_TIMEOUT_MILLIS = 5 * 1000;
+
+ public GSMTestHandler(Context context) {
+ super("GSMPhoneTest");
+ mMsgConsumed = false;
+ mContext = context;
+ }
+
+ @Override
+ protected void onLooperPrepared() {
+ sc = new SimulatedCommands();
+ mGSMPhone = new GSMPhone(mContext, sc, new TestPhoneNotifier(), true);
+ mHandler = new Handler(getLooper(), this);
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+ public boolean handleMessage(Message msg) {
+ synchronized (this) {
+ mCurrentMessage = msg;
+ this.notifyAll();
+ while(!mMsgConsumed) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {}
+ }
+ mMsgConsumed = false;
+ }
+ return true;
+ }
+
+
+ public void cleanup() {
+ Looper looper = getLooper();
+ if (looper != null) looper.quit();
+ mHandler = null;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public SimulatedCommands getSimulatedCommands() {
+ return sc;
+ }
+
+ public GSMPhone getGSMPhone() {
+ return mGSMPhone;
+ }
+
+ public Message waitForMessage(int code) {
+ Message msg;
+ while(true) {
+ msg = null;
+ synchronized (this) {
+ try {
+ this.wait(FAIL_TIMEOUT_MILLIS);
+ } catch (InterruptedException e) {
+ }
+
+ // Check if timeout has occurred.
+ if (mCurrentMessage != null) {
+ // Consume the message
+ msg = Message.obtain();
+ msg.copyFrom(mCurrentMessage);
+ mCurrentMessage = null;
+ mMsgConsumed = true;
+ this.notifyAll();
+ }
+ }
+ if (msg == null || code == GSMPhoneTest.ANY_MESSAGE || msg.what == code) return msg;
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java
new file mode 100644
index 0000000..82c6944
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.telephony.SmsCbEtwsInfo;
+import android.telephony.SmsCbLocation;
+import android.telephony.SmsCbMessage;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.internal.telephony.IccUtils;
+
+import java.util.Random;
+
+/**
+ * Test cases for basic SmsCbMessage operations
+ */
+public class GsmSmsCbTest extends AndroidTestCase {
+
+ private static final String TAG = "GsmSmsCbTest";
+
+ private static final SmsCbLocation sTestLocation = new SmsCbLocation("94040", 1234, 5678);
+
+ private static SmsCbMessage createFromPdu(byte[] pdu) {
+ try {
+ SmsCbHeader header = new SmsCbHeader(pdu);
+ byte[][] pdus = new byte[1][];
+ pdus[0] = pdu;
+ return GsmSmsCbMessage.createSmsCbMessage(header, sTestLocation, pdus);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ private static void doTestGeographicalScopeValue(byte[] pdu, byte b, int expectedGs) {
+ pdu[0] = b;
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected geographical scope decoded", expectedGs, msg
+ .getGeographicalScope());
+ }
+
+ public void testCreateNullPdu() {
+ SmsCbMessage msg = createFromPdu(null);
+ assertNull("createFromPdu(byte[] with null pdu should return null", msg);
+ }
+
+ public void testCreateTooShortPdu() {
+ byte[] pdu = new byte[4];
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertNull("createFromPdu(byte[] with too short pdu should return null", msg);
+ }
+
+ public void testGetGeographicalScope() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
+ (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
+ (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
+ (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+
+ doTestGeographicalScopeValue(pdu, (byte)0x00,
+ SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE);
+ doTestGeographicalScopeValue(pdu, (byte)0x40, SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE);
+ doTestGeographicalScopeValue(pdu, (byte)0x80, SmsCbMessage.GEOGRAPHICAL_SCOPE_LA_WIDE);
+ doTestGeographicalScopeValue(pdu, (byte)0xC0, SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE);
+ }
+
+ public void testGetGeographicalScopeUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
+
+ (byte)0x01,
+
+ (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
+ (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
+ (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
+ (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
+ (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
+ (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
+ (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
+ (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x34
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected geographical scope decoded",
+ SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE, msg.getGeographicalScope());
+ }
+
+ public void testGetMessageBody7Bit() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
+ (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
+ (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
+ (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A GSM default alphabet message with carriage return padding",
+ msg.getMessageBody());
+ }
+
+ public void testGetMessageBody7BitUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
+
+ (byte)0x01,
+
+ (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
+ (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
+ (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
+ (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
+ (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
+ (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
+ (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
+ (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x34
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A GSM default alphabet message with carriage return padding",
+ msg.getMessageBody());
+ }
+
+ public void testGetMessageBody7BitMultipageUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x40,
+
+ (byte)0x02,
+
+ (byte)0xC6, (byte)0xB4, (byte)0x7C, (byte)0x4E, (byte)0x07, (byte)0xC1,
+ (byte)0xC3, (byte)0xE7, (byte)0xF2, (byte)0xAA, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A,
+ (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34,
+ (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x0A,
+
+ (byte)0xD3, (byte)0xF2, (byte)0xF8, (byte)0xED, (byte)0x26, (byte)0x83,
+ (byte)0xE0, (byte)0xE1, (byte)0x73, (byte)0xB9, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A,
+ (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34,
+ (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x0A
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected multipage 7-bit string decoded",
+ "First page+Second page",
+ msg.getMessageBody());
+ }
+
+ public void testGetMessageBody7BitFull() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xC4, (byte)0xE5,
+ (byte)0xB4, (byte)0xFB, (byte)0x0C, (byte)0x2A, (byte)0xE3, (byte)0xC3, (byte)0x63,
+ (byte)0x3A, (byte)0x3B, (byte)0x0F, (byte)0xCA, (byte)0xCD, (byte)0x40, (byte)0x63,
+ (byte)0x74, (byte)0x58, (byte)0x1E, (byte)0x1E, (byte)0xD3, (byte)0xCB, (byte)0xF2,
+ (byte)0x39, (byte)0x88, (byte)0xFD, (byte)0x76, (byte)0x9F, (byte)0x59, (byte)0xA0,
+ (byte)0x76, (byte)0x39, (byte)0xEC, (byte)0x4E, (byte)0xBB, (byte)0xCF, (byte)0x20,
+ (byte)0x3A, (byte)0xBA, (byte)0x2C, (byte)0x2F, (byte)0x83, (byte)0xD2, (byte)0x73,
+ (byte)0x90, (byte)0xFB, (byte)0x0D, (byte)0x82, (byte)0x87, (byte)0xC9, (byte)0xE4,
+ (byte)0xB4, (byte)0xFB, (byte)0x1C, (byte)0x02
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals(
+ "Unexpected 7-bit string decoded",
+ "A GSM default alphabet message being exactly 93 characters long, " +
+ "meaning there is no padding!",
+ msg.getMessageBody());
+ }
+
+ public void testGetMessageBody7BitFullUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
+
+ (byte)0x01,
+
+ (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
+ (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
+ (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
+ (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
+ (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xC4, (byte)0xE5, (byte)0xB4,
+ (byte)0xFB, (byte)0x0C, (byte)0x2A, (byte)0xE3, (byte)0xC3, (byte)0x63,
+ (byte)0x3A, (byte)0x3B, (byte)0x0F, (byte)0xCA, (byte)0xCD, (byte)0x40,
+ (byte)0x63, (byte)0x74, (byte)0x58, (byte)0x1E, (byte)0x1E, (byte)0xD3,
+ (byte)0xCB, (byte)0xF2, (byte)0x39, (byte)0x88, (byte)0xFD, (byte)0x76,
+ (byte)0x9F, (byte)0x59, (byte)0xA0, (byte)0x76, (byte)0x39, (byte)0xEC,
+ (byte)0x4E, (byte)0xBB, (byte)0xCF, (byte)0x20, (byte)0x3A, (byte)0xBA,
+ (byte)0x2C, (byte)0x2F, (byte)0x83, (byte)0xD2, (byte)0x73, (byte)0x90,
+ (byte)0xFB, (byte)0x0D, (byte)0x82, (byte)0x87, (byte)0xC9, (byte)0xE4,
+ (byte)0xB4, (byte)0xFB, (byte)0x1C, (byte)0x02,
+
+ (byte)0x52
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals(
+ "Unexpected 7-bit string decoded",
+ "A GSM default alphabet message being exactly 93 characters long, " +
+ "meaning there is no padding!",
+ msg.getMessageBody());
+ }
+
+ public void testGetMessageBody7BitWithLanguage() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x04, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
+ (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
+ (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
+ (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A GSM default alphabet message with carriage return padding",
+ msg.getMessageBody());
+
+ assertEquals("Unexpected language indicator decoded", "es", msg.getLanguageCode());
+ }
+
+ public void testGetMessageBody7BitWithLanguageInBody() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x10, (byte)0x11, (byte)0x73,
+ (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E, (byte)0x9B, (byte)0x20,
+ (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE, (byte)0xB3, (byte)0xE9, (byte)0xA0,
+ (byte)0x30, (byte)0x1B, (byte)0x8E, (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74,
+ (byte)0x50, (byte)0xBB, (byte)0x3C, (byte)0x9F, (byte)0x87, (byte)0xCF, (byte)0x65,
+ (byte)0xD0, (byte)0x3D, (byte)0x4D, (byte)0x47, (byte)0x83, (byte)0xC6, (byte)0x61,
+ (byte)0xB9, (byte)0x3C, (byte)0x1D, (byte)0x3E, (byte)0x97, (byte)0x41, (byte)0xF2,
+ (byte)0x32, (byte)0xBD, (byte)0x2E, (byte)0x77, (byte)0x83, (byte)0xE0, (byte)0x61,
+ (byte)0x32, (byte)0x39, (byte)0xED, (byte)0x3E, (byte)0x37, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A GSM default alphabet message with carriage return padding",
+ msg.getMessageBody());
+
+ assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode());
+ }
+
+ public void testGetMessageBody7BitWithLanguageInBodyUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x10,
+
+ (byte)0x01,
+
+ (byte)0x73, (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E,
+ (byte)0x9B, (byte)0x20, (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE,
+ (byte)0xB3, (byte)0xE9, (byte)0xA0, (byte)0x30, (byte)0x1B, (byte)0x8E,
+ (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74, (byte)0x50, (byte)0xBB,
+ (byte)0x3C, (byte)0x9F, (byte)0x87, (byte)0xCF, (byte)0x65, (byte)0xD0,
+ (byte)0x3D, (byte)0x4D, (byte)0x47, (byte)0x83, (byte)0xC6, (byte)0x61,
+ (byte)0xB9, (byte)0x3C, (byte)0x1D, (byte)0x3E, (byte)0x97, (byte)0x41,
+ (byte)0xF2, (byte)0x32, (byte)0xBD, (byte)0x2E, (byte)0x77, (byte)0x83,
+ (byte)0xE0, (byte)0x61, (byte)0x32, (byte)0x39, (byte)0xED, (byte)0x3E,
+ (byte)0x37, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x37
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A GSM default alphabet message with carriage return padding",
+ msg.getMessageBody());
+
+ assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode());
+ }
+
+ public void testGetMessageBody8Bit() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x44, (byte)0x11, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
+ (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("8-bit message body should be empty", "", msg.getMessageBody());
+ }
+
+ public void testGetMessageBodyUcs2() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x48, (byte)0x11, (byte)0x00,
+ (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43,
+ (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00,
+ (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73,
+ (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, (byte)0x00,
+ (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, (byte)0x00, (byte)0x6E,
+ (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x69, (byte)0x00,
+ (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x67,
+ (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x20, (byte)0x04,
+ (byte)0x34, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68,
+ (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, (byte)0x00,
+ (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x72,
+ (byte)0x00, (byte)0x0D, (byte)0x00, (byte)0x0D
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A UCS2 message containing a \u0434 character", msg.getMessageBody());
+ }
+
+ public void testGetMessageBodyUcs2Umts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48,
+
+ (byte)0x01,
+
+ (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55,
+ (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32,
+ (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65,
+ (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x61,
+ (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x20,
+ (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, (byte)0x00, (byte)0x6E,
+ (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x69,
+ (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E,
+ (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61,
+ (byte)0x00, (byte)0x20, (byte)0x04, (byte)0x34, (byte)0x00, (byte)0x20,
+ (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68, (byte)0x00, (byte)0x61,
+ (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x63,
+ (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x72,
+ (byte)0x00, (byte)0x0D, (byte)0x00, (byte)0x0D,
+
+ (byte)0x4E
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A UCS2 message containing a \u0434 character", msg.getMessageBody());
+ }
+
+ public void testGetMessageBodyUcs2MultipageUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48,
+
+ (byte)0x02,
+
+ (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x41,
+ (byte)0x00, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+
+ (byte)0x06,
+
+ (byte)0x00, (byte)0x42, (byte)0x00, (byte)0x42, (byte)0x00, (byte)0x42,
+ (byte)0x00, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+ (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
+
+ (byte)0x06
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected multipage UCS2 string decoded",
+ "AAABBB", msg.getMessageBody());
+ }
+
+ public void testGetMessageBodyUcs2WithLanguageInBody() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x11, (byte)0x11, (byte)0x78,
+ (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55,
+ (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00,
+ (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73,
+ (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00,
+ (byte)0x65, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F,
+ (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00,
+ (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E,
+ (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, (byte)0x00,
+ (byte)0x20, (byte)0x04, (byte)0x34, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63,
+ (byte)0x00, (byte)0x68, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00,
+ (byte)0x61, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65,
+ (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x0D
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A UCS2 message containing a \u0434 character", msg.getMessageBody());
+
+ assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
+ }
+
+ public void testGetMessageBodyUcs2WithLanguageInBodyUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x11,
+
+ (byte)0x01,
+
+ (byte)0x78, (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20,
+ (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53,
+ (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x6D,
+ (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73,
+ (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65,
+ (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F,
+ (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61,
+ (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69,
+ (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20,
+ (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x20, (byte)0x04, (byte)0x34,
+ (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68,
+ (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61,
+ (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65,
+ (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x0D,
+
+ (byte)0x50
+ };
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected 7-bit string decoded",
+ "A UCS2 message containing a \u0434 character", msg.getMessageBody());
+
+ assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
+ }
+
+ public void testGetMessageIdentifier() {
+ byte[] pdu = {
+ (byte)0xC0, (byte)0x00, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
+ (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
+ (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
+ (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected message identifier decoded", 12345, msg.getServiceCategory());
+ }
+
+ public void testGetMessageIdentifierUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40,
+
+ (byte)0x01,
+
+ (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
+ (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
+ (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
+ (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
+ (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
+ (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
+ (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
+ (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x34
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+
+ assertEquals("Unexpected message identifier decoded", 12345, msg.getServiceCategory());
+ }
+
+ public void testGetMessageCode() {
+ byte[] pdu = {
+ (byte)0x2A, (byte)0xA5, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
+ (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
+ (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
+ (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+ int messageCode = (msg.getSerialNumber() & 0x3ff0) >> 4;
+
+ assertEquals("Unexpected message code decoded", 682, messageCode);
+ }
+
+ public void testGetMessageCodeUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40,
+
+ (byte)0x01,
+
+ (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
+ (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
+ (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
+ (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
+ (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
+ (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
+ (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
+ (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x34
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+ int messageCode = (msg.getSerialNumber() & 0x3ff0) >> 4;
+
+ assertEquals("Unexpected message code decoded", 682, messageCode);
+ }
+
+ public void testGetUpdateNumber() {
+ byte[] pdu = {
+ (byte)0x2A, (byte)0xA5, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41,
+ (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
+ (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
+ (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
+ (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
+ (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
+ (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
+ (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+ int updateNumber = msg.getSerialNumber() & 0x000f;
+
+ assertEquals("Unexpected update number decoded", 5, updateNumber);
+ }
+
+ public void testGetUpdateNumberUmts() {
+ byte[] pdu = {
+ (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40,
+
+ (byte)0x01,
+
+ (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
+ (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
+ (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
+ (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
+ (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
+ (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
+ (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
+ (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
+ (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
+ (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
+ (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
+ (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
+ (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
+ (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
+
+ (byte)0x34
+ };
+
+ SmsCbMessage msg = createFromPdu(pdu);
+ int updateNumber = msg.getSerialNumber() & 0x000f;
+
+ assertEquals("Unexpected update number decoded", 5, updateNumber);
+ }
+
+ /* ETWS Test message including header */
+ private static final byte[] etwsMessageNormal = IccUtils.hexStringToBytes("000011001101" +
+ "0D0A5BAE57CE770C531790E85C716CBF3044573065B930675730" +
+ "9707767A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09" +
+ "0000000000000000000000000000");
+
+ private static final byte[] etwsMessageCancel = IccUtils.hexStringToBytes("000011001101" +
+ "0D0A5148307B3069002800310030003A0035" +
+ "00320029306E7DCA602557309707901F5831309253D66D883057307E3059FF086C178C615E81FF09" +
+ "00000000000000000000000000000000000000000000");
+
+ private static final byte[] etwsMessageTest = IccUtils.hexStringToBytes("000011031101" +
+ "0D0A5BAE57CE770C531790E85C716CBF3044" +
+ "573065B9306757309707300263FA308C306B5099304830664E0B30553044FF086C178C615E81FF09" +
+ "00000000000000000000000000000000000000000000");
+
+ // FIXME: add example of ETWS primary notification PDU
+
+ public void testEtwsMessageNormal() {
+ SmsCbMessage msg = createFromPdu(etwsMessageNormal);
+ Log.d(TAG, msg.toString());
+ assertEquals("GS mismatch", 0, msg.getGeographicalScope());
+ assertEquals("serial number mismatch", 0, msg.getSerialNumber());
+ assertEquals("message ID mismatch", 0x1100, msg.getServiceCategory());
+ assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE,
+ msg.getEtwsWarningInfo().getWarningType());
+ }
+
+ public void testEtwsMessageCancel() {
+ SmsCbMessage msg = createFromPdu(etwsMessageCancel);
+ Log.d(TAG, msg.toString());
+ assertEquals("GS mismatch", 0, msg.getGeographicalScope());
+ assertEquals("serial number mismatch", 0, msg.getSerialNumber());
+ assertEquals("message ID mismatch", 0x1100, msg.getServiceCategory());
+ assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE,
+ msg.getEtwsWarningInfo().getWarningType());
+ }
+
+ public void testEtwsMessageTest() {
+ SmsCbMessage msg = createFromPdu(etwsMessageTest);
+ Log.d(TAG, msg.toString());
+ assertEquals("GS mismatch", 0, msg.getGeographicalScope());
+ assertEquals("serial number mismatch", 0, msg.getSerialNumber());
+ assertEquals("message ID mismatch", 0x1103, msg.getServiceCategory());
+ assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE,
+ msg.getEtwsWarningInfo().getWarningType());
+ }
+
+ // Make sure we don't throw an exception if we feed random data to the PDU parser.
+ public void testRandomPdus() {
+ Random r = new Random(94040);
+ for (int run = 0; run < 10000; run++) {
+ int len = r.nextInt(140);
+ byte[] data = new byte[len];
+ for (int i = 0; i < len; i++) {
+ data[i] = (byte) r.nextInt(256);
+ }
+ try {
+ // this should return a SmsCbMessage object or null for invalid data
+ SmsCbMessage msg = createFromPdu(data);
+ } catch (Exception e) {
+ Log.d(TAG, "exception thrown", e);
+ fail("Exception in decoder at run " + run + " length " + len + ": " + e);
+ }
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
new file mode 100644
index 0000000..ea6836d
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.IccIoResult;
+import com.android.internal.telephony.UUSInfo;
+
+import junit.framework.Assert;
+
+/**
+ * Dummy BaseCommands for UsimDataDownloadTest. Only implements UICC envelope and
+ * SMS acknowledgement commands.
+ */
+class UsimDataDownloadCommands extends BaseCommands {
+ private static final String TAG = "UsimDataDownloadCommands";
+
+ private boolean mExpectingAcknowledgeGsmSms; // true if expecting ack GSM SMS
+ private boolean mExpectingAcknowledgeGsmSmsSuccess; // true if expecting ack SMS success
+ private int mExpectingAcknowledgeGsmSmsFailureCause; // expecting ack SMS failure cause
+ private String mExpectingAcknowledgeGsmSmsPdu; // expecting ack SMS PDU
+
+ private boolean mExpectingSendEnvelope; // true to expect a send envelope command
+ private String mExpectingSendEnvelopeContents; // expected string for send envelope
+ private int mExpectingSendEnvelopeResponseSw1; // SW1/SW2 response status
+ private int mExpectingSendEnvelopeResponseSw2; // SW1/SW2 response status
+ private String mExpectingSendEnvelopeResponse; // Response string for Send Envelope
+
+ UsimDataDownloadCommands(Context context) {
+ super(context);
+ }
+
+ /**
+ * Expect a call to acknowledgeLastIncomingGsmSms with success flag and failure cause.
+ * @param success true if expecting success; false if expecting failure
+ * @param cause the failure cause, if success is false
+ */
+ synchronized void expectAcknowledgeGsmSms(boolean success, int cause) {
+ Assert.assertFalse("expectAcknowledgeGsmSms called twice", mExpectingAcknowledgeGsmSms);
+ mExpectingAcknowledgeGsmSms = true;
+ mExpectingAcknowledgeGsmSmsSuccess = success;
+ mExpectingAcknowledgeGsmSmsFailureCause = cause;
+ }
+
+ /**
+ * Expect a call to acknowledgeLastIncomingGsmSmsWithPdu with success flag and PDU.
+ * @param success true if expecting success; false if expecting failure
+ * @param ackPdu the acknowledgement PDU to expect
+ */
+ synchronized void expectAcknowledgeGsmSmsWithPdu(boolean success, String ackPdu) {
+ Assert.assertFalse("expectAcknowledgeGsmSms called twice", mExpectingAcknowledgeGsmSms);
+ mExpectingAcknowledgeGsmSms = true;
+ mExpectingAcknowledgeGsmSmsSuccess = success;
+ mExpectingAcknowledgeGsmSmsPdu = ackPdu;
+ }
+
+ /**
+ * Expect a call to sendEnvelopeWithStatus().
+ * @param contents expected envelope contents to send
+ * @param sw1 simulated SW1 status to return
+ * @param sw2 simulated SW2 status to return
+ * @param response simulated envelope response to return
+ */
+ synchronized void expectSendEnvelope(String contents, int sw1, int sw2, String response) {
+ Assert.assertFalse("expectSendEnvelope called twice", mExpectingSendEnvelope);
+ mExpectingSendEnvelope = true;
+ mExpectingSendEnvelopeContents = contents;
+ mExpectingSendEnvelopeResponseSw1 = sw1;
+ mExpectingSendEnvelopeResponseSw2 = sw2;
+ mExpectingSendEnvelopeResponse = response;
+ }
+
+ synchronized void assertExpectedMethodsCalled() {
+ long stopTime = SystemClock.elapsedRealtime() + 5000;
+ while ((mExpectingAcknowledgeGsmSms || mExpectingSendEnvelope)
+ && SystemClock.elapsedRealtime() < stopTime) {
+ try {
+ wait();
+ } catch (InterruptedException ignored) {}
+ }
+ Assert.assertFalse("expecting SMS acknowledge call", mExpectingAcknowledgeGsmSms);
+ Assert.assertFalse("expecting send envelope call", mExpectingSendEnvelope);
+ }
+
+ @Override
+ public synchronized void acknowledgeLastIncomingGsmSms(boolean success, int cause,
+ Message response) {
+ Log.d(TAG, "acknowledgeLastIncomingGsmSms: success=" + success + ", cause=" + cause);
+ Assert.assertTrue("unexpected call to acknowledge SMS", mExpectingAcknowledgeGsmSms);
+ Assert.assertEquals(mExpectingAcknowledgeGsmSmsSuccess, success);
+ Assert.assertEquals(mExpectingAcknowledgeGsmSmsFailureCause, cause);
+ mExpectingAcknowledgeGsmSms = false;
+ if (response != null) {
+ AsyncResult.forMessage(response);
+ response.sendToTarget();
+ }
+ notifyAll(); // wake up assertExpectedMethodsCalled()
+ }
+
+ @Override
+ public synchronized void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu,
+ Message response) {
+ Log.d(TAG, "acknowledgeLastIncomingGsmSmsWithPdu: success=" + success
+ + ", ackPDU= " + ackPdu);
+ Assert.assertTrue("unexpected call to acknowledge SMS", mExpectingAcknowledgeGsmSms);
+ Assert.assertEquals(mExpectingAcknowledgeGsmSmsSuccess, success);
+ Assert.assertEquals(mExpectingAcknowledgeGsmSmsPdu, ackPdu);
+ mExpectingAcknowledgeGsmSms = false;
+ if (response != null) {
+ AsyncResult.forMessage(response);
+ response.sendToTarget();
+ }
+ notifyAll(); // wake up assertExpectedMethodsCalled()
+ }
+
+ @Override
+ public synchronized void sendEnvelopeWithStatus(String contents, Message response) {
+ // Add spaces between hex bytes for readability
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < contents.length(); i += 2) {
+ builder.append(contents.charAt(i)).append(contents.charAt(i+1)).append(' ');
+ }
+ Log.d(TAG, "sendEnvelopeWithStatus: " + builder.toString());
+
+ Assert.assertTrue("unexpected call to send envelope", mExpectingSendEnvelope);
+ Assert.assertEquals(mExpectingSendEnvelopeContents, contents);
+ mExpectingSendEnvelope = false;
+
+ IccIoResult result = new IccIoResult(mExpectingSendEnvelopeResponseSw1,
+ mExpectingSendEnvelopeResponseSw2, mExpectingSendEnvelopeResponse);
+
+ if (response != null) {
+ AsyncResult.forMessage(response, result, null);
+ response.sendToTarget();
+ }
+ notifyAll(); // wake up assertExpectedMethodsCalled()
+ }
+
+ @Override
+ public void setSuppServiceNotifications(boolean enable, Message result) {
+ }
+
+ @Override
+ public void supplyIccPin(String pin, Message result) {
+ }
+
+ @Override
+ public void supplyIccPinForApp(String pin, String aid, Message result) {
+ }
+
+ @Override
+ public void supplyIccPuk(String puk, String newPin, Message result) {
+ }
+
+ @Override
+ public void supplyIccPukForApp(String puk, String newPin, String aid, Message result) {
+ }
+
+ @Override
+ public void supplyIccPin2(String pin2, Message result) {
+ }
+
+ @Override
+ public void supplyIccPin2ForApp(String pin2, String aid, Message result) {
+ }
+
+ @Override
+ public void supplyIccPuk2(String puk2, String newPin2, Message result) {
+ }
+
+ @Override
+ public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message result) {
+ }
+
+ @Override
+ public void changeIccPin(String oldPin, String newPin, Message result) {
+ }
+
+ @Override
+ public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message result) {
+ }
+
+ @Override
+ public void changeIccPin2(String oldPin2, String newPin2, Message result) {
+ }
+
+ @Override
+ public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr, Message result) {
+ }
+
+ @Override
+ public void changeBarringPassword(String facility, String oldPwd, String newPwd,
+ Message result) {
+ }
+
+ @Override
+ public void supplyNetworkDepersonalization(String netpin, Message result) {
+ }
+
+ @Override
+ public void getCurrentCalls(Message result) {
+ }
+
+ @Override
+ public void getPDPContextList(Message result) {
+ }
+
+ @Override
+ public void getDataCallList(Message result) {
+ }
+
+ @Override
+ public void dial(String address, int clirMode, Message result) {
+ }
+
+ @Override
+ public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
+ }
+
+ @Override
+ public void getIMSI(Message result) {
+ }
+
+ @Override
+ public void getIMEI(Message result) {
+ }
+
+ @Override
+ public void getIMEISV(Message result) {
+ }
+
+ @Override
+ public void hangupConnection(int gsmIndex, Message result) {
+ }
+
+ @Override
+ public void hangupWaitingOrBackground(Message result) {
+ }
+
+ @Override
+ public void hangupForegroundResumeBackground(Message result) {
+ }
+
+ @Override
+ public void switchWaitingOrHoldingAndActive(Message result) {
+ }
+
+ @Override
+ public void conference(Message result) {
+ }
+
+ @Override
+ public void setPreferredVoicePrivacy(boolean enable, Message result) {
+ }
+
+ @Override
+ public void getPreferredVoicePrivacy(Message result) {
+ }
+
+ @Override
+ public void separateConnection(int gsmIndex, Message result) {
+ }
+
+ @Override
+ public void acceptCall(Message result) {
+ }
+
+ @Override
+ public void rejectCall(Message result) {
+ }
+
+ @Override
+ public void explicitCallTransfer(Message result) {
+ }
+
+ @Override
+ public void getLastCallFailCause(Message result) {
+ }
+
+ @Override
+ public void getLastPdpFailCause(Message result) {
+ }
+
+ @Override
+ public void getLastDataCallFailCause(Message result) {
+ }
+
+ @Override
+ public void setMute(boolean enableMute, Message response) {
+ }
+
+ @Override
+ public void getMute(Message response) {
+ }
+
+ @Override
+ public void getSignalStrength(Message response) {
+ }
+
+ @Override
+ public void getVoiceRegistrationState(Message response) {
+ }
+
+ @Override
+ public void getDataRegistrationState(Message response) {
+ }
+
+ @Override
+ public void getOperator(Message response) {
+ }
+
+ @Override
+ public void sendDtmf(char c, Message result) {
+ }
+
+ @Override
+ public void startDtmf(char c, Message result) {
+ }
+
+ @Override
+ public void stopDtmf(Message result) {
+ }
+
+ @Override
+ public void sendBurstDtmf(String dtmfString, int on, int off, Message result) {
+ }
+
+ @Override
+ public void sendSMS(String smscPDU, String pdu, Message response) {
+ }
+
+ @Override
+ public void sendCdmaSms(byte[] pdu, Message response) {
+ }
+
+ @Override
+ public void deleteSmsOnSim(int index, Message response) {
+ }
+
+ @Override
+ public void deleteSmsOnRuim(int index, Message response) {
+ }
+
+ @Override
+ public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
+ }
+
+ @Override
+ public void writeSmsToRuim(int status, String pdu, Message response) {
+ }
+
+ @Override
+ public void setRadioPower(boolean on, Message response) {
+ }
+
+ @Override
+ public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message response) {
+ }
+
+ @Override
+ public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data,
+ String pin2, Message response) {
+ }
+
+ @Override
+ public void queryCLIP(Message response) {
+ }
+
+ @Override
+ public void getCLIR(Message response) {
+ }
+
+ @Override
+ public void setCLIR(int clirMode, Message response) {
+ }
+
+ @Override
+ public void queryCallWaiting(int serviceClass, Message response) {
+ }
+
+ @Override
+ public void setCallWaiting(boolean enable, int serviceClass, Message response) {
+ }
+
+ @Override
+ public void setCallForward(int action, int cfReason, int serviceClass, String number,
+ int timeSeconds, Message response) {
+ }
+
+ @Override
+ public void queryCallForwardStatus(int cfReason, int serviceClass, String number,
+ Message response) {
+ }
+
+ @Override
+ public void setNetworkSelectionModeAutomatic(Message response) {
+ }
+
+ @Override
+ public void setNetworkSelectionModeManual(String operatorNumeric, Message response) {
+ }
+
+ @Override
+ public void getNetworkSelectionMode(Message response) {
+ }
+
+ @Override
+ public void getAvailableNetworks(Message response) {
+ }
+
+ @Override
+ public void getBasebandVersion(Message response) {
+ }
+
+ @Override
+ public void queryFacilityLock(String facility, String password, int serviceClass,
+ Message response) {
+ }
+
+ @Override
+ public void queryFacilityLockForApp(String facility, String password, int serviceClass,
+ String appId, Message response) {
+ }
+
+ @Override
+ public void setFacilityLock(String facility, boolean lockState, String password,
+ int serviceClass, Message response) {
+ }
+
+ @Override
+ public void setFacilityLockForApp(String facility, boolean lockState, String password,
+ int serviceClass, String appId, Message response) {
+ }
+
+ @Override
+ public void sendUSSD(String ussdString, Message response) {
+ }
+
+ @Override
+ public void cancelPendingUssd(Message response) {
+ }
+
+ @Override
+ public void resetRadio(Message result) {
+ }
+
+ @Override
+ public void setBandMode(int bandMode, Message response) {
+ }
+
+ @Override
+ public void queryAvailableBandMode(Message response) {
+ }
+
+ @Override
+ public void setPreferredNetworkType(int networkType, Message response) {
+ }
+
+ @Override
+ public void getPreferredNetworkType(Message response) {
+ }
+
+ @Override
+ public void getNeighboringCids(Message response) {
+ }
+
+ @Override
+ public void setLocationUpdates(boolean enable, Message response) {
+ }
+
+ @Override
+ public void getSmscAddress(Message result) {
+ }
+
+ @Override
+ public void setSmscAddress(String address, Message result) {
+ }
+
+ @Override
+ public void reportSmsMemoryStatus(boolean available, Message result) {
+ }
+
+ @Override
+ public void reportStkServiceIsRunning(Message result) {
+ }
+
+ @Override
+ public void invokeOemRilRequestRaw(byte[] data, Message response) {
+ }
+
+ @Override
+ public void invokeOemRilRequestStrings(String[] strings, Message response) {
+ }
+
+ @Override
+ public void sendTerminalResponse(String contents, Message response) {
+ }
+
+ @Override
+ public void sendEnvelope(String contents, Message response) {
+ }
+
+ @Override
+ public void handleCallSetupRequestFromSim(boolean accept, Message response) {
+ }
+
+ @Override
+ public void setGsmBroadcastActivation(boolean activate, Message result) {
+ }
+
+ @Override
+ public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) {
+ }
+
+ @Override
+ public void getGsmBroadcastConfig(Message response) {
+ }
+
+ @Override
+ public void getDeviceIdentity(Message response) {
+ }
+
+ @Override
+ public void getCDMASubscription(Message response) {
+ }
+
+ @Override
+ public void sendCDMAFeatureCode(String FeatureCode, Message response) {
+ }
+
+ @Override
+ public void setPhoneType(int phoneType) {
+ }
+
+ @Override
+ public void queryCdmaRoamingPreference(Message response) {
+ }
+
+ @Override
+ public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+ }
+
+ @Override
+ public void setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) {
+ }
+
+ @Override
+ public void getCdmaSubscriptionSource(Message response) {
+ }
+
+ @Override
+ public void setTTYMode(int ttyMode, Message response) {
+ }
+
+ @Override
+ public void queryTTYMode(Message response) {
+ }
+
+ @Override
+ public void setupDataCall(String radioTechnology, String profile, String apn, String user,
+ String password, String authType, String protocol, Message result) {
+ }
+
+ @Override
+ public void deactivateDataCall(int cid, int reason, Message result) {
+ }
+
+ @Override
+ public void setCdmaBroadcastActivation(boolean activate, Message result) {
+ }
+
+ @Override
+ public void setCdmaBroadcastConfig(int[] configValuesArray, Message result) {
+ }
+
+ @Override
+ public void getCdmaBroadcastConfig(Message result) {
+ }
+
+ @Override
+ public void exitEmergencyCallbackMode(Message response) {
+ }
+
+ @Override
+ public void getIccCardStatus(Message result) {
+ }
+
+ @Override
+ public void requestIsimAuthentication(String nonce, Message response) {
+ }
+
+ @Override
+ public void getVoiceRadioTechnology(Message response) {
+ }
+
+ @Override
+ public void getIMSIForApp(String aid, Message result) {
+ }
+
+ @Override
+ public void iccIOForApp(int command, int fileid, String path, int p1, int p2, int p3,
+ String data, String pin2, String aid, Message response) {
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java
new file mode 100644
index 0000000..6c8ba5e
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.os.HandlerThread;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.nio.charset.Charset;
+
+/**
+ * Test SMS-PP data download to UICC.
+ * Uses test messages from 3GPP TS 31.124 section 27.22.5.
+ */
+public class UsimDataDownloadTest extends AndroidTestCase {
+ private static final String TAG = "UsimDataDownloadTest";
+
+ class TestHandlerThread extends HandlerThread {
+ private UsimDataDownloadHandler mHandler;
+
+ TestHandlerThread() {
+ super("TestHandlerThread");
+ }
+
+ @Override
+ protected void onLooperPrepared() {
+ synchronized (this) {
+ mHandler = new UsimDataDownloadHandler(mCm);
+ notifyAll();
+ }
+ }
+
+ UsimDataDownloadHandler getHandler() {
+ synchronized (this) {
+ while (mHandler == null) {
+ try {
+ wait();
+ } catch (InterruptedException ignored) {}
+ }
+ return mHandler;
+ }
+ }
+ }
+
+ private UsimDataDownloadCommands mCm;
+ private TestHandlerThread mHandlerThread;
+ UsimDataDownloadHandler mHandler;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mCm = new UsimDataDownloadCommands(mContext);
+ mHandlerThread = new TestHandlerThread();
+ mHandlerThread.start();
+ mHandler = mHandlerThread.getHandler();
+ Log.d(TAG, "mHandler is constructed");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mHandlerThread.quit();
+ super.tearDown();
+ }
+
+ // SMS-PP Message 3.1.1
+ private static final byte[] SMS_PP_MESSAGE_3_1_1 = {
+ // Service center address
+ 0x09, (byte) 0x91, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0xf8,
+
+ 0x04, 0x04, (byte) 0x91, 0x21, 0x43, 0x7f, 0x16, (byte) 0x89, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x0d, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x20, 0x31
+ };
+
+ // SMS-PP Download Envelope 3.1.1
+ private static final String SMS_PP_ENVELOPE_3_1_1 = "d12d8202838106099111223344556677f88b1c04"
+ + "049121437f16891010000000000d546573744d6573736167652031";
+
+ // SMS-PP Message 3.1.5
+ private static final byte[] SMS_PP_MESSAGE_3_1_5 = {
+ // Service center address
+ 0x09, (byte) 0x91, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0xf8,
+
+ 0x44, 0x04, (byte) 0x91, 0x21, 0x43, 0x7f, (byte) 0xf6, (byte) 0x89, 0x10, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x02, 0x70, 0x00, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x00,
+ 0x00, 0x00, (byte) 0xbf, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ (byte) 0xdc, (byte) 0xdc, (byte) 0xdc, (byte) 0xdc, (byte) 0xdc, (byte) 0xdc,
+ (byte) 0xdc, (byte) 0xdc, (byte) 0xdc, (byte) 0xdc
+ };
+
+ // SMS-PP Download Envelope 3.1.5
+ private static final String SMS_PP_ENVELOPE_3_1_5 = "d13e8202838106099111223344556677f88b2d44"
+ + "049121437ff6891010000000001e0270000019000d00000000bfff00000000000100"
+ + "dcdcdcdcdcdcdcdcdcdc";
+
+ public void testDataDownloadMessage1() {
+ SmsMessage message = SmsMessage.createFromPdu(SMS_PP_MESSAGE_3_1_1);
+ assertTrue("message is SMS-PP data download", message.isUsimDataDownload());
+
+ mCm.expectSendEnvelope(SMS_PP_ENVELOPE_3_1_1, 0x90, 0x00, "");
+ mCm.expectAcknowledgeGsmSms(true, 0);
+ mHandler.startDataDownload(message);
+ mCm.assertExpectedMethodsCalled();
+
+ mCm.expectSendEnvelope(SMS_PP_ENVELOPE_3_1_1, 0x90, 0x00, "0123456789");
+ mCm.expectAcknowledgeGsmSmsWithPdu(true, "00077f16050123456789");
+ mHandler.startDataDownload(message);
+ mCm.assertExpectedMethodsCalled();
+
+ mCm.expectSendEnvelope(SMS_PP_ENVELOPE_3_1_1, 0x62, 0xff, "0123456789abcdef");
+ mCm.expectAcknowledgeGsmSmsWithPdu(false, "00d5077f16080123456789abcdef");
+ mHandler.startDataDownload(message);
+ mCm.assertExpectedMethodsCalled();
+ }
+
+ public void testDataDownloadMessage5() {
+ SmsMessage message = SmsMessage.createFromPdu(SMS_PP_MESSAGE_3_1_5);
+ assertTrue("message is SMS-PP data download", message.isUsimDataDownload());
+
+ mCm.expectSendEnvelope(SMS_PP_ENVELOPE_3_1_5, 0x90, 0x00, "9876543210");
+ mCm.expectAcknowledgeGsmSmsWithPdu(true, "00077ff6059876543210");
+ mHandler.startDataDownload(message);
+ mCm.assertExpectedMethodsCalled();
+
+ mCm.expectSendEnvelope(SMS_PP_ENVELOPE_3_1_5, 0x93, 0x00, "");
+ mCm.expectAcknowledgeGsmSms(false, 0xd4); // SIM toolkit busy
+ mHandler.startDataDownload(message);
+ mCm.assertExpectedMethodsCalled();
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java
new file mode 100644
index 0000000..56854ed
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test UsimServiceTable class.
+ */
+public class UsimServiceTableTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testUsimServiceTable() {
+ byte[] noServices = {0x00};
+ byte[] service1 = {0x01, 0x00};
+ byte[] service8 = {(byte) 0x80, 0x00, 0x00};
+ byte[] service8And9 = {(byte) 0x80, 0x01};
+ byte[] service28 = {0x00, 0x00, 0x00, 0x08};
+ byte[] service89To96 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, (byte) 0xff};
+
+ UsimServiceTable testTable1 = new UsimServiceTable(noServices);
+ assertFalse(testTable1.isAvailable(UsimServiceTable.UsimService.PHONEBOOK));
+ assertFalse(testTable1.isAvailable(UsimServiceTable.UsimService.FDN));
+ assertFalse(testTable1.isAvailable(UsimServiceTable.UsimService.NAS_CONFIG_BY_USIM));
+
+ UsimServiceTable testTable2 = new UsimServiceTable(service1);
+ assertTrue(testTable2.isAvailable(UsimServiceTable.UsimService.PHONEBOOK));
+ assertFalse(testTable2.isAvailable(UsimServiceTable.UsimService.FDN));
+ assertFalse(testTable2.isAvailable(UsimServiceTable.UsimService.NAS_CONFIG_BY_USIM));
+
+ UsimServiceTable testTable3 = new UsimServiceTable(service8);
+ assertFalse(testTable3.isAvailable(UsimServiceTable.UsimService.PHONEBOOK));
+ assertFalse(testTable3.isAvailable(UsimServiceTable.UsimService.BDN_EXTENSION));
+ assertTrue(testTable3.isAvailable(UsimServiceTable.UsimService.OUTGOING_CALL_INFO));
+ assertFalse(testTable3.isAvailable(UsimServiceTable.UsimService.INCOMING_CALL_INFO));
+ assertFalse(testTable3.isAvailable(UsimServiceTable.UsimService.NAS_CONFIG_BY_USIM));
+
+ UsimServiceTable testTable4 = new UsimServiceTable(service8And9);
+ assertFalse(testTable4.isAvailable(UsimServiceTable.UsimService.PHONEBOOK));
+ assertFalse(testTable4.isAvailable(UsimServiceTable.UsimService.BDN_EXTENSION));
+ assertTrue(testTable4.isAvailable(UsimServiceTable.UsimService.OUTGOING_CALL_INFO));
+ assertTrue(testTable4.isAvailable(UsimServiceTable.UsimService.INCOMING_CALL_INFO));
+ assertFalse(testTable4.isAvailable(UsimServiceTable.UsimService.SM_STORAGE));
+ assertFalse(testTable4.isAvailable(UsimServiceTable.UsimService.NAS_CONFIG_BY_USIM));
+
+ UsimServiceTable testTable5 = new UsimServiceTable(service28);
+ assertFalse(testTable5.isAvailable(UsimServiceTable.UsimService.PHONEBOOK));
+ assertTrue(testTable5.isAvailable(UsimServiceTable.UsimService.DATA_DL_VIA_SMS_PP));
+ assertFalse(testTable5.isAvailable(UsimServiceTable.UsimService.NAS_CONFIG_BY_USIM));
+
+ UsimServiceTable testTable6 = new UsimServiceTable(service89To96);
+ assertFalse(testTable6.isAvailable(UsimServiceTable.UsimService.PHONEBOOK));
+ assertFalse(testTable6.isAvailable(UsimServiceTable.UsimService.HPLMN_DIRECT_ACCESS));
+ assertTrue(testTable6.isAvailable(UsimServiceTable.UsimService.ECALL_DATA));
+ assertTrue(testTable6.isAvailable(UsimServiceTable.UsimService.SM_OVER_IP));
+ assertTrue(testTable6.isAvailable(UsimServiceTable.UsimService.UICC_ACCESS_TO_IMS));
+ assertTrue(testTable6.isAvailable(UsimServiceTable.UsimService.NAS_CONFIG_BY_USIM));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java b/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java
new file mode 100644
index 0000000..3149ee1
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.mockril;
+
+import android.util.Log;
+import android.test.InstrumentationTestCase;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import com.android.internal.communication.MsgHeader;
+import com.android.internal.communication.Msg;
+import com.android.internal.telephony.RilChannel;
+import com.android.internal.telephony.ril_proto.RilCtrlCmds;
+import com.android.internal.telephony.ril_proto.RilCmds;
+
+import com.android.frameworks.telephonytests.TelephonyMockRilTestRunner;
+import com.google.protobuf.micro.InvalidProtocolBufferMicroException;
+
+// Test suite for test ril
+public class MockRilTest extends InstrumentationTestCase {
+ private static final String TAG = "MockRilTest";
+
+ RilChannel mMockRilChannel;
+ TelephonyMockRilTestRunner mRunner;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mRunner = (TelephonyMockRilTestRunner)getInstrumentation();
+ mMockRilChannel = mRunner.mMockRilChannel;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ static void log(String s) {
+ Log.v(TAG, s);
+ }
+
+ /**
+ * Test Case 1: Test protobuf serialization and deserialization
+ * @throws InvalidProtocolBufferMicroException
+ */
+ public void testProtobufSerDes() throws InvalidProtocolBufferMicroException {
+ log("testProtobufSerdes E");
+
+ RilCtrlCmds.CtrlRspRadioState rs = new RilCtrlCmds.CtrlRspRadioState();
+ assertTrue(String.format("expected rs.state == 0 was %d", rs.getState()),
+ rs.getState() == 0);
+ rs.setState(1);
+ assertTrue(String.format("expected rs.state == 1 was %d", rs.getState()),
+ rs.getState() == 1);
+
+ byte[] rs_ser = rs.toByteArray();
+ RilCtrlCmds.CtrlRspRadioState rsNew = RilCtrlCmds.CtrlRspRadioState.parseFrom(rs_ser);
+ assertTrue(String.format("expected rsNew.state == 1 was %d", rs.getState()),
+ rs.getState() == 1);
+
+ log("testProtobufSerdes X");
+ }
+
+ /**
+ * Test case 2: Test echo command works using writeMsg & readMsg
+ */
+ public void testEchoMsg() throws IOException {
+ log("testEchoMsg E");
+
+ MsgHeader mh = new MsgHeader();
+ mh.setCmd(0);
+ mh.setToken(1);
+ mh.setStatus(2);
+ ByteBuffer data = ByteBuffer.allocate(3);
+ data.put((byte)3);
+ data.put((byte)4);
+ data.put((byte)5);
+ Msg.send(mMockRilChannel, mh, data);
+
+ Msg respMsg = Msg.recv(mMockRilChannel);
+ assertTrue(String.format("expected mhd.header.cmd == 0 was %d",respMsg.getCmd()),
+ respMsg.getCmd() == 0);
+ assertTrue(String.format("expected mhd.header.token == 1 was %d",respMsg.getToken()),
+ respMsg.getToken() == 1);
+ assertTrue(String.format("expected mhd.header.status == 2 was %d", respMsg.getStatus()),
+ respMsg.getStatus() == 2);
+ assertTrue(String.format("expected mhd.data[0] == 3 was %d", respMsg.getData(0)),
+ respMsg.getData(0) == 3);
+ assertTrue(String.format("expected mhd.data[1] == 4 was %d", respMsg.getData(1)),
+ respMsg.getData(1) == 4);
+ assertTrue(String.format("expected mhd.data[2] == 5 was %d", respMsg.getData(2)),
+ respMsg.getData(2) == 5);
+
+ log("testEchoMsg X");
+ }
+
+ /**
+ * Test case 3: Test get as
+ */
+ public void testGetAs() {
+ log("testGetAs E");
+
+ // Use a message header as the protobuf data content
+ MsgHeader mh = new MsgHeader();
+ mh.setCmd(12345);
+ mh.setToken(9876);
+ mh.setStatus(7654);
+ mh.setLengthData(4321);
+ byte[] data = mh.toByteArray();
+ MsgHeader mhResult = Msg.getAs(MsgHeader.class, data);
+
+ assertTrue(String.format("expected cmd == 12345 was %d", mhResult.getCmd()),
+ mhResult.getCmd() == 12345);
+ assertTrue(String.format("expected token == 9876 was %d", mhResult.getToken()),
+ mhResult.getToken() == 9876);
+ assertTrue(String.format("expected status == 7654 was %d", mhResult.getStatus()),
+ mhResult.getStatus() == 7654);
+ assertTrue(String.format("expected lengthData == 4321 was %d", mhResult.getLengthData()),
+ mhResult.getLengthData() == 4321);
+
+ Msg msg = Msg.obtain();
+ msg.setData(ByteBuffer.wrap(data));
+
+ mhResult = msg.getDataAs(MsgHeader.class);
+
+ assertTrue(String.format("expected cmd == 12345 was %d", mhResult.getCmd()),
+ mhResult.getCmd() == 12345);
+ assertTrue(String.format("expected token == 9876 was %d", mhResult.getToken()),
+ mhResult.getToken() == 9876);
+ assertTrue(String.format("expected status == 7654 was %d", mhResult.getStatus()),
+ mhResult.getStatus() == 7654);
+ assertTrue(String.format("expected lengthData == 4321 was %d", mhResult.getLengthData()),
+ mhResult.getLengthData() == 4321);
+
+ log("testGetAs X");
+ }
+
+ /**
+ * Test case 3: test get radio state
+ */
+ public void testGetRadioState() throws IOException {
+ log("testGetRadioState E");
+
+ Msg.send(mMockRilChannel, 1, 9876, 0, null);
+
+ Msg resp = Msg.recv(mMockRilChannel);
+ //resp.printHeader("testGetRadioState");
+
+ assertTrue(String.format("expected cmd == 1 was %d", resp.getCmd()),
+ resp.getCmd() == 1);
+ assertTrue(String.format("expected token == 9876 was %d", resp.getToken()),
+ resp.getToken() == 9876);
+ assertTrue(String.format("expected status == 0 was %d", resp.getStatus()),
+ resp.getStatus() == 0);
+
+ RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);
+
+ int state = rsp.getState();
+ log("testGetRadioState state=" + state);
+ assertTrue(String.format("expected RadioState >= 0 && RadioState <= 9 was %d", state),
+ ((state >= 0) && (state <= 9)));
+
+ log("testGetRadioState X");
+ }
+
+ /**
+ * Test case 5: test set radio state
+ */
+ public void testSetRadioState() throws IOException {
+ log("testSetRadioState E");
+
+ RilCtrlCmds.CtrlReqRadioState cmdrs = new RilCtrlCmds.CtrlReqRadioState();
+ assertEquals(0, cmdrs.getState());
+
+ cmdrs.setState(RilCmds.RADIOSTATE_SIM_NOT_READY);
+ assertEquals(2, cmdrs.getState());
+
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_RADIO_STATE, 0, 0, cmdrs);
+
+ Msg resp = Msg.recv(mMockRilChannel);
+ log("get response status :" + resp.getStatus());
+ log("get response for command: " + resp.getCmd());
+ log("get command token: " + resp.getToken());
+
+ RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);
+
+ int state = rsp.getState();
+ log("get response for testSetRadioState: " + state);
+ assertTrue(RilCmds.RADIOSTATE_SIM_NOT_READY == state);
+ }
+
+ /**
+ * Test case 6: test start incoming call and hangup it.
+ */
+ public void testStartIncomingCallAndHangup() throws IOException {
+ log("testStartIncomingCallAndHangup");
+ RilCtrlCmds.CtrlReqSetMTCall cmd = new RilCtrlCmds.CtrlReqSetMTCall();
+ String incomingCall = "6502889108";
+ // set the MT call
+ cmd.setPhoneNumber(incomingCall);
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_MT_CALL, 0, 0, cmd);
+ // get response
+ Msg resp = Msg.recv(mMockRilChannel);
+ log("Get response status: " + resp.getStatus());
+ assertTrue("The ril is not in a proper state to set MT calls.",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+ // allow the incoming call alerting for some time
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {}
+
+ // we are playing a trick to assume the current is 1
+ RilCtrlCmds.CtrlHangupConnRemote hangupCmd = new RilCtrlCmds.CtrlHangupConnRemote();
+ hangupCmd.setConnectionId(1);
+ hangupCmd.setCallFailCause(16); // normal hangup
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_HANGUP_CONN_REMOTE, 0, 0, hangupCmd);
+
+ // get response
+ resp = Msg.recv(mMockRilChannel);
+ log("Get response for hangup connection: " + resp.getStatus());
+ assertTrue("CTRL_CMD_HANGUP_CONN_REMOTE failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+ }
+
+ /**
+ * Test case 7: test set call transition flag
+ */
+ public void testSetCallTransitionFlag() throws IOException {
+ log("testSetCallTransitionFlag");
+ // Set flag to true:
+ RilCtrlCmds.CtrlSetCallTransitionFlag cmd = new RilCtrlCmds.CtrlSetCallTransitionFlag();
+ cmd.setFlag(true);
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_TRANSITION_FLAG, 0, 0, cmd);
+
+ Msg resp = Msg.recv(mMockRilChannel);
+ log("Get response status: " + resp.getStatus());
+ assertTrue("Set call transition flag failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+ // add a dialing call
+ RilCtrlCmds.CtrlReqAddDialingCall cmdDialCall = new RilCtrlCmds.CtrlReqAddDialingCall();
+ String phoneNumber = "5102345678";
+ cmdDialCall.setPhoneNumber(phoneNumber);
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_ADD_DIALING_CALL, 0, 0, cmdDialCall);
+ resp = Msg.recv(mMockRilChannel);
+ log("Get response status for adding a dialing call: " + resp.getStatus());
+ assertTrue("add dialing call failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {}
+
+ // send command to force call state change
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_ALERT, 0, 0, null);
+ resp = Msg.recv(mMockRilChannel);
+ log("Get response status: " + resp.getStatus());
+ assertTrue("Set call alert failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {}
+
+ // send command to force call state change
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_ACTIVE, 0, 0, null);
+ resp = Msg.recv(mMockRilChannel);
+ log("Get response status: " + resp.getStatus());
+ assertTrue("Set call active failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+ // hangup the active all remotely
+ RilCtrlCmds.CtrlHangupConnRemote hangupCmd = new RilCtrlCmds.CtrlHangupConnRemote();
+ hangupCmd.setConnectionId(1);
+ hangupCmd.setCallFailCause(16); // normal hangup
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_HANGUP_CONN_REMOTE, 0, 0, hangupCmd);
+ resp = Msg.recv(mMockRilChannel);
+ log("Get response for hangup connection: " + resp.getStatus());
+ assertTrue("CTRL_CMD_HANGUP_CONN_REMOTE failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+ // set the flag to false
+ cmd.setFlag(false);
+ Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_TRANSITION_FLAG, 0, 0, cmd);
+ resp = Msg.recv(mMockRilChannel);
+ assertTrue("Set call transition flag failed",
+ resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+ }
+}