summaryrefslogtreecommitdiffstats
path: root/telephony/java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
commitf013e1afd1e68af5e3b868c26a653bbfb39538f8 (patch)
tree7ad6c8fd9c7b55f4b4017171dec1cb760bbd26bf /telephony/java
parente70cfafe580c6f2994c4827cd8a534aabf3eb05c (diff)
downloadframeworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.zip
frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.tar.gz
frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'telephony/java')
-rw-r--r--telephony/java/android/telephony/JapanesePhoneNumberFormatter.java216
-rw-r--r--telephony/java/android/telephony/NeighboringCellInfo.aidl20
-rw-r--r--telephony/java/android/telephony/NeighboringCellInfo.java123
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java145
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java204
-rw-r--r--telephony/java/android/telephony/gsm/SmsManager.java12
-rw-r--r--telephony/java/android/telephony/gsm/SmsMessage.java27
-rw-r--r--telephony/java/com/android/internal/telephony/CallerInfo.java38
-rw-r--r--telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java7
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl27
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java11
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyIntents.java20
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java14
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/CallTracker.java51
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java6
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java323
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GSMConnection.java53
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GSMPhone.java128
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java4
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java32
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/MccTable.java80
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/PdpConnection.java27
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/RIL.java414
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SIMRecords.java119
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java14
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java198
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimException.java25
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimUtils.java147
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/AppInterface.java291
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java21
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/CommandDetails.java106
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/CommandListener.java187
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java168
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java870
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java8
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/Duration.java29
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java45
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/Input.java97
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/Item.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/Menu.java46
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java140
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/ResultCode.java11
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java145
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/Service.java2510
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/StkAppInstaller.java61
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/StkAppStateReceiver.java51
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/StkCmdMessage.java175
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/StkLog.java (renamed from telephony/java/com/android/internal/telephony/gsm/stk/CtlvCommandDetails.java)32
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/StkResponseMessage.java54
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/TextMessage.java71
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/Tone.java26
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/ToneSettings.java62
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java340
-rw-r--r--telephony/java/com/android/internal/telephony/test/ModelInterpreter.java43
-rw-r--r--telephony/java/com/android/internal/telephony/test/SimulatedCommands.java46
-rw-r--r--telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java8
56 files changed, 4668 insertions, 3462 deletions
diff --git a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
new file mode 100644
index 0000000..8a82966
--- /dev/null
+++ b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
@@ -0,0 +1,216 @@
+/*
+ * 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 android.telephony;
+
+import android.text.Editable;
+
+/*
+ * Japanese Phone number formatting rule is a bit complicated.
+ * Here are some valid examples:
+ *
+ * 022-229-1234 0223-23-1234 022-301-9876 015-482-7849 0154-91-3478
+ * 01547-5-4534 090-1234-1234 080-0123-6789
+ * 0800-000-9999 0570-000-000 0276-00-0000
+ *
+ * As you can see, there is no straight-forward rule here.
+ * In order to handle this, a big array is prepared.
+ */
+/* package */ class JapanesePhoneNumberFormatter {
+ private static short FORMAT_MAP[] = {
+ -100, 10, 220, -15, 410, 530, -15, 670, 780, 1060,
+ -100, -25, 20, 40, 70, 100, 150, 190, 200, 210,
+ -36, -100, -100, -35, -35, -35, 30, -100, -100, -100,
+ -35, -35, -35, -35, -35, -35, -35, -45, -35, -35,
+ -100, -100, -100, -35, -35, -35, -35, 50, -35, 60,
+ -35, -35, -45, -35, -45, -35, -35, -45, -35, -35,
+ -35, -35, -45, -35, -35, -35, -35, -45, -45, -35,
+ -100, -100, -35, -35, -35, 80, 90, -100, -100, -100,
+ -35, -35, -35, -35, -35, -35, -45, -45, -35, -35,
+ -35, -35, -35, -35, -35, -35, -45, -35, -35, -35,
+ -25, -25, -35, -35, 110, 120, 130, -35, 140, -25,
+ -35, -25, -35, -35, -35, -35, -35, -45, -25, -35,
+ -35, -25, -35, -35, -35, -35, -35, -25, -45, -35,
+ -35, -35, -35, -35, -45, -35, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -45, -45, -35, -35,
+ -100, -100, -35, 160, 170, 180, -35, -35, -100, -100,
+ -35, -35, -45, -35, -45, -45, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -35, -35, -45, -35,
+ -35, -35, -35, -35, -45, -45, -45, -35, -45, -35,
+ -25, -25, -35, -35, -35, -35, -35, -25, -35, -35,
+ -25, -25, -35, -35, -35, -35, -35, -35, -25, -25,
+ -25, -35, -35, -35, -35, -35, -25, -35, -35, -25,
+ -100, -100, 230, 250, 260, 270, 320, 340, 360, 390,
+ -35, -25, -25, 240, -35, -35, -35, -25, -35, -35,
+ -25, -35, -35, -35, -25, -25, -25, -25, -25, -25,
+ -25, -25, -25, -35, -35, -35, -25, -35, -35, -25,
+ -35, -35, -35, -35, -35, -25, -35, -35, -35, -25,
+ -35, -25, -25, -25, -35, 280, 290, 300, 310, -35,
+ -25, -25, -25, -25, -25, -25, -25, -35, -35, -25,
+ -25, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -25, -25, -35, -35, -35, -25, -25, -25, -25, -25,
+ -25, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, -35, -25, -35, 330, -35, -35, -35, -35, -35,
+ -25, -35, -35, -35, -35, -35, -25, -25, -25, -25,
+ -35, -25, -25, -25, -35, -25, -35, -35, 350, -35,
+ -25, -35, -35, -35, -35, -35, -35, -35, -25, -25,
+ -35, -25, -35, 370, -35, -35, -25, -35, -35, 380,
+ -25, -35, -35, -25, -25, -35, -35, -35, -35, -35,
+ -25, -35, -25, -25, -25, -25, -35, -35, -35, -35,
+ -25, -35, -25, 400, -35, -35, -35, -35, -25, -35,
+ -25, -35, -35, -35, -35, -25, -25, -25, -25, -25,
+ -15, -15, 420, 460, -25, -25, 470, 480, 500, 510,
+ -15, -25, 430, -25, -25, -25, -25, -25, 440, 450,
+ -25, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -25, -25, -35, -35, -25, -25, -25, -35, -35, -35,
+ -15, -25, -15, -15, -15, -15, -15, -25, -25, -15,
+ -25, -25, -25, -25, -25, -25, -35, -25, -35, -35,
+ -35, -25, -25, -35, -25, -35, -35, -35, -25, -25,
+ 490, -15, -25, -25, -25, -35, -35, -25, -35, -35,
+ -15, -35, -35, -35, -35, -35, -35, -35, -35, -15,
+ -35, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -25, -25, -25, -35, -35, -35, -25, -25, -25, 520,
+ -100, -100, -45, -100, -45, -100, -45, -100, -45, -100,
+ -25, -100, -25, 540, 580, 590, 600, 610, 630, 640,
+ -25, -35, -35, -35, -25, -25, -35, -35, -35, 550,
+ -35, -35, -25, -25, -25, -25, 560, 570, -25, -35,
+ -35, -35, -35, -35, -25, -25, -25, -25, -25, -25,
+ -25, -25, -25, -25, -35, -25, -25, -35, -25, -25,
+ -25, -25, -25, -25, -35, -35, -25, -35, -35, -25,
+ -35, -35, -25, -35, -35, -35, -35, -35, -35, -25,
+ -100, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -36, -100, -35, -35, -35, -35, 620, -35, -35, -100,
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -45,
+ -25, -35, -25, -25, -35, -35, -35, -35, -25, -25,
+ -25, -25, -25, -25, -35, -35, -35, 650, -35, 660,
+ -35, -35, -35, -35, -45, -35, -35, -35, -35, -45,
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -25,
+ -26, -100, 680, 690, 700, -25, 720, 730, -25, 740,
+ -25, -35, -25, -25, -25, -35, -25, -25, -25, -25,
+ -25, -25, -25, -25, -25, -35, -35, -35, -35, -35,
+ -35, -100, -35, -35, -35, -35, 710, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -35, -35, -45, -35,
+ -25, -35, -25, -35, -25, -35, -35, -35, -35, -25,
+ -35, -35, -35, -35, -35, -25, -35, -25, -35, -35,
+ -35, -35, -25, -25, 750, 760, 770, -35, -35, -35,
+ -25, -35, -25, -25, -25, -25, -35, -35, -35, -25,
+ -25, -35, -35, -35, -35, -25, -25, -35, -35, -25,
+ -25, -35, -35, -35, -35, -35, -25, -25, -35, -35,
+ 790, -100, 800, 850, 900, 920, 940, 1030, 1040, 1050,
+ -36, -26, -26, -26, -26, -26, -26, -26, -26, -26,
+ -35, -25, -25, -35, 810, -25, -35, -35, -25, 820,
+ -25, -35, -25, -25, -35, -35, -35, -35, -35, -25,
+ -25, -35, 830, -35, 840, -35, -25, -35, -35, -25,
+ -35, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -100, -25, -25, -25, -100, -100, -100, -100, -100, -100,
+ -25, -25, -35, -35, -35, -35, 860, -35, 870, 880,
+ -25, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -35, -45, -45, -35,
+ -100, -100, -100, -100, -100, -100, 890, -100, -100, -100,
+ -25, -45, -45, -25, -45, -45, -25, -45, -45, -45,
+ -25, -25, -25, -25, -25, -35, -35, 910, -35, -25,
+ -35, -35, -35, -35, -35, -35, -35, -45, -35, -35,
+ -100, 930, -35, -35, -35, -35, -35, -35, -35, -35,
+ -100, -100, -45, -100, -45, -100, -100, -100, -100, -100,
+ -25, -25, -25, 950, -25, 970, 990, -35, 1000, 1010,
+ -35, -35, -35, -35, -35, -35, 960, -35, -35, -35,
+ -45, -45, -45, -45, -45, -45, -35, -45, -45, -45,
+ -35, -35, -25, -35, -35, 980, -35, -35, -35, -35,
+ -100, -100, -25, -25, -100, -100, -100, -100, -100, -100,
+ -25, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -25, -35, -35, -35, -35, -35, -35, -35, -35, -25,
+ -25, -35, -35, -35, -25, -25, -35, -35, -35, 1020,
+ -45, -45, -35, -35, -45, -45, -45, -45, -45, -45,
+ -25, -25, -25, -25, -25, -35, -25, -35, -25, -35,
+ -35, -25, -25, -35, -35, -35, -25, -35, -25, -35,
+ -25, -25, -35, -35, -35, -35, -35, -35, -35, -25,
+ -26, -100, 1070, 1080, 1090, 1110, 1120, 1130, 1140, 1160,
+ -35, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -35, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -35, -100, -35, -35, -35, -100, -35, -35, -35, 1100,
+ -35, -35, -35, -35, -35, -35, -45, -35, -35, -35,
+ -35, -25, -35, -25, -35, -35, -35, -35, -25, -35,
+ -25, -25, -25, -25, -35, -35, -35, -35, -35, -35,
+ -25, -25, -35, -35, -35, -25, -25, -35, -35, -35,
+ 1150, -25, -35, -35, -35, -35, -35, -35, -25, -25,
+ -35, -35, -45, -35, -35, -35, -35, -35, -35, -35,
+ -35, 1170, -25, -35, 1180, -35, 1190, -35, -25, -25,
+ -100, -100, -45, -45, -100, -100, -100, -100, -100, -100,
+ -25, -35, -35, -35, -35, -35, -35, -25, -25, -35,
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -45};
+
+ public static void format(Editable text) {
+ // Here, "root" means the position of "'":
+ // 0'3, 0'90, and +81'-90
+ // (dash will be deleted soon, so it is actually +81'90).
+ int rootIndex = 1;
+ int length = text.length();
+ if (length > 3
+ && text.subSequence(0, 3).toString().equals("+81")) {
+ rootIndex = 3;
+ } else if (length < 1 || text.charAt(0) != '0') {
+ return;
+ }
+
+ CharSequence saved = text.subSequence(0, length);
+
+ // Strip the dashes first, as we're going to add them back
+ int i = 0;
+ while (i < text.length()) {
+ if (text.charAt(i) == '-') {
+ text.delete(i, i + 1);
+ } else {
+ i++;
+ }
+ }
+
+ length = text.length();
+ int dashposition;
+
+ i = rootIndex;
+ int base = 0;
+ while (i < length) {
+ char ch = text.charAt(i);
+ if (!Character.isDigit(ch)) {
+ text.replace(0, length, saved);
+ return;
+ }
+ short value = FORMAT_MAP[base + ch - '0'];
+ if (value < 0) {
+ if (value <= -100) {
+ text.replace(0, length, saved);
+ return;
+ }
+ int dashPos2 = rootIndex + (Math.abs(value) % 10);
+ if (length > dashPos2) {
+ text.insert(dashPos2, "-");
+ }
+ int dashPos1 = rootIndex + (Math.abs(value) / 10);
+ if (length > dashPos1) {
+ text.insert(dashPos1, "-");
+ }
+ break;
+ } else {
+ base = value;
+ i++;
+ }
+ }
+
+ if (length > 3 && rootIndex == 3) {
+ text.insert(rootIndex, "-");
+ }
+ }
+} \ No newline at end of file
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.aidl b/telephony/java/android/telephony/NeighboringCellInfo.aidl
new file mode 100644
index 0000000..a7e709e
--- /dev/null
+++ b/telephony/java/android/telephony/NeighboringCellInfo.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/content/Intent.aidl
+**
+** Copyright 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 android.telephony;
+
+parcelable NeighboringCellInfo; \ No newline at end of file
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
new file mode 100644
index 0000000..326401a
--- /dev/null
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -0,0 +1,123 @@
+/*
+ * 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 android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the neighboring cell information, including
+ * Received Signal Strength and Cell ID location.
+ */
+public class NeighboringCellInfo implements Parcelable
+{
+ /**
+ * Signal strength is not available
+ */
+ static final public int UNKNOWN_RSSI = 99;
+ /**
+ * Cell location is not available
+ */
+ static final public int UNKNOWN_CID = -1;
+
+ private int mRssi;
+ private int mCid;
+
+ /**
+ * Empty constructor. Initializes the RSSI and CID.
+ */
+ public NeighboringCellInfo() {
+ mRssi = UNKNOWN_RSSI;
+ mCid = UNKNOWN_CID;
+ }
+
+ /**
+ * Initialize the object from rssi and cid.
+ */
+ public NeighboringCellInfo(int rssi, int cid) {
+ mRssi = rssi;
+ mCid = cid;
+ }
+
+ /**
+ * Initialize the object from a parcel.
+ */
+ public NeighboringCellInfo(Parcel in) {
+ mRssi = in.readInt();
+ mCid = in.readInt();
+ }
+
+ /**
+ * @return received signal strength in "asu", ranging from 0 - 31,
+ * or UNKNOWN_RSSI if unknown
+ *
+ * For GSM, dBm = -113 + 2*asu,
+ * 0 means "-113 dBm or less" and 31 means "-51 dBm or greater"
+ */
+ public int getRssi() {
+ return mRssi;
+ }
+
+ /**
+ * @return cell id, UNKNOWN_CID if unknown, 0xffffffff max legal value
+ */
+ public int getCid() {
+ return mCid;
+ }
+
+ /**
+ * Set the cell id.
+ */
+ public void setCid(int cid) {
+ mCid = cid;
+ }
+
+ /**
+ * Set the signal strength of the cell.
+ */
+ public void setRssi(int rssi) {
+ mRssi = rssi;
+ }
+
+ @Override
+ public String toString() {
+ return "["+ ((mCid == UNKNOWN_CID) ? "/" : Integer.toHexString(mCid))
+ + " at " + ((mRssi == UNKNOWN_RSSI)? "/" : mRssi) + "]";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mRssi);
+ dest.writeInt(mCid);
+ }
+
+ public static final Parcelable.Creator<NeighboringCellInfo> CREATOR
+ = new Parcelable.Creator<NeighboringCellInfo>() {
+ public NeighboringCellInfo createFromParcel(Parcel in) {
+ return new NeighboringCellInfo(in);
+ }
+
+ public NeighboringCellInfo[] newArray(int size) {
+ return new NeighboringCellInfo[size];
+ }
+ };
+}
+
+
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index f2b63cc..d3942fc 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -505,9 +505,10 @@ public class PhoneNumberUtils
* Called Party BCD Number
*
* See Also TS 51.011 10.5.1 "dialing number/ssc string"
+ * and TS 11.11 "10.3.1 EF adn (Abbreviated dialing numbers)"
*
* @param bytes the data buffer
- * @param offset should point to the TOI/NPI octet after the length byte
+ * @param offset should point to the TOA (aka. TON/NPI) octet after the length byte
* @param length is the number of bytes including TOA byte
* and must be at least 2
*
@@ -518,7 +519,7 @@ public class PhoneNumberUtils
*/
public static String
calledPartyBCDToString (byte[] bytes, int offset, int length) {
- boolean prependedPlus = false;
+ boolean prependPlus = false;
StringBuilder ret = new StringBuilder(1 + length * 2);
if (length < 2) {
@@ -526,18 +527,92 @@ public class PhoneNumberUtils
}
if ((bytes[offset] & 0xff) == TOA_International) {
- ret.append("+");
- prependedPlus = true;
+ prependPlus = true;
}
internalCalledPartyBCDFragmentToString(
ret, bytes, offset + 1, length - 1);
- if (prependedPlus && ret.length() == 1) {
+ if (prependPlus && ret.length() == 0) {
// If the only thing there is a prepended plus, return ""
return "";
}
+ if (prependPlus) {
+ // This is an "international number" and should have
+ // a plus prepended to the dialing number. But there
+ // can also be Gsm MMI codes as defined in TS 22.030 6.5.2
+ // so we need to handle those also.
+ //
+ // http://web.telia.com/~u47904776/gsmkode.htm is a
+ // has a nice list of some of these GSM codes.
+ //
+ // Examples are:
+ // **21*+886988171479#
+ // **21*8311234567#
+ // *21#
+ // #21#
+ // *#21#
+ // *31#+11234567890
+ // #31#+18311234567
+ // #31#8311234567
+ // 18311234567
+ // +18311234567#
+ // +18311234567
+ // Odd ball cases that some phones handled
+ // where there is no dialing number so they
+ // append the "+"
+ // *21#+
+ // **21#+
+ String retString = ret.toString();
+ Pattern p = Pattern.compile("(^[#*])(.*)([#*])(.*)(#)$");
+ Matcher m = p.matcher(retString);
+ if (m.matches()) {
+ if ("".equals(m.group(2))) {
+ // Started with two [#*] ends with #
+ // So no dialing number and we'll just
+ // append a +, this handles **21#+
+ ret = new StringBuilder();
+ ret.append(m.group(1));
+ ret.append(m.group(3));
+ ret.append(m.group(4));
+ ret.append(m.group(5));
+ ret.append("+");
+ } else {
+ // Starts with [#*] and ends with #
+ // Assume group 4 is a dialing number
+ // such as *21*+1234554#
+ ret = new StringBuilder();
+ ret.append(m.group(1));
+ ret.append(m.group(2));
+ ret.append(m.group(3));
+ ret.append("+");
+ ret.append(m.group(4));
+ ret.append(m.group(5));
+ }
+ } else {
+ p = Pattern.compile("(^[#*])(.*)([#*])(.*)");
+ m = p.matcher(retString);
+ if (m.matches()) {
+ // Starts with [#*] and only one other [#*]
+ // Assume the data after last [#*] is dialing
+ // number (i.e. group 4) such as *31#+11234567890.
+ // This also includes the odd ball *21#+
+ ret = new StringBuilder();
+ ret.append(m.group(1));
+ ret.append(m.group(2));
+ ret.append(m.group(3));
+ ret.append("+");
+ ret.append(m.group(4));
+ } else {
+ // Does NOT start with [#*] just prepend '+'
+ ret = new StringBuilder();
+ ret.append('+');
+ ret.append(retString);
+ }
+ }
+ }
+
return ret.toString();
}
@@ -688,7 +763,7 @@ public class PhoneNumberUtils
numberToCalledPartyBCD(String number) {
// The extra byte required for '+' is taken into consideration while calculating
// length of ret.
- int size = ((number.charAt(0) == '+') ? number.length() - 1 : number.length());
+ int size = (hasPlus(number) ? number.length() - 1 : number.length());
byte[] ret = new byte[(size + 1) / 2 + 1];
return numberToCalledPartyBCDHelper(ret, 0, number);
@@ -702,7 +777,7 @@ public class PhoneNumberUtils
numberToCalledPartyBCDWithLength(String number) {
// The extra byte required for '+' is taken into consideration while calculating
// length of ret.
- int size = ((number.charAt(0) == '+') ? number.length() - 1 : number.length());
+ int size = (hasPlus(number) ? number.length() - 1 : number.length());
int length = (size + 1) / 2 + 1;
byte[] ret = new byte[length + 1];
@@ -710,21 +785,22 @@ public class PhoneNumberUtils
return numberToCalledPartyBCDHelper(ret, 1, number);
}
+ private static boolean
+ hasPlus(String s) {
+ return s.indexOf('+') >= 0;
+ }
+
private static byte[]
numberToCalledPartyBCDHelper(byte[] ret, int offset, String number) {
- int size;
- int curChar;
-
- size = number.length();
-
- if (number.charAt(0) == '+') {
- curChar = 1;
+ if (hasPlus(number)) {
+ number = number.replaceAll("\\+", "");
ret[offset] = (byte) TOA_International;
} else {
- curChar = 0;
ret[offset] = (byte) TOA_Unknown;
}
+ int size = number.length();
+ int curChar = 0;
int countFullBytes = ret.length - offset - 1 - ((size - curChar) & 1);
for (int i = 1; i < 1 + countFullBytes; i++) {
ret[offset + i]
@@ -818,6 +894,8 @@ public class PhoneNumberUtils
public static final int FORMAT_UNKNOWN = 0;
/** NANP formatting */
public static final int FORMAT_NANP = 1;
+ /** Japanese formatting */
+ public static final int FORMAT_JAPAN = 2;
/** List of country codes for countries that use the NANP */
private static final String[] NANP_COUNTRIES = new String[] {
@@ -878,6 +956,9 @@ public class PhoneNumberUtils
return FORMAT_NANP;
}
}
+ if (locale.equals(Locale.JAPAN)) {
+ return FORMAT_JAPAN;
+ }
return FORMAT_UNKNOWN;
}
@@ -891,10 +972,12 @@ public class PhoneNumberUtils
public static void formatNumber(Editable text, int defaultFormattingType) {
int formatType = defaultFormattingType;
- // This only handles +1 for now
if (text.length() > 2 && text.charAt(0) == '+') {
if (text.charAt(1) == '1') {
formatType = FORMAT_NANP;
+ } else if (text.length() >= 3 && text.charAt(1) == '8'
+ && text.charAt(2) == '1') {
+ formatType = FORMAT_JAPAN;
} else {
return;
}
@@ -904,6 +987,9 @@ public class PhoneNumberUtils
case FORMAT_NANP:
formatNanpNumber(text);
return;
+ case FORMAT_JAPAN:
+ formatJapaneseNumber(text);
+ return;
}
}
@@ -932,7 +1018,7 @@ public class PhoneNumberUtils
return;
}
CharSequence saved = text.subSequence(0, length);
-
+
// Strip the dashes first, as we're going to add them back
int p = 0;
while (p < text.length()) {
@@ -1013,7 +1099,7 @@ public class PhoneNumberUtils
int pos = dashPositions[i];
text.replace(pos + i, pos + i, "-");
}
-
+
// Remove trailing dashes
int len = text.length();
while (len > 0) {
@@ -1026,6 +1112,25 @@ public class PhoneNumberUtils
}
}
+ /**
+ * Formats a phone number in-place using the Japanese formatting rules.
+ * Numbers will be formatted as:
+ *
+ * <p><code>
+ * 03-xxxx-xxxx
+ * 090-xxxx-xxxx
+ * 0120-xxx-xxx
+ * +81-3-xxxx-xxxx
+ * +81-90-xxxx-xxxx
+ * </code></p>
+ *
+ * @param text the number to be formatted, will be modified with
+ * the formatting
+ */
+ public static void formatJapaneseNumber(Editable text) {
+ JapanesePhoneNumberFormatter.format(text);
+ }
+
// Three and four digit phone numbers for either special services
// or from the network (eg carrier-originated SMS messages) should
// not match
@@ -1040,10 +1145,10 @@ public class PhoneNumberUtils
* listed in the ril / sim, then return true, otherwise false.
*/
public static boolean isEmergencyNumber(String number) {
- // Strip the separators from the number before comparing it
+ // Strip the separators from the number before comparing it
// to the list.
number = extractNetworkPortion(number);
-
+
// retrieve the list of emergency numbers
String numbers = SystemProperties.get("ro.ril.ecclist");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 529ba31..374a703 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16,20 +16,19 @@
package android.telephony;
-import android.content.BroadcastReceiver;
+import com.android.internal.telephony.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SdkConstant;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Bundle;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.ServiceManager;
+import android.os.SystemProperties;
-import com.android.internal.telephony.*;
-import android.telephony.CellLocation;
-import android.telephony.ServiceState;
-
-import java.util.ArrayList;
/**
* Provides access to information about the telephony services on
@@ -73,6 +72,93 @@ public class TelephonyManager {
return sInstance;
}
+
+ //
+ // Broadcast Intent actions
+ //
+
+ /**
+ * Broadcast intent action indicating that the call state (cellular)
+ * on the device has changed.
+ *
+ * <p>
+ * The {@link #EXTRA_STATE} extra indicates the new call state.
+ * If the new state is RINGING, a second extra
+ * {@link #EXTRA_INCOMING_NUMBER} provides the incoming phone number as
+ * a String.
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">
+ * This was a {@link android.content.Context#sendStickyBroadcast sticky}
+ * broadcast in version 1.0, but it is no longer sticky.
+ * Instead, use {@link #getCallState} to synchronously query the current call state.
+ *
+ * @see #EXTRA_STATE
+ * @see #EXTRA_INCOMING_NUMBER
+ * @see #getCallState
+ *
+ * @hide pending API Council approval
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PHONE_STATE_CHANGED =
+ "android.intent.action.PHONE_STATE";
+
+ /**
+ * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
+ * for a String containing the new call state.
+ *
+ * @see #EXTRA_STATE_IDLE
+ * @see #EXTRA_STATE_RINGING
+ * @see #EXTRA_STATE_OFFHOOK
+ *
+ * <p class="note">
+ * Retrieve with
+ * {@link android.content.Intent#getStringExtra(String)}.
+ *
+ * @hide pending API Council approval
+ */
+ public static final String EXTRA_STATE = Phone.STATE_KEY;
+
+ /**
+ * Value used with {@link #EXTRA_STATE} corresponding to
+ * {@link #CALL_STATE_IDLE}.
+ *
+ * @hide pending API Council approval
+ */
+ public static final String EXTRA_STATE_IDLE = Phone.State.IDLE.toString();
+
+ /**
+ * Value used with {@link #EXTRA_STATE} corresponding to
+ * {@link #CALL_STATE_RINGING}.
+ *
+ * @hide pending API Council approval
+ */
+ public static final String EXTRA_STATE_RINGING = Phone.State.RINGING.toString();
+
+ /**
+ * Value used with {@link #EXTRA_STATE} corresponding to
+ * {@link #CALL_STATE_OFFHOOK}.
+ *
+ * @hide pending API Council approval
+ */
+ public static final String EXTRA_STATE_OFFHOOK = Phone.State.OFFHOOK.toString();
+
+ /**
+ * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
+ * for a String containing the incoming phone number.
+ * Only valid when the new call state is RINGING.
+ *
+ * <p class="note">
+ * Retrieve with
+ * {@link android.content.Intent#getStringExtra(String)}.
+ *
+ * @hide pending API Council approval
+ */
+ public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
+
+
//
//
// Device Info
@@ -157,6 +243,26 @@ public class TelephonyManager {
}
/**
+ * Returns the neighboring cell information of the device.
+ *
+ * @return List of NeighboringCellInfo or null if info unavailable.
+ *
+ * <p>Requires Permission:
+ * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
+ */
+ public List<NeighboringCellInfo> getNeighboringCellInfo() {
+ try {
+ ITelephony tel = getITelephony();
+ if (tel != null) {
+ return tel.getNeighboringCellInfo();
+ }
+ } catch (RemoteException ex) {
+ }
+ return null;
+
+ }
+
+ /**
* No phone module
*/
public static final int PHONE_TYPE_NONE = 0;
@@ -233,6 +339,7 @@ public class TelephonyManager {
/**
* Returns a constant indicating the radio technology (network type)
* currently in use on the device.
+ * @return the network type
*
* @see #NETWORK_TYPE_UNKNOWN
* @see #NETWORK_TYPE_GPRS
@@ -255,6 +362,26 @@ public class TelephonyManager {
}
}
+ /**
+ * Returns a string representation of the radio technology (network type)
+ * currently in use on the device.
+ * @return the name of the radio technology
+ *
+ * @hide pending API council review
+ */
+ public String getNetworkTypeName() {
+ switch (getNetworkType()) {
+ case NETWORK_TYPE_GPRS:
+ return "GPRS";
+ case NETWORK_TYPE_EDGE:
+ return "EDGE";
+ case NETWORK_TYPE_UMTS:
+ return "UMTS";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
//
//
// SIM Card
@@ -562,62 +689,3 @@ public class TelephonyManager {
}
}
}
-
-/*
- * These have not been implemented since they're not used anywhere in the system
- * and it's impossible to tell if they're working or not. The comments in SystemProperties
- * were wrong in at least one case, so I don't trust them. They claimed that
- * PROPERTY_OPERATOR_ISROAMING was "1" if it was true, but it's actually set to "true."
- */
-
-
- /* Set to '1' if voice mail is waiting, otherwise false */
- /*
- public boolean isVoiceMailWaiting() {
- return "1".equals(
- SystemProperties.get(TelephonyProperties.PROPERTY_LINE1_VOICE_MAIL_WAITING));
- }
- */
-
- /* Set to 'true' if unconditional voice call forwarding is enabled
- * Availablity: only if configured in SIM; SIM state must be "READY"
- */
- /*
- public boolean isCallForwarding() {
- SystemProperties.get(TelephonyProperties.PROPERTY_LINE1_VOICE_CALL_FORWARDING);
- }
- */
-
- /* '1' if the current network is the result of a manual network selection.
- * Availability: when registered to a network
- */
- /*
- public boolean isNetworkManual() {
- return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISMANUAL);
- }
- */
-
-
-/*
- * These have not been implemented because they're not public IMHO. -joeo
- */
-
- /*
- * Baseband version
- * Availability: property is available any time radio is on
- */
- /*
- public String getBasebandVersion() {
- return SystemProperties.get(TelephonyProperties.PROPERTY_BASEBAND_VERSION);
- }
- */
-
- /*
- * Radio Interface Layer (RIL) library implementation.
- */
- /*
- public String getRilLibrary() {
- return SystemProperties.get(TelephonyProperties.PROPERTY_RIL_IMPL);
- }
- */
-
diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java
index 274c461..c63b530 100644
--- a/telephony/java/android/telephony/gsm/SmsManager.java
+++ b/telephony/java/android/telephony/gsm/SmsManager.java
@@ -104,11 +104,12 @@ public final class SmsManager {
int limit;
if (messageCount > 1) {
- limit = (encodingType == SmsMessage.ENCODING_7BIT)?
- SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER: SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+ limit = (encodingType == SmsMessage.ENCODING_7BIT) ?
+ SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER :
+ SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
} else {
- limit = (encodingType == SmsMessage.ENCODING_7BIT)?
- SmsMessage.MAX_USER_DATA_SEPTETS: SmsMessage.MAX_USER_DATA_BYTES;
+ limit = (encodingType == SmsMessage.ENCODING_7BIT) ?
+ SmsMessage.MAX_USER_DATA_SEPTETS : SmsMessage.MAX_USER_DATA_BYTES;
}
try {
@@ -117,8 +118,7 @@ public final class SmsManager {
result.add(text.substring(start, end));
start = end;
}
- }
- catch (EncodeException e) {
+ } catch (EncodeException e) {
// ignore it.
}
return result;
diff --git a/telephony/java/android/telephony/gsm/SmsMessage.java b/telephony/java/android/telephony/gsm/SmsMessage.java
index 836a013..f79b0a0 100644
--- a/telephony/java/android/telephony/gsm/SmsMessage.java
+++ b/telephony/java/android/telephony/gsm/SmsMessage.java
@@ -16,11 +16,12 @@
package android.telephony.gsm;
-import android.pim.Time;
import android.telephony.PhoneNumberUtils;
import android.util.Config;
import android.util.Log;
import android.telephony.PhoneNumberUtils;
+import android.text.format.Time;
+
import com.android.internal.telephony.gsm.EncodeException;
import com.android.internal.telephony.gsm.GsmAlphabet;
import com.android.internal.telephony.gsm.SimUtils;
@@ -222,7 +223,7 @@ public class SmsMessage {
*
* @hide pending API Council approval to extend the public API
*/
- public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
+ static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
/** The maximum number of payload septets per message */
public static final int MAX_USER_DATA_SEPTETS = 160;
@@ -329,6 +330,9 @@ public class SmsMessage {
*/
boolean isStatusReportMessage = false;
+ /**
+ * This class represents the encoded form of an outgoing SMS.
+ */
public static class SubmitPdu {
public byte[] encodedScAddress; // Null if not applicable.
public byte[] encodedMessage;
@@ -472,23 +476,25 @@ public class SmsMessage {
ret[1] = septets;
if (septets > MAX_USER_DATA_SEPTETS) {
ret[0] = (septets / MAX_USER_DATA_SEPTETS_WITH_HEADER) + 1;
- ret[2] = septets % MAX_USER_DATA_SEPTETS_WITH_HEADER;
+ ret[2] = MAX_USER_DATA_SEPTETS_WITH_HEADER
+ - (septets % MAX_USER_DATA_SEPTETS_WITH_HEADER);
} else {
ret[0] = 1;
ret[2] = MAX_USER_DATA_SEPTETS - septets;
}
ret[3] = ENCODING_7BIT;
} catch (EncodeException ex) {
- // fall back to USC-2
+ // fall back to UCS-2
int octets = messageBody.length() * 2;
- ret[1] = octets;
+ ret[1] = messageBody.length();
if (octets > MAX_USER_DATA_BYTES) {
// 6 is the size of the user data header
ret[0] = (octets / MAX_USER_DATA_BYTES_WITH_HEADER) + 1;
- ret[2] = octets % MAX_USER_DATA_BYTES_WITH_HEADER;
+ ret[2] = (MAX_USER_DATA_BYTES_WITH_HEADER
+ - (octets % MAX_USER_DATA_BYTES_WITH_HEADER))/2;
} else {
ret[0] = 1;
- ret[2] = MAX_USER_DATA_BYTES - octets;
+ ret[2] = (MAX_USER_DATA_BYTES - octets)/2;
}
ret[3] = ENCODING_16BIT;
}
@@ -559,8 +565,7 @@ public class SmsMessage {
System.arraycopy(header, 0, userData, 0, header.length);
System.arraycopy(textPart, 0, userData, header.length, textPart.length);
- }
- else {
+ } else {
userData = textPart;
}
@@ -875,7 +880,9 @@ public class SmsMessage {
if (dataInSeptets) {
// Return the number of septets
- return userDataLength - headerSeptets;
+ int count = userDataLength - headerSeptets;
+ // If count < 0, return 0 (means UDL was probably incorrect)
+ return count < 0 ? 0 : count;
} else {
// Return the number of octets
return userData.length;
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 5f630f8..13b6e5c 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -40,6 +40,33 @@ public class CallerInfo {
public static final String UNKNOWN_NUMBER = "-1";
public static final String PRIVATE_NUMBER = "-2";
+ /**
+ * Please note that, any one of these member variables can be null,
+ * and any accesses to them should be prepared to handle such a case.
+ *
+ * Also, it is implied that phoneNumber is more often populated than
+ * name is, (think of calls being dialed/received using numbers where
+ * names are not known to the device), so phoneNumber should serve as
+ * a dependable fallback when name is unavailable.
+ *
+ * One other detail here is that this CallerInfo object reflects
+ * information found on a connection, it is an OUTPUT that serves
+ * mainly to display information to the user. In no way is this object
+ * used as input to make a connection, so we can choose to display
+ * whatever human-readable text makes sense to the user for a
+ * connection. This is especially relevant for the phone number field,
+ * since it is the one field that is most likely exposed to the user.
+ *
+ * As an example:
+ * 1. User dials "911"
+ * 2. Device recognizes that this is an emergency number
+ * 3. We use the "Emergency Number" string instead of "911" in the
+ * phoneNumber field.
+ *
+ * What we're really doing here is treating phoneNumber as an essential
+ * field here, NOT name. We're NOT always guaranteed to have a name
+ * for a connection, but the number should be displayable.
+ */
public String name;
public String phoneNumber;
public String phoneLabel;
@@ -192,6 +219,9 @@ public class CallerInfo {
// shortcut and skip the query.
if (PhoneNumberUtils.isEmergencyNumber(number)) {
CallerInfo ci = new CallerInfo();
+
+ // Note we're setting the phone number here (refer to javadoc
+ // comments at the top of CallerInfo class).
ci.phoneNumber = context.getString(
com.android.internal.R.string.emergency_call_dialog_number_for_display);
return ci;
@@ -200,7 +230,10 @@ public class CallerInfo {
if (!sSkipVmCheck && PhoneNumberUtils.compare(number,
TelephonyManager.getDefault().getVoiceMailNumber())) {
CallerInfo ci = new CallerInfo();
- ci.name = TelephonyManager.getDefault().getVoiceMailAlphaTag();
+
+ // Note we're setting the phone number here (refer to javadoc
+ // comments at the top of CallerInfo class).
+ ci.phoneNumber = TelephonyManager.getDefault().getVoiceMailAlphaTag();
// TODO: FIND ANOTHER ICON
//info.photoResource = android.R.drawable.badge_voicemail;
return ci;
@@ -214,7 +247,8 @@ public class CallerInfo {
}
}
- Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, number);
+ Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL,
+ Uri.encode(number));
CallerInfo info = getCallerInfo(context, contactUri);
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 6cb829d..145e5d8 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -224,6 +224,8 @@ public class CallerInfoAsyncQuery {
// accordingly.
if (cw.event == EVENT_EMERGENCY_NUMBER) {
mCallerInfo = new CallerInfo();
+ // Note we're setting the phone number here (refer to javadoc
+ // comments at the top of CallerInfo class).
mCallerInfo.phoneNumber = mQueryContext.getString(com.android.internal
.R.string.emergency_call_dialog_number_for_display);
mCallerInfo.photoResource = com.android.internal.R.drawable.picture_emergency;
@@ -231,7 +233,10 @@ public class CallerInfoAsyncQuery {
} else if (cw.event == EVENT_VOICEMAIL_NUMBER) {
mCallerInfo = new CallerInfo();
try {
- mCallerInfo.name = TelephonyManager.getDefault().getVoiceMailAlphaTag();
+ // Note we're setting the phone number here (refer to javadoc
+ // comments at the top of CallerInfo class).
+ mCallerInfo.phoneNumber =
+ TelephonyManager.getDefault().getVoiceMailAlphaTag();
} catch (SecurityException ex) {
// Should never happen: if this process does not have
// permission to retrieve VM tag, it should not have
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 663fc03..4957366 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -17,6 +17,8 @@
package com.android.internal.telephony;
import android.os.Bundle;
+import java.util.List;
+import android.telephony.NeighboringCellInfo;
/**
* Interface used to interact with the phone. Mostly this is used by the
@@ -43,10 +45,26 @@ interface ITelephony {
/**
* If there is currently a call in progress, show the call screen.
- * Returns true if the call screen was shown.
+ * The DTMF dialpad may or may not be visible initially, depending on
+ * whether it was up when the user last exited the InCallScreen.
+ *
+ * @return true if the call screen was shown.
*/
boolean showCallScreen();
-
+
+ /**
+ * Variation of showCallScreen() that also specifies whether the
+ * DTMF dialpad should be initially visible when the InCallScreen
+ * comes up.
+ *
+ * @param showDialpad if true, make the dialpad visible initially,
+ * otherwise hide the dialpad initially.
+ * @return true if the call screen was shown.
+ *
+ * @see showCallScreen
+ */
+ boolean showCallScreenWithDialpad(boolean showDialpad);
+
/**
* End call or go to the Home screen
*
@@ -157,6 +175,11 @@ interface ITelephony {
Bundle getCellLocation();
+ /**
+ * Returns the neighboring cell information of the device.
+ */
+ List<NeighboringCellInfo> getNeighboringCellInfo();
+
int getCallState();
int getDataActivity();
int getDataState();
diff --git a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index c558cd1..61d4c9f 100644
--- a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -16,15 +16,15 @@
package com.android.internal.telephony;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.util.Log;
import android.os.Handler;
import android.os.Message;
import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.util.Log;
/**
*
@@ -40,7 +40,6 @@ public final class PhoneStateIntentReceiver extends BroadcastReceiver {
private static final boolean DBG = false;
public static final String INTENT_KEY_ASU = "asu";
- public static final String INTENT_KEY_NUM = "incoming_number";
private static final int NOTIF_PHONE = 1 << 0;
private static final int NOTIF_SERVICE = 1 << 1;
@@ -49,7 +48,6 @@ public final class PhoneStateIntentReceiver extends BroadcastReceiver {
private static final int NOTIF_MAX = 1 << 5;
Phone.State mPhoneState = Phone.State.IDLE;
- String mIncomingNumber;
ServiceState mServiceState = new ServiceState();
int mAsu = -1;
private Context mContext;
@@ -141,7 +139,7 @@ public final class PhoneStateIntentReceiver extends BroadcastReceiver {
public void notifyPhoneCallState(int eventWhat) {
mWants |= NOTIF_PHONE;
mPhoneStateEventWhat = eventWhat;
- mFilter.addAction(TelephonyIntents.ACTION_PHONE_STATE_CHANGED);
+ mFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
}
public boolean getNotifyPhoneCallState() {
@@ -189,11 +187,10 @@ public final class PhoneStateIntentReceiver extends BroadcastReceiver {
Message message = Message.obtain(mTarget, mAsuEventWhat);
mTarget.sendMessage(message);
}
- } else if (TelephonyIntents.ACTION_PHONE_STATE_CHANGED.equals(action)) {
+ } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
if (DBG) Log.d(LOG_TAG, "onReceiveIntent: ACTION_PHONE_STATE_CHANGED, state="
+ intent.getStringExtra(Phone.STATE_KEY));
String phoneState = intent.getStringExtra(Phone.STATE_KEY);
- mIncomingNumber = intent.getStringExtra(INTENT_KEY_NUM);
mPhoneState = (Phone.State) Enum.valueOf(
Phone.State.class, phoneState);
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 8519796..9219e7a 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -10,26 +10,6 @@ package com.android.internal.telephony;
public class TelephonyIntents {
/**
- * <p>Broadcast Action: The phone state has changed. The intent will have the following
- * extra values:</p>
- * <ul>
- * <li><em>phoneName</em> - A string version of the phone name.</li>
- * <li><em>state</em> - A string version of the new phone state.</li>
- * </ul>
- *
- * <p class="note">
- * You can <em>not</em> receive this through components declared
- * in manifests, only by exlicitly registering for it with
- * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
- * android.content.IntentFilter) Context.registerReceiver()}.
- *
- * <p class="note">
- * Requires the READ_PHONE_STATE permission.
- */
- public static final String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
-
-
- /**
* Broadcast Action: The phone service state has changed. The intent will have the following
* extra values:</p>
* <ul>
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index c197734..6aa90f1 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -53,11 +53,7 @@ public interface TelephonyProperties
*/
static final String PROPERTY_OPERATOR_ISROAMING = "gsm.operator.isroaming";
- /** '1' if the current network is the result of a manual network selection.
- * Availability: when registered to a network
- */
- static final String PROPERTY_OPERATOR_ISMANUAL = "gsm.operator.ismanual";
- /** The ISO country code equivilent of the current registered operator's
+ /** The ISO country code equivalent of the current registered operator's
* MCC (Mobile Country Code)
* Availability: when registered to a network
*/
@@ -70,14 +66,6 @@ public interface TelephonyProperties
*/
static String PROPERTY_SIM_STATE = "gsm.sim.state";
- /** Set to '1' if voice mail is waiting, otherwise false */
- static String PROPERTY_LINE1_VOICE_MAIL_WAITING = "gsm.sim.voice-mail.waiting";
-
- /** Set to 'true' if unconditional voice call forwarding is enabled
- * Availablity: only if configured in SIM; SIM state must be "READY"
- */
- static String PROPERTY_LINE1_VOICE_CALL_FORWARDING = "gsm.sim.line1.cff";
-
/** The MCC+MNC (mobile country code+mobile network code) of the
* provider of the SIM. 5 or 6 decimal digits.
* Availablity: SIM state must be "READY"
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java b/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
index 9821852..afd11c4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
@@ -15,16 +15,32 @@
*/
package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
-import android.os.*;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_EDGE;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_GPRS;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UMTS;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UNKNOWN;
import android.os.AsyncResult;
-import android.util.Log;
-import android.provider.Checkin;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.telephony.gsm.GsmCellLocation;
+import android.util.EventLog;
+import android.util.Log;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.Phone;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
/**
* {@hide}
@@ -36,6 +52,9 @@ public final class CallTracker extends Handler
private static final boolean DBG_POLL = false;
+ // Event Log Tags
+ private static final int EVENT_LOG_CALL_DROP = 50106;
+
//***** Constants
static final int POLL_DELAY_MSEC = 250;
@@ -165,7 +184,7 @@ public final class CallTracker extends Handler
throw new CallStateException("cannot dial in current state");
}
- pendingMO = new GSMConnection(dialString, this, foregroundCall);
+ pendingMO = new GSMConnection(phone.getContext(), dialString, this, foregroundCall);
hangupPendingMO = false;
if (pendingMO.address == null || pendingMO.address.length() == 0
@@ -503,7 +522,7 @@ public final class CallTracker extends Handler
return;
}
} else {
- connections[i] = new GSMConnection(dc, this, i);
+ connections[i] = new GSMConnection(phone.getContext(), dc, this, i);
// it's a ringing call
if (connections[i].getCall() == ringingCall) {
@@ -540,7 +559,7 @@ public final class CallTracker extends Handler
// we were tracking. Assume dropped call and new call
droppedDuringPoll.add(conn);
- connections[i] = new GSMConnection (dc, this, i);
+ connections[i] = new GSMConnection (phone.getContext(), dc, this, i);
if (connections[i].getCall() == ringingCall) {
newRinging = connections[i];
@@ -916,6 +935,22 @@ public final class CallTracker extends Handler
} else {
causeCode = ((int[])ar.result)[0];
}
+ // Log the causeCode if its not normal
+ if (causeCode == CallFailCause.NO_CIRCUIT_AVAIL ||
+ causeCode == CallFailCause.TEMPORARY_FAILURE ||
+ causeCode == CallFailCause.SWITCHING_CONGESTION ||
+ causeCode == CallFailCause.CHANNEL_NOT_AVAIL ||
+ causeCode == CallFailCause.QOS_NOT_AVAIL ||
+ causeCode == CallFailCause.BEARER_NOT_AVAIL ||
+ causeCode == CallFailCause.ERROR_UNSPECIFIED) {
+ int cid = -1;
+ GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+ if (loc != null) cid = loc.getCid();
+
+ EventLog.List val = new EventLog.List(causeCode, cid,
+ TelephonyManager.getDefault().getNetworkType());
+ EventLog.writeEvent(EVENT_LOG_CALL_DROP, val);
+ }
for (int i = 0, s = droppedDuringPoll.size()
; i < s ; i++
diff --git a/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java b/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
index ececd72..c7b08d2 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
@@ -212,9 +212,9 @@ public interface CommandsInterface
*
* AsyncResult.result is an Object[]
* ((Object[])AsyncResult.result)[0] is a String containing the NITZ time string
- * ((Object[])AsyncResult.result)[0] is an Integer containing
- * the UNIX time_t returned by time() when
- * this NITZ time was posted.
+ * ((Object[])AsyncResult.result)[1] is a Long containing the milliseconds since boot as
+ * returned by elapsedRealtime() when this NITZ time
+ * was posted.
*
* Please note that the delivery of this message may be delayed several
* seconds on system startup
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
index 63d145e..b0b8cdc 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
@@ -16,8 +16,12 @@
package com.android.internal.telephony.gsm;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_EDGE;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_GPRS;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UMTS;
+import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UNKNOWN;
import android.app.AlarmManager;
-import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -40,14 +44,19 @@ import android.provider.Checkin;
import android.provider.Settings;
import android.provider.Telephony;
import android.provider.Settings.SettingNotFoundException;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.PdpConnection.PdpFailCause;
-
import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
-import android.text.TextUtils;
+import android.util.EventLog.List;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.gsm.PdpConnection.PdpFailCause;
+import android.net.wifi.WifiManager;
+import android.net.NetworkInfo;
+
import java.io.IOException;
import java.util.ArrayList;
@@ -66,12 +75,14 @@ final class DataConnectionTracker extends Handler
* SCANNING: data connection fails with one apn but other apns are available
* ready to start data connection on other apns (before INITING)
* CONNECTED: IP connection is setup
+ * DISCONNECTING: PdpConnection.disconnect() has been called, but PDP
+ * context is not yet deactivated
* FAILED: data connection fail for all apns settings
*
* getDataConnectionState() maps State to DataState
* FAILED or IDLE : DISCONNECTED
* INITING or CONNECTING or SCANNING: CONNECTING
- * CONNECTED : CONNECTED
+ * CONNECTED : CONNECTED or DISCONNECTING
*/
enum State {
IDLE,
@@ -79,6 +90,7 @@ final class DataConnectionTracker extends Handler
CONNECTING,
SCANNING,
CONNECTED,
+ DISCONNECTING,
FAILED
}
@@ -99,14 +111,7 @@ final class DataConnectionTracker extends Handler
@Override
public void onChange(boolean selfChange) {
- boolean isConnected;
-
- isConnected = (state != State.IDLE && state != State.FAILED);
- // TODO: It'd be nice to only do this if the changed entrie(s)
- // match the current operator.
- cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
- createAllApnList();
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+ sendMessage(obtainMessage(EVENT_APN_CHANGED));
}
}
@@ -172,6 +177,12 @@ final class DataConnectionTracker extends Handler
private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
+ // wifi connection status will be updated by sticky intent
+ private boolean mIsWifiConnected = false;
+
+ /** Intent sent when the reconnect alarm fires. */
+ private PendingIntent mReconnectIntent = null;
+
//***** Constants
// TODO: Increase this to match the max number of simultaneous
@@ -183,6 +194,8 @@ final class DataConnectionTracker extends Handler
private static final int POLL_PDP_MILLIS = 5 * 1000;
private static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
+ /** Cap out with 1 hour retry interval. */
+ private static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;
/** Slow poll when attempting connection recovery. */
private static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
@@ -215,13 +228,16 @@ final class DataConnectionTracker extends Handler
// represents an invalid IP address
private static final String NULL_IP = "0.0.0.0";
- static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
+ private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
+ private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+
//***** Tag IDs for EventLog
private static final int EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED = 50101;
private static final int EVENT_LOG_RADIO_RESET = 50102;
private static final int EVENT_LOG_PDP_RESET = 50103;
private static final int EVENT_LOG_REREGISTER_NETWORK = 50104;
+ private static final int EVENT_LOG_RADIO_PDP_SETUP_FAIL = 50105;
//***** Event Codes
static final int EVENT_DATA_SETUP_COMPLETE = 1;
@@ -244,37 +260,44 @@ final class DataConnectionTracker extends Handler
static final int EVENT_GPRS_ATTACHED = 26;
static final int EVENT_START_NETSTAT_POLL = 27;
static final int EVENT_START_RECOVERY = 28;
+ static final int EVENT_APN_CHANGED = 29;
- BroadcastReceiver screenOnOffReceiver = new BroadcastReceiver ()
+ BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
{
+ @Override
public void onReceive(Context context, Intent intent)
{
- if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_SCREEN_ON)) {
mIsScreenOn = true;
stopNetStatPoll();
startNetStatPoll();
- } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
+ } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
mIsScreenOn = false;
stopNetStatPoll();
startNetStatPoll();
- } else {
- Log.w(LOG_TAG, "DataConnectionTracker received unexpected Intent: " + intent.getAction());
- }
- }
- };
+ } else if (action.equals((INTENT_RECONNECT_ALARM))) {
+ Log.d(LOG_TAG, "GPRS reconnect alarm. Previous state was " + state);
- BroadcastReceiver alarmReceiver
- = new BroadcastReceiver () {
-
- public void onReceive(Context context, Intent intent)
- {
- Log.d(LOG_TAG, "GPRS reconnect alarm. Previous state was " + state);
-
- if (state == State.FAILED) {
- cleanUpConnection(false, null);
+ String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+ if (state == State.FAILED) {
+ cleanUpConnection(false, reason);
+ }
+ trySetupData(reason);
+ } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ final android.net.NetworkInfo networkInfo = (NetworkInfo)
+ intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
+ } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+
+ if (!enabled) {
+ // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION
+ // quit and wont report disconnected til next enalbing.
+ mIsWifiConnected = false;
+ }
}
-
- trySetupData(null);
}
};
@@ -301,13 +324,13 @@ final class DataConnectionTracker extends Handler
IntentFilter filter = new IntentFilter();
filter.addAction(INTENT_RECONNECT_ALARM);
- phone.getContext().registerReceiver(
- alarmReceiver, filter, null, phone.h);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+
+ phone.getContext().registerReceiver(mIntentReceiver, filter, null, phone.h);
- IntentFilter filterS = new IntentFilter();
- filterS.addAction(Intent.ACTION_SCREEN_ON);
- filterS.addAction(Intent.ACTION_SCREEN_OFF);
- phone.getContext().registerReceiver(screenOnOffReceiver, filterS);
mDataConnectionTracker = this;
mResolver = phone.getContext().getContentResolver();
@@ -326,6 +349,7 @@ final class DataConnectionTracker extends Handler
}
void setState(State s) {
+ if (DBG) log ("setState: " + s);
if (state != s) {
if (s == State.INITING) { // request PDP context
Checkin.updateStats(
@@ -347,6 +371,20 @@ final class DataConnectionTracker extends Handler
waitingApns.clear(); // when teardown the connection and set to IDLE
}
}
+
+ String getStateInString() {
+ switch (state) {
+ case IDLE: return "IDLE";
+ case INITING: return "INIT";
+ case CONNECTING: return "CING";
+ case SCANNING: return "SCAN";
+ case CONNECTED: return "CNTD";
+ case DISCONNECTING: return "DING";
+ case FAILED: return "FAIL";
+ default: return "ERRO";
+ }
+ }
+
String[] getActiveApnTypes() {
String[] result;
if (mActiveApn != null) {
@@ -394,7 +432,8 @@ final class DataConnectionTracker extends Handler
sendMessageDelayed(
obtainMessage(EVENT_RESTORE_DEFAULT_APN),
getRestoreDefaultApnDelay());
- return Phone.APN_ALREADY_ACTIVE;
+ if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
+ else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
}
if (!isApnTypeAvailable(type)) {
@@ -440,6 +479,27 @@ final class DataConnectionTracker extends Handler
return Phone.APN_REQUEST_FAILED;
}
}
+
+ /**
+ * The data connection is expected to be setup while device
+ * 1. has sim card
+ * 2. registered to gprs service
+ * 3. user doesn't explicitly disable data service
+ * 4. wifi is not on
+ *
+ * @return false while no data connection if all above requirements are met.
+ */
+ boolean isDataConnectionAsDesired() {
+ boolean roaming = phone.getServiceState().getRoaming();
+
+ if (phone.mSIMRecords.getRecordsLoaded() &&
+ phone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
+ (!roaming || getDataOnRoamingEnabled()) &&
+ !mIsWifiConnected ) {
+ return (state == State.CONNECTED);
+ }
+ return true;
+ }
private boolean isApnTypeActive(String type) {
// TODO: to support simultaneous, mActiveApn can be a List instead.
@@ -534,8 +594,8 @@ final class DataConnectionTracker extends Handler
// the shared values. If it is not, then update it.
public void setDataOnRoamingEnabled(boolean enabled) {
if (getDataOnRoamingEnabled() != enabled) {
- Settings.System.putInt(phone.getContext().getContentResolver(),
- Settings.System.DATA_ROAMING, enabled ? 1 : 0);
+ Settings.Secure.putInt(phone.getContext().getContentResolver(),
+ Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
}
Message roamingMsg = phone.getServiceState().getRoaming() ?
obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
@@ -545,8 +605,8 @@ final class DataConnectionTracker extends Handler
//Retrieve the data roaming setting from the shared preferences.
public boolean getDataOnRoamingEnabled() {
try {
- return Settings.System.getInt(phone.getContext().getContentResolver(),
- Settings.System.DATA_ROAMING) > 0;
+ return Settings.Secure.getInt(phone.getContext().getContentResolver(),
+ Settings.Secure.DATA_ROAMING) > 0;
} catch (SettingNotFoundException snfe) {
return false;
}
@@ -582,6 +642,10 @@ final class DataConnectionTracker extends Handler
startNetStatPoll();
phone.notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
} else {
+ if (state == State.FAILED) {
+ cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
+ nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+ }
trySetupData(Phone.REASON_GPRS_ATTACHED);
}
}
@@ -651,18 +715,45 @@ final class DataConnectionTracker extends Handler
*/
private void cleanUpConnection(boolean tearDown, String reason) {
if (DBG) log("Clean up connection due to " + reason);
+
+ // Clear the reconnect alarm, if set.
+ if (mReconnectIntent != null) {
+ AlarmManager am =
+ (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ am.cancel(mReconnectIntent);
+ mReconnectIntent = null;
+ }
+
for (PdpConnection pdp : pdpList) {
if (tearDown) {
- Message msg = obtainMessage(EVENT_DISCONNECT_DONE);
+ Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
pdp.disconnect(msg);
} else {
pdp.clearSettings();
}
}
stopNetStatPoll();
- setState(State.IDLE);
- phone.notifyDataConnection(reason);
- mActiveApn = null;
+
+ /*
+ * If we've been asked to tear down the connection,
+ * set the state to DISCONNECTING. However, there's
+ * a race that can occur if for some reason we were
+ * already in the IDLE state. In that case, the call
+ * to pdp.disconnect() above will immediately post
+ * a message to the handler thread that the disconnect
+ * is done, and if the handler runs before the code
+ * below does, the handler will have set the state to
+ * IDLE before the code below runs. If we didn't check
+ * for that, future calls to trySetupData would fail,
+ * and we would never get out of the DISCONNECTING state.
+ */
+ if (!tearDown) {
+ setState(State.IDLE);
+ phone.notifyDataConnection(reason);
+ mActiveApn = null;
+ } else if (state != State.IDLE) {
+ setState(State.DISCONNECTING);
+ }
}
/**
@@ -729,6 +820,7 @@ final class DataConnectionTracker extends Handler
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
+ msg.obj = reason;
pdp.connect(apn, msg);
setState(State.INITING);
@@ -789,6 +881,25 @@ final class DataConnectionTracker extends Handler
}
/**
+ * Handles changes to the APN database.
+ */
+ private void onApnChanged() {
+ boolean isConnected;
+
+ isConnected = (state != State.IDLE && state != State.FAILED);
+
+ // TODO: It'd be nice to only do this if the changed entrie(s)
+ // match the current operator.
+ createAllApnList();
+ if (state != State.DISCONNECTING) {
+ cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
+ if (!isConnected) {
+ trySetupData(Phone.REASON_APN_CHANGED);
+ }
+ }
+ }
+
+ /**
* @param explicitPoll if true, indicates that *we* polled for this
* update while state == CONNECTED rather than having it delivered
* via an unsolicited response (which could have happened at any
@@ -822,7 +933,6 @@ final class DataConnectionTracker extends Handler
Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
cleanUpConnection(true, null);
- trySetupData(null);
return;
}
@@ -855,16 +965,15 @@ final class DataConnectionTracker extends Handler
+ " Reconnecting");
cleanUpConnection(true, null);
- trySetupData(null);
}
}
}
}
- private void notifyDefaultData() {
+ private void notifyDefaultData(String reason) {
setupDnsProperties();
setState(State.CONNECTED);
- phone.notifyDataConnection(null);
+ phone.notifyDataConnection(reason);
startNetStatPoll();
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
@@ -949,7 +1058,7 @@ final class DataConnectionTracker extends Handler
private void
startNetStatPoll()
{
- if (state == State.CONNECTED && mPingTestActive == false) {
+ if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) {
Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
resetPollStats();
netStatPollEnabled = true;
@@ -1066,14 +1175,13 @@ final class DataConnectionTracker extends Handler
" pkts since last received");
// We've exceeded the threshold. Run ping test as a final check;
// it will proceed with recovery if ping fails.
- netStatPollEnabled = false;
stopNetStatPoll();
Thread pingTest = new Thread() {
public void run() {
- mPingTestActive = true;
runPingTest();
}
};
+ mPingTestActive = true;
pingTest.start();
}
} else {
@@ -1141,27 +1249,26 @@ final class DataConnectionTracker extends Handler
return (shouldPost && cause != PdpConnection.PdpFailCause.UNKNOWN);
}
- private void
- reconnectAfterFail(PdpConnection.PdpFailCause lastFailCauseCode)
- {
+ private void reconnectAfterFail(PdpFailCause lastFailCauseCode, String reason) {
if (state == State.FAILED) {
Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
- try {
- IAlarmManager am = IAlarmManager.Stub.asInterface(
- ServiceManager.getService(Context.ALARM_SERVICE));
- PendingIntent sender = PendingIntent.getBroadcast(
- phone.getContext(), 0,
- new Intent(INTENT_RECONNECT_ALARM), 0);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + nextReconnectDelay,
- sender);
- } catch (RemoteException ex) {
- }
+ AlarmManager am =
+ (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ Intent intent = new Intent(INTENT_RECONNECT_ALARM);
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
+ mReconnectIntent = PendingIntent.getBroadcast(
+ phone.getContext(), 0, intent, 0);
+ am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + nextReconnectDelay,
+ mReconnectIntent);
// double it for next time
nextReconnectDelay *= 2;
+ if (nextReconnectDelay > RECONNECT_DELAY_MAX_MILLIS) {
+ nextReconnectDelay = RECONNECT_DELAY_MAX_MILLIS;
+ }
if (!shouldPostNotification(lastFailCauseCode)) {
Log.d(LOG_TAG,"NOT Posting GPRS Unavailable notification "
@@ -1202,7 +1309,8 @@ final class DataConnectionTracker extends Handler
// cleanUpConnection if it needs to free up a PdpConnection.
reason = Phone.REASON_APN_SWITCHED;
cleanUpConnection(true, reason);
- // Fall through to EVENT_TRY_SETUP_DATA.
+ break;
+
case EVENT_TRY_SETUP_DATA:
trySetupData(reason);
break;
@@ -1213,7 +1321,6 @@ final class DataConnectionTracker extends Handler
if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
mRequestedApnType = Phone.APN_TYPE_DEFAULT;
- trySetupData(Phone.REASON_RESTORE_DEFAULT_APN );
}
break;
@@ -1272,6 +1379,9 @@ final class DataConnectionTracker extends Handler
case EVENT_DATA_SETUP_COMPLETE:
ar = (AsyncResult) msg.obj;
+ if (ar.userObj instanceof String) {
+ reason = (String) ar.userObj;
+ }
if (ar.exception == null) {
// everything is setup
@@ -1299,7 +1409,7 @@ final class DataConnectionTracker extends Handler
} else {
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
}
- notifyDefaultData();
+ notifyDefaultData(reason);
// TODO: For simultaneous PDP support, we need to build another
// trigger another TRY_SETUP_DATA for the next APN type. (Note
@@ -1310,7 +1420,23 @@ final class DataConnectionTracker extends Handler
cause = (PdpConnection.PdpFailCause) (ar.result);
if(DBG)
log("PDP setup failed " + cause);
-
+ // Log this failure to the Event Logs.
+ if (cause == PdpConnection.PdpFailCause.BAD_APN ||
+ cause == PdpConnection.PdpFailCause.BAD_PAP_SECRET ||
+ cause == PdpConnection.PdpFailCause.BARRED ||
+ cause == PdpConnection.PdpFailCause.RADIO_ERROR_RETRY ||
+ cause == PdpConnection.PdpFailCause.SUSPENED_TEMPORARY ||
+ cause == PdpConnection.PdpFailCause.UNKNOWN ||
+ cause == PdpConnection.PdpFailCause.USER_AUTHENTICATION) {
+ int cid = -1;
+ GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+ if (loc != null) cid = loc.getCid();
+
+ EventLog.List val = new EventLog.List(
+ cause.ordinal(), cid,
+ TelephonyManager.getDefault().getNetworkType());
+ EventLog.writeEvent(EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
+ }
// No try for permanent failure
if (cause.isPermanentFail()) {
notifyNoData(cause);
@@ -1320,23 +1446,28 @@ final class DataConnectionTracker extends Handler
waitingApns.remove(0);
if (waitingApns.isEmpty()) {
// No more to try, start delayed retry
- notifyNoData(cause);
- reconnectAfterFail(cause);
+ startDelayedRetry(cause, reason);
} else {
// we still have more apns to try
setState(State.SCANNING);
- trySetupData(null);
+ trySetupData(reason);
}
} else {
- notifyNoData(cause);
- reconnectAfterFail(cause);
+ startDelayedRetry(cause, reason);
}
}
break;
case EVENT_DISCONNECT_DONE:
if(DBG) log("EVENT_DISCONNECT_DONE");
- trySetupData(null);
+ ar = (AsyncResult) msg.obj;
+ if (ar.userObj instanceof String) {
+ reason = (String) ar.userObj;
+ }
+ setState(State.IDLE);
+ phone.notifyDataConnection(reason);
+ mActiveApn = null;
+ trySetupData(reason);
break;
case EVENT_PDP_STATE_CHANGED:
@@ -1375,15 +1506,17 @@ final class DataConnectionTracker extends Handler
break;
case EVENT_VOICE_CALL_ENDED:
- // in case data setup was attempted when we were on a voice call
- trySetupData(Phone.REASON_VOICE_CALL_ENDED);
- if (state == State.CONNECTED &&
- !phone.mSST.isConcurrentVoiceAndData()) {
- startNetStatPoll();
- phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
+ if (state == State.CONNECTED) {
+ if (!phone.mSST.isConcurrentVoiceAndData()) {
+ startNetStatPoll();
+ phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
+ } else {
+ // clean slate after call end.
+ resetPollStats();
+ }
} else {
- // clean slate after call end.
- resetPollStats();
+ // in case data setup was attempted when we were on a voice call
+ trySetupData(Phone.REASON_VOICE_CALL_ENDED);
}
break;
@@ -1396,6 +1529,10 @@ final class DataConnectionTracker extends Handler
mPingTestActive = false;
doRecovery();
break;
+
+ case EVENT_APN_CHANGED:
+ onApnChanged();
+ break;
}
}
@@ -1509,4 +1646,14 @@ final class DataConnectionTracker extends Handler
}
return result.toString();
}
+
+ private void startDelayedRetry(PdpConnection.PdpFailCause cause, String reason) {
+ notifyNoData(cause);
+ if (mRequestedApnType != Phone.APN_TYPE_DEFAULT) {
+ sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
+ }
+ else {
+ reconnectAfterFail(cause, reason);
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
index c316a23..43930c1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
@@ -16,7 +16,9 @@
package com.android.internal.telephony.gsm;
import com.android.internal.telephony.*;
+import android.content.Context;
import android.os.Handler;
+import android.os.PowerManager;
import android.os.Registrant;
import android.os.Looper;
import android.os.Message;
@@ -72,6 +74,8 @@ public class GSMConnection extends Connection {
Handler h;
+ private PowerManager.WakeLock mPartialWakeLock;
+
//***** Event Constants
static final int EVENT_DTMF_DONE = 1;
@@ -106,8 +110,11 @@ public class GSMConnection extends Connection {
/** This is probably an MT call that we first saw in a CLCC response */
/*package*/
- GSMConnection (DriverCall dc, CallTracker ct, int index)
+ GSMConnection (Context context, DriverCall dc, CallTracker ct, int index)
{
+ createWakeLock(context);
+ acquireWakeLock();
+
owner = ct;
h = new MyHandler(owner.getLooper());
@@ -124,8 +131,11 @@ public class GSMConnection extends Connection {
/** This is an MO call, created when dialing */
/*package*/
- GSMConnection (String dialString, CallTracker ct, GSMCall parent)
+ GSMConnection (Context context, String dialString, CallTracker ct, GSMCall parent)
{
+ createWakeLock(context);
+ acquireWakeLock();
+
owner = ct;
h = new MyHandler(owner.getLooper());
@@ -412,6 +422,7 @@ public class GSMConnection extends Connection {
parent.connectionDisconnected(this);
}
}
+ releaseWakeLock();
}
// Returns true if state has changed, false if nothing changed
@@ -513,6 +524,7 @@ public class GSMConnection extends Connection {
// outgoing calls only
processNextPostDialChar();
}
+ releaseWakeLock();
}
private void
@@ -574,6 +586,21 @@ public class GSMConnection extends Connection {
return postDialString.substring(nextPostDialChar);
}
+ @Override
+ protected void finalize()
+ {
+ /**
+ * It is understood that This finializer is not guaranteed
+ * to be called and the release lock call is here just in
+ * case there is some path that doesn't call onDisconnect
+ * and or onConnectedInOrOut.
+ */
+ if (mPartialWakeLock.isHeld()) {
+ Log.e(LOG_TAG, "[GSMConn] UNEXPECTED; mPartialWakeLock is held when finalizing.");
+ }
+ releaseWakeLock();
+ }
+
private void
processNextPostDialChar()
{
@@ -672,6 +699,28 @@ public class GSMConnection extends Connection {
}
}
+ private void
+ createWakeLock(Context context) {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
+ }
+
+ private void
+ acquireWakeLock() {
+ log("acquireWakeLock");
+ mPartialWakeLock.acquire();
+ }
+
+ private void
+ releaseWakeLock() {
+ synchronized(mPartialWakeLock) {
+ if (mPartialWakeLock.isHeld()) {
+ log("releaseWakeLock");
+ mPartialWakeLock.release();
+ }
+ }
+ }
+
private void log(String msg) {
Log.d(LOG_TAG, "[GSMConn] " + msg);
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index f2e5799..3f4bb5c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -16,29 +16,58 @@
package com.android.internal.telephony.gsm;
-import android.content.*;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_DISABLE;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_ENABLE;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_ERASURE;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_REGISTRATION;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_ALL;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_BUSY;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_NOT_REACHABLE;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_NO_REPLY;
+import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_UNCONDITIONAL;
+import static com.android.internal.telephony.gsm.CommandsInterface.SERVICE_CLASS_VOICE;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
import android.database.SQLException;
-import android.os.*;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Telephony;
-import com.android.internal.telephony.*;
-import com.android.internal.telephony.gsm.stk.Service;
-import static com.android.internal.telephony.gsm.CommandsInterface.*;
-
-import com.android.internal.telephony.test.SimulatedRadioControl;
-import android.text.TextUtils;
-import android.util.Log;
-import static com.android.internal.telephony.TelephonyProperties.*;
-import android.net.Uri;
-import android.telephony.PhoneNumberUtils;
import android.telephony.CellLocation;
+import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+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.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneSubInfo;
+import com.android.internal.telephony.SimCard;
+import com.android.internal.telephony.gsm.SimException;
+import com.android.internal.telephony.gsm.stk.Service;
+import com.android.internal.telephony.test.SimulatedRadioControl;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
/**
* {@hide}
@@ -58,7 +87,10 @@ public class GSMPhone extends PhoneBase {
public static final String CIPHERING_KEY = "ciphering_key";
// Key used to read/write current CLIR setting
public static final String CLIR_KEY = "clir_key";
-
+ // Key used to read/write voice mail number
+ public static final String VM_NUMBER = "vm_number_key";
+ // Key used to read/write the SIM IMSI used for storing the voice mail
+ public static final String VM_SIM_IMSI = "vm_sim_imsi_key";
//***** Instance Variables
@@ -91,6 +123,7 @@ public class GSMPhone extends PhoneBase {
private String mImei;
private String mImeiSv;
+ private String mVmNumber;
//***** Event Constants
@@ -115,6 +148,7 @@ public class GSMPhone extends PhoneBase {
static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 16;
static final int EVENT_SET_CLIR_COMPLETE = 17;
static final int EVENT_REGISTERED_TO_NETWORK = 18;
+ static final int EVENT_SET_VM_NUMBER_DONE = 19;
//***** Constructors
@@ -275,11 +309,13 @@ public class GSMPhone extends PhoneBase {
break;
case CONNECTED:
+ case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData())
+ && !mSST.isConcurrentVoiceAndData()) {
ret = DataState.SUSPENDED;
- else
+ } else {
ret = DataState.CONNECTED;
+ }
break;
case INITING:
@@ -731,8 +767,10 @@ public class GSMPhone extends PhoneBase {
if (handleInCallMmiCommands(newDialString)) {
return null;
}
-
- GsmMmiCode mmi = GsmMmiCode.newFromDialString(newDialString, this);
+
+ // Only look at the Network portion for mmi
+ String networkPortion = PhoneNumberUtils.extractNetworkPortion(newDialString);
+ GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this);
if (LOCAL_DEBUG) Log.d(LOG_TAG,
"dialing w/ mmi '" + mmi + "'...");
@@ -802,11 +840,36 @@ public class GSMPhone extends PhoneBase {
mSST.setRadioPower(power);
}
+ private void storeVoiceMailNumber(String number) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putString(VM_NUMBER, number);
+ editor.commit();
+ setVmSimImsi(getSubscriberId());
+ }
public String getVoiceMailNumber() {
- return mSIMRecords.getVoiceMailNumber();
+ // Read from the SIM. If its null, try reading from the shared preference area.
+ String number = mSIMRecords.getVoiceMailNumber();
+ if (TextUtils.isEmpty(number)) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ number = sp.getString(VM_NUMBER, null);
+ }
+ return number;
+ }
+
+ private String getVmSimImsi() {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ return sp.getString(VM_SIM_IMSI, null);
}
+ private void setVmSimImsi(String imsi) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putString(VM_SIM_IMSI, imsi);
+ editor.commit();
+ }
+
public String getVoiceMailAlphaTag() {
String ret;
@@ -860,7 +923,11 @@ public class GSMPhone extends PhoneBase {
public void setVoiceMailNumber(String alphaTag,
String voiceMailNumber,
Message onComplete) {
- mSIMRecords.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
+
+ Message resp;
+ mVmNumber = voiceMailNumber;
+ resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
+ mSIMRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
@@ -1301,6 +1368,13 @@ public class GSMPhone extends PhoneBase {
} catch (SQLException e) {
Log.e(LOG_TAG, "Can't store current operator", e);
}
+ // Check if this is a different SIM than the previous one. If so unset the
+ // voice mail number.
+ String imsi = getVmSimImsi();
+ if (imsi != null && !getSubscriberId().equals(imsi)) {
+ storeVoiceMailNumber(null);
+ setVmSimImsi(null);
+ }
break;
@@ -1380,7 +1454,21 @@ public class GSMPhone extends PhoneBase {
onComplete.sendToTarget();
}
break;
+
+ case EVENT_SET_VM_NUMBER_DONE:
+ ar = (AsyncResult)msg.obj;
+ if (SimVmNotSupportedException.class.isInstance(ar.exception)) {
+ storeVoiceMailNumber(mVmNumber);
+ ar.exception = null;
+ }
+ onComplete = (Message) ar.userObj;
+ if (onComplete != null) {
+ AsyncResult.forMessage(onComplete, ar.result, ar.exception);
+ onComplete.sendToTarget();
+ }
+ break;
+
case EVENT_GET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
index 7baaeca..59a9422 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
@@ -495,7 +495,7 @@ public class GsmAlphabet
countGsmSeptets(char c)
{
try {
- return countGsmSeptets(c, true);
+ return countGsmSeptets(c, false);
} catch (EncodeException ex) {
// This should never happen.
return 0;
@@ -535,7 +535,7 @@ public class GsmAlphabet
countGsmSeptets(String s)
{
try {
- return countGsmSeptets(s, true);
+ return countGsmSeptets(s, false);
} catch (EncodeException ex) {
// this should never happen
return 0;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index c85fb7c..ce6c186 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -197,7 +197,7 @@ public final class GsmMmiCode extends Handler implements MmiCode
ret = new GsmMmiCode(phone);
ret.dialingNumber = dialString;
}
-
+
return ret;
}
@@ -621,21 +621,21 @@ public final class GsmMmiCode extends Handler implements MmiCode
throw new RuntimeException ("invalid action");
}
- int isSettingUnconditionalVoice = (
- (reason == CommandsInterface.CF_REASON_UNCONDITIONAL) &&
- ((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0)
- ) ? 1 : 0;
+ int isSettingUnconditionalVoice =
+ ((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) &&
+ (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
+ (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
int isEnableDesired =
- ((cfAction == CommandsInterface.CF_ACTION_ENABLE)
- || (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
-
- phone.mCM.setCallForward(cfAction, reason,
- serviceClass, dialingNumber, time,
- obtainMessage(EVENT_SET_CFF_COMPLETE,
- isSettingUnconditionalVoice,
- isEnableDesired,
- this));
+ ((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||
+ (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
+
+ Log.d(LOG_TAG, "is CF setCallForward");
+ phone.mCM.setCallForward(cfAction, reason, serviceClass,
+ dialingNumber, time, obtainMessage(
+ EVENT_SET_CFF_COMPLETE,
+ isSettingUnconditionalVoice,
+ isEnableDesired, this));
}
} else if (isServiceCodeCallBarring(sc)) {
// sia = password
@@ -711,6 +711,10 @@ public final class GsmMmiCode extends Handler implements MmiCode
} else if (pinLen < 4 || pinLen > 8 ) {
// invalid length
handlePasswordError(com.android.internal.R.string.invalidPin);
+ } else if (sc.equals(SC_PIN) &&
+ phone.mSimCard.getState() == SimCard.State.PUK_REQUIRED ) {
+ // Sim is puk-locked
+ handlePasswordError(com.android.internal.R.string.needPuk);
} else {
// pre-checks OK
if (sc.equals(SC_PIN)) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/MccTable.java b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
index 57aa012..8f6b22e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
@@ -33,12 +33,23 @@ public final class MccTable
int mcc;
String iso;
int smallestDigitsMnc;
+ String timezone;
+ String language;
- MccEntry(int mnc, String iso, int smallestDigitsMCC)
- {
+ MccEntry(int mnc, String iso, int smallestDigitsMCC) {
+ this(mnc, iso, smallestDigitsMCC, null);
+ }
+
+ MccEntry(int mnc, String iso, int smallestDigitsMCC, String timezone) {
+ this(mnc, iso, smallestDigitsMCC, timezone, null);
+ }
+
+ MccEntry(int mnc, String iso, int smallestDigitsMCC, String timezone, String language) {
this.mcc = mnc;
this.iso = iso;
this.smallestDigitsMnc = smallestDigitsMCC;
+ this.timezone = timezone;
+ this.language = language;
}
public int compareTo(MccEntry o)
@@ -66,6 +77,23 @@ public final class MccTable
}
/**
+ * Returns a default time zone ID for the given MCC.
+ * @param mcc Mobile Country Code
+ * @return default TimeZone ID, or null if not specified
+ */
+ /* package */ static String defaultTimeZoneForMcc(int mcc) {
+ MccEntry entry;
+
+ entry = entryForMcc(mcc);
+
+ if (entry == null) {
+ return null;
+ } else {
+ return entry.timezone;
+ }
+ }
+
+ /**
* Given a GSM Mobile Country Code, returns
* an ISO two-character country code if available.
* Returns "" if unavailable.
@@ -84,6 +112,22 @@ public final class MccTable
}
}
+ /**
+ * Given a GSM Mobile Country Code, returns
+ * an ISO 2-3 character language code if available.
+ * Returns null if unavailable.
+ */
+ /* package */ static String defaultLanguageForMcc(int mcc) {
+ MccEntry entry;
+
+ entry = entryForMcc(mcc);
+
+ if (entry == null) {
+ return null;
+ } else {
+ return entry.language;
+ }
+ }
/**
* Given a GSM Mobile Country Code, returns
@@ -125,7 +169,7 @@ public final class MccTable
*/
table.add(new MccEntry(202,"gr",2)); //Greece
- table.add(new MccEntry(204,"nl",2)); //Netherlands (Kingdom of the)
+ table.add(new MccEntry(204,"nl",2,"Europe/Amsterdam")); //Netherlands (Kingdom of the)
table.add(new MccEntry(206,"be",2)); //Belgium
table.add(new MccEntry(208,"fr",2)); //France
table.add(new MccEntry(212,"mc",2)); //Monaco (Principality of)
@@ -139,11 +183,11 @@ public final class MccTable
table.add(new MccEntry(225,"va",2)); //Vatican City State
table.add(new MccEntry(226,"ro",2)); //Romania
table.add(new MccEntry(228,"ch",2)); //Switzerland (Confederation of)
- table.add(new MccEntry(230,"cz",2)); //Czech Republic
+ table.add(new MccEntry(230,"cz",2,"Europe/Prague")); //Czech Republic
table.add(new MccEntry(231,"sk",2)); //Slovak Republic
- table.add(new MccEntry(232,"at",2)); //Austria
- table.add(new MccEntry(234,"gb",2)); //United Kingdom of Great Britain and Northern Ireland
- table.add(new MccEntry(235,"gb",2)); //United Kingdom of Great Britain and Northern Ireland
+ table.add(new MccEntry(232,"at",2,"Europe/Vienna","de")); //Austria
+ table.add(new MccEntry(234,"gb",2,"Europe/London","en")); //United Kingdom of Great Britain and Northern Ireland
+ table.add(new MccEntry(235,"gb",2,"Europe/London","en")); //United Kingdom of Great Britain and Northern Ireland
table.add(new MccEntry(238,"dk",2)); //Denmark
table.add(new MccEntry(240,"se",2)); //Sweden
table.add(new MccEntry(242,"no",2)); //Norway
@@ -155,8 +199,8 @@ public final class MccTable
table.add(new MccEntry(255,"ua",2)); //Ukraine
table.add(new MccEntry(257,"by",2)); //Belarus (Republic of)
table.add(new MccEntry(259,"md",2)); //Moldova (Republic of)
- table.add(new MccEntry(260,"pl",2)); //Poland (Republic of)
- table.add(new MccEntry(262,"de",2)); //Germany (Federal Republic of)
+ table.add(new MccEntry(260,"pl",2,"Europe/Warsaw")); //Poland (Republic of)
+ table.add(new MccEntry(262,"de",2,"Europe/Berlin","de")); //Germany (Federal Republic of)
table.add(new MccEntry(266,"gi",2)); //Gibraltar
table.add(new MccEntry(268,"pt",2)); //Portugal
table.add(new MccEntry(270,"lu",2)); //Luxembourg
@@ -177,13 +221,13 @@ public final class MccTable
table.add(new MccEntry(295,"li",2)); //Liechtenstein (Principality of)
table.add(new MccEntry(302,"ca",2)); //Canada
table.add(new MccEntry(308,"pm",2)); //Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)
- table.add(new MccEntry(310,"us",3)); //United States of America
- table.add(new MccEntry(311,"us",3)); //United States of America
- table.add(new MccEntry(312,"us",3)); //United States of America
- table.add(new MccEntry(313,"us",3)); //United States of America
- table.add(new MccEntry(314,"us",3)); //United States of America
- table.add(new MccEntry(315,"us",3)); //United States of America
- table.add(new MccEntry(316,"us",3)); //United States of America
+ table.add(new MccEntry(310,"us",3,"","en")); //United States of America
+ table.add(new MccEntry(311,"us",3,"","en")); //United States of America
+ table.add(new MccEntry(312,"us",3,"","en")); //United States of America
+ table.add(new MccEntry(313,"us",3,"","en")); //United States of America
+ table.add(new MccEntry(314,"us",3,"","en")); //United States of America
+ table.add(new MccEntry(315,"us",3,"","en")); //United States of America
+ table.add(new MccEntry(316,"us",3,"","en")); //United States of America
table.add(new MccEntry(330,"pr",2)); //Puerto Rico
table.add(new MccEntry(332,"vi",2)); //United States Virgin Islands
table.add(new MccEntry(334,"mx",3)); //Mexico
@@ -254,12 +298,12 @@ public final class MccTable
table.add(new MccEntry(470,"bd",2)); //Bangladesh (People's Republic of)
table.add(new MccEntry(472,"mv",2)); //Maldives (Republic of)
table.add(new MccEntry(502,"my",2)); //Malaysia
- table.add(new MccEntry(505,"au",2)); //Australia
+ table.add(new MccEntry(505,"au",2,"Australia/Sydney","en")); //Australia
table.add(new MccEntry(510,"id",2)); //Indonesia (Republic of)
table.add(new MccEntry(514,"tl",2)); //Democratic Republic of Timor-Leste
table.add(new MccEntry(515,"ph",2)); //Philippines (Republic of the)
table.add(new MccEntry(520,"th",2)); //Thailand
- table.add(new MccEntry(525,"sg",2)); //Singapore (Republic of)
+ table.add(new MccEntry(525,"sg",2,"Singapore","en")); //Singapore (Republic of)
table.add(new MccEntry(528,"bn",2)); //Brunei Darussalam
table.add(new MccEntry(530,"nz",2)); //New Zealand
table.add(new MccEntry(534,"mp",2)); //Northern Mariana Islands (Commonwealth of the)
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 79e48f9..6428f70 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -19,10 +19,12 @@ package com.android.internal.telephony.gsm;
import android.os.*;
import android.database.Cursor;
import android.provider.Telephony;
+import android.text.util.Regex;
import android.util.EventLog;
import android.util.Log;
import java.util.ArrayList;
+import com.android.internal.telephony.Phone;
/**
* {@hide}
@@ -204,6 +206,9 @@ public class PdpConnection extends Handler {
}
} else if (state == PdpState.ACTIVATING) {
receivedDisconnectReq = true;
+ } else {
+ // state == INACTIVE. Nothing to do, so notify immediately.
+ notifyDisconnect(msg);
}
}
@@ -395,6 +400,8 @@ public class PdpConnection extends Handler {
// Don't bother reporting success if there's already a
// pending disconnect request, since DataConnectionTracker
// has already updated its state.
+ // Set ACTIVE so that disconnect does the right thing.
+ state = PdpState.ACTIVE;
disconnect(onDisconnect);
} else {
String[] response = ((String[]) ar.result);
@@ -416,10 +423,16 @@ public class PdpConnection extends Handler {
if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])) {
// Work around a race condition where QMI does not fill in DNS:
// Deactivate PDP and let DataConnectionTracker retry.
- EventLog.writeEvent(EVENT_LOG_BAD_DNS_ADDRESS, dnsServers[0]);
- phone.mCM.deactivateDefaultPDP(cid,
- obtainMessage(EVENT_FORCE_RETRY));
- break;
+ // Do not apply the race condition workaround for MMS APN
+ // if Proxy is an IP-address.
+ // Otherwise, the default APN will not be restored anymore.
+ if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
+ || !isIpAddress(apn.mmsProxy)) {
+ EventLog.writeEvent(EVENT_LOG_BAD_DNS_ADDRESS, dnsServers[0]);
+ phone.mCM.deactivateDefaultPDP(cid,
+ obtainMessage(EVENT_FORCE_RETRY));
+ break;
+ }
}
}
@@ -470,4 +483,10 @@ public class PdpConnection extends Handler {
break;
}
}
+
+ private boolean isIpAddress(String address) {
+ if (address == null) return false;
+
+ return Regex.IP_ADDRESS_PATTERN.matcher(apn.mmsProxy).matches();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/RIL.java b/telephony/java/com/android/internal/telephony/gsm/RIL.java
index 6739fba..45000ba 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RIL.java
+++ b/telephony/java/com/android/internal/telephony/gsm/RIL.java
@@ -16,32 +16,32 @@
package com.android.internal.telephony.gsm;
+import static com.android.internal.telephony.gsm.RILConstants.*;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.BroadcastReceiver;
-import com.android.internal.telephony.*;
-import android.os.Parcel;
-import java.io.IOException;
-import android.os.Message;
-import android.os.Handler;
-import android.net.LocalSocketAddress;
import android.net.LocalSocket;
-import com.android.internal.os.HandlerThread;
-import android.os.HandlerInterface;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.io.InputStream;
+import android.net.LocalSocketAddress;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
import android.telephony.PhoneNumberUtils;
import android.telephony.gsm.SmsManager;
import android.telephony.gsm.SmsMessage;
-import android.util.Log;
+import android.telephony.NeighboringCellInfo;
import android.util.Config;
-import android.os.AsyncResult;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
+import android.util.Log;
-import static com.android.internal.telephony.gsm.RILConstants.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
/**
* {@hide}
@@ -160,7 +160,7 @@ class RILRequest
ex = CommandException.fromRilErrno(error);
- if (RIL.RILJ_LOG) Log.d(LOG_TAG, serialString() + "< "
+ if (RIL.RILJ_LOGD) Log.d(LOG_TAG, serialString() + "< "
+ RIL.requestToString(mRequest)
+ " error: " + ex);
@@ -186,15 +186,15 @@ class RILRequest
public final class RIL extends BaseCommands implements CommandsInterface
{
static final String LOG_TAG = "RILJ";
- private static final boolean DBG = true;
- static final boolean RILJ_LOG = true;
+ private static final boolean DBG = false;
+ static final boolean RILJ_LOGD = Config.LOGD;
+ static final boolean RILJ_LOGV = DBG ? Config.LOGD : Config.LOGV;
static int WAKE_LOCK_TIMEOUT = 5000;
//***** Instance Variables
LocalSocket mSocket;
- HandlerThread mSenderThread;
- Handler mSenderH;
+ HandlerThread mSenderThread;
RILSender mSender;
Thread mReceiverThread;
RILReceiver mReceiver;
@@ -239,8 +239,12 @@ public final class RIL extends BaseCommands implements CommandsInterface
}
};
- class RILSender implements HandlerInterface,Runnable
+ class RILSender extends Handler implements Runnable
{
+ public RILSender(Looper looper) {
+ super(looper);
+ }
+
// Only allocated once
byte[] dataLength = new byte[4];
@@ -341,7 +345,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
// TODO should we clean up mRequestList and mRequestPending
synchronized (mWakeLock) {
if (mWakeLock.isHeld()) {
- if (DBG) {
+ if (RILJ_LOGD) {
synchronized (mRequestsList) {
int count = mRequestsList.size();
Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " +
@@ -512,7 +516,8 @@ public final class RIL extends BaseCommands implements CommandsInterface
Log.i(LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed",
ex);
} catch (Throwable tr) {
- Log.e(LOG_TAG, "Uncaught exception read length=" + length, tr);
+ Log.e(LOG_TAG, "Uncaught exception read length=" + length +
+ "Exception:" + tr.toString());
}
Log.i(LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL
@@ -559,9 +564,13 @@ public final class RIL extends BaseCommands implements CommandsInterface
mRequestMessagesPending = 0;
mContext = context;
- mSender = new RILSender();
- mSenderThread = new HandlerThread(mSender, mSender, "RILSender");
- mSenderH = mSenderThread.getHandler();
+
+ mSenderThread = new HandlerThread("RILSender");
+ mSenderThread.start();
+
+ Looper looper = mSenderThread.getLooper();
+ mSender = new RILSender(looper);
+
mReceiver = new RILReceiver();
mReceiverThread = new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
@@ -593,7 +602,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -603,7 +612,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(1);
rr.mp.writeString(pin);
@@ -616,7 +625,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PUK, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(2);
rr.mp.writeString(puk);
@@ -630,7 +639,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN2, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(1);
rr.mp.writeString(pin);
@@ -643,7 +652,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PUK2, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(2);
rr.mp.writeString(puk);
@@ -657,7 +666,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(2);
rr.mp.writeString(oldPin);
@@ -671,7 +680,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN2, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(2);
rr.mp.writeString(oldPin2);
@@ -685,7 +694,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_BARRING_PASSWORD, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(3);
rr.mp.writeString(facility);
@@ -700,7 +709,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(1);
rr.mp.writeString(netpin);
@@ -713,7 +722,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -723,7 +732,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_PDP_CONTEXT_LIST, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -736,7 +745,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(address);
rr.mp.writeInt(clirMode);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -746,7 +755,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> getIMSI:RIL_REQUEST_GET_IMSI " + RIL_REQUEST_GET_IMSI + " " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> getIMSI:RIL_REQUEST_GET_IMSI " + RIL_REQUEST_GET_IMSI + " " + requestToString(rr.mRequest));
send(rr);
}
@@ -756,7 +765,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -766,7 +775,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEISV, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -775,11 +784,11 @@ public final class RIL extends BaseCommands implements CommandsInterface
public void
hangupConnection (int gsmIndex, Message result)
{
- if (RILJ_LOG) riljLog("hangupConnection: gsmIndex=" + gsmIndex);
+ if (RILJ_LOGD) riljLog("hangupConnection: gsmIndex=" + gsmIndex);
RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + gsmIndex);
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + gsmIndex);
rr.mp.writeInt(1);
rr.mp.writeInt(gsmIndex);
@@ -793,7 +802,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -805,7 +814,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(
RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -817,7 +826,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(
RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -828,7 +837,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_CONFERENCE, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -840,7 +849,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SEPARATE_CONNECTION, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + gsmIndex);
rr.mp.writeInt(1);
@@ -855,7 +864,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_ANSWER, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -866,7 +875,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_UDUB, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -877,7 +886,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_EXPLICIT_CALL_TRANSFER, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -888,7 +897,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -899,7 +908,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_LAST_PDP_FAIL_CAUSE, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -910,7 +919,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SET_MUTE, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + enableMute);
rr.mp.writeInt(1);
@@ -925,7 +934,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_GET_MUTE, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -936,7 +945,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -947,7 +956,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_REGISTRATION_STATE, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -958,7 +967,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_GPRS_REGISTRATION_STATE, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -969,7 +978,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_OPERATOR, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -980,7 +989,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_DTMF, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeString(Character.toString(c));
@@ -992,7 +1001,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_DTMF_START, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeString(Character.toString(c));
@@ -1004,7 +1013,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_DTMF_STOP, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1020,7 +1029,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(smscPDU);
rr.mp.writeString(pdu);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1032,9 +1041,9 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(index);
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog(rr.serialString() + "> "
- + requestToString(rr.mRequest)
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> "
+ + requestToString(rr.mRequest)
+ " " + index);
}
@@ -1051,8 +1060,8 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(pdu);
rr.mp.writeString(smsc);
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog(rr.serialString() + "> "
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest)
+ " " + status);
}
@@ -1091,7 +1100,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(user);
rr.mp.writeString(password);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " "
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " "
+ apn);
send(rr);
@@ -1106,7 +1115,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeString(Integer.toString(cid));
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + cid);
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + cid);
send(rr);
}
@@ -1120,7 +1129,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(on ? 1 : 0);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1134,10 +1143,8 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(enable ? 1 : 0);
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog(rr.serialString() + "> "
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest));
- }
send(rr);
}
@@ -1151,7 +1158,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(success ? 1 : 0);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1172,7 +1179,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(data);
rr.mp.writeString(pin2);
- if (RILJ_LOG) riljLog(rr.serialString() + "> simIO: " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> simIO: " + requestToString(rr.mRequest)
+ " 0x" + Integer.toHexString(command)
+ " 0x" + Integer.toHexString(fileid) + " "
+ p1 + "," + p2 + "," + p3);
@@ -1186,7 +1193,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_GET_CLIR, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1202,7 +1209,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(clirMode);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + clirMode);
send(rr);
@@ -1217,7 +1224,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(serviceClass);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + serviceClass);
send(rr);
@@ -1233,7 +1240,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(enable ? 1 : 0);
rr.mp.writeInt(serviceClass);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + enable + ", " + serviceClass);
send(rr);
@@ -1246,7 +1253,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1258,7 +1265,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + operatorNumeric);
rr.mp.writeString(operatorNumeric);
@@ -1273,7 +1280,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE,
response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1285,7 +1292,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS,
response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1304,7 +1311,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(number);
rr.mp.writeInt (timeSeconds);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + action + " " + cfReason + " " + serviceClass
+ timeSeconds);
@@ -1325,7 +1332,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeString(number);
rr.mp.writeInt (0);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + cfReason + " " + serviceClass);
send(rr);
@@ -1337,7 +1344,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_QUERY_CLIP, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1349,7 +1356,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_BASEBAND_VERSION, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1360,7 +1367,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_QUERY_FACILITY_LOCK, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
// count strings
rr.mp.writeInt(3);
@@ -1381,7 +1388,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
// count strings
rr.mp.writeInt(4);
@@ -1402,7 +1409,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SEND_USSD, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + ussdString);
rr.mp.writeString(ussdString);
@@ -1415,7 +1422,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_CANCEL_USSD, response);
- if (RILJ_LOG) riljLog(rr.serialString()
+ if (RILJ_LOGD) riljLog(rr.serialString()
+ "> " + requestToString(rr.mRequest));
send(rr);
@@ -1427,7 +1434,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_RESET_RADIO, result);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1437,7 +1444,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_OEM_HOOK_RAW, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ "[" + SimUtils.bytesToHexString(data) + "]");
rr.mp.writeByteArray(data);
@@ -1451,7 +1458,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_OEM_HOOK_STRINGS, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeStringArray(strings);
@@ -1471,7 +1478,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(bandMode);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + bandMode);
send(rr);
@@ -1489,7 +1496,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
= RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE,
response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1501,7 +1508,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeString(contents);
send(rr);
@@ -1514,7 +1521,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeString(contents);
send(rr);
@@ -1530,7 +1537,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILConstants.RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM,
response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
int[] param = new int[1];
param[0] = accept ? 1 : 0;
@@ -1548,7 +1555,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(networkType);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " : " + networkType);
send(rr);
@@ -1561,7 +1568,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1573,7 +1580,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, response);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1586,7 +1593,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(enable ? 1 : 0);
- if (RILJ_LOG) riljLog(rr.serialString() + "> "
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest) + ": " + enable);
send(rr);
@@ -1600,7 +1607,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
rr.mp.writeInt(1);
rr.mp.writeInt(on ? 1 : 0);
- if (RILJ_LOG) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ": " + on);
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ": " + on);
send(rr);
}
@@ -1640,7 +1647,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
* (eg, if it or the runtime crashed) without the RIL
* and/or radio knowing.
*/
- if (DBG) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
+ if (RILJ_LOGD) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
setRadioPower(false, null);
return;
}
@@ -1665,9 +1672,9 @@ public final class RIL extends BaseCommands implements CommandsInterface
mWakeLock.acquire();
mRequestMessagesPending++;
- mSenderH.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
- Message msg = mSenderH.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
- mSenderH.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT);
+ mSender.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
+ Message msg = mSender.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
+ mSender.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT);
}
}
@@ -1678,7 +1685,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
if (mWakeLock.isHeld() &&
(mRequestMessagesPending == 0) &&
(mRequestsList.size() == 0)) {
- mSenderH.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
+ mSender.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
mWakeLock.release();
}
}
@@ -1689,7 +1696,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
{
Message msg;
- msg = mSenderH.obtainMessage(EVENT_SEND, rr);
+ msg = mSender.obtainMessage(EVENT_SEND, rr);
acquireWakeLock();
@@ -1837,7 +1844,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break;
case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break;
case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseInts(p); break;
- case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseStrings(p); break;
+ case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break;
case RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break;
default:
@@ -1857,7 +1864,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
return;
}
- if (RILJ_LOG) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
+ " " + retToString(rr.mRequest, ret));
if (rr.mResult != null) {
@@ -1916,6 +1923,14 @@ public final class RIL extends BaseCommands implements CommandsInterface
sb.append("[").append(dc).append("] ");
}
s = sb.toString();
+ } else if (req == RIL_REQUEST_GET_NEIGHBORING_CELL_IDS) {
+ ArrayList<NeighboringCellInfo> cells;
+ cells = (ArrayList<NeighboringCellInfo>) ret;
+ sb = new StringBuilder(" ");
+ for (NeighboringCellInfo cell : cells) {
+ sb.append(cell).append(" ");
+ }
+ s = sb.toString();
} else {
s = ret.toString();
}
@@ -1959,8 +1974,8 @@ public final class RIL extends BaseCommands implements CommandsInterface
throw new RuntimeException("Unrecognized unsol response: " + response);
//break; (implied)
}} catch (Throwable tr) {
- Log.e(LOG_TAG, "Exception processing unsol response: "
- + response, tr);
+ Log.e(LOG_TAG, "Exception processing unsol response: " + response +
+ "Exception:" + tr.toString());
return;
}
@@ -1969,22 +1984,22 @@ public final class RIL extends BaseCommands implements CommandsInterface
/* has bonus radio state int */
setRadioStateFromRILInt(p.readInt());
- if (RILJ_LOG) riljLog("[UNSL]< RADIO_STATE_CHANGED " +mState);
+ if (RILJ_LOGD) unsljLogMore(response, mState.toString());
break;
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
- if (RILJ_LOG) riljLog("[UNSL]< CALL_STATE_CHANGED");
+ if (RILJ_LOGD) unsljLog(response);
mCallStateRegistrants
.notifyRegistrants(new AsyncResult(null, null, null));
break;
case RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED:
- if (RILJ_LOG) riljLog("[UNSL]< NETWORK_STATE_CHANGED");
+ if (RILJ_LOGD) unsljLog(response);
mNetworkStateRegistrants
.notifyRegistrants(new AsyncResult(null, null, null));
break;
case RIL_UNSOL_RESPONSE_NEW_SMS: {
- if (RILJ_LOG) riljLog("[UNSL]< NEW_SMS");
+ if (RILJ_LOGD) unsljLog(response);
// FIXME this should move up a layer
String a[] = new String[2];
@@ -2001,9 +2016,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
}
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< NEW_SMS_STATUS_REPORT " + ret);
- }
+ if (RILJ_LOGD) unsljLogRet(response, ret);
if (mSmsStatusRegistrant != null) {
mSmsStatusRegistrant.notifyRegistrant(
@@ -2011,7 +2024,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
}
break;
case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM:
- if (RILJ_LOG) riljLog("[UNSL]< NEW_SMS_ON_SIM" + retToString(response, ret));
+ if (RILJ_LOGD) unsljLogRet(response, ret);
int[] smsIndex = (int[])ret;
@@ -2021,7 +2034,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
notifyRegistrant(new AsyncResult(null, smsIndex, null));
}
} else {
- if (RILJ_LOG) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length "
+ if (RILJ_LOGD) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length "
+ smsIndex.length);
}
break;
@@ -2033,23 +2046,23 @@ public final class RIL extends BaseCommands implements CommandsInterface
resp[0] = ((String[])ret)[0];
resp[1] = null;
}
- if (RILJ_LOG) riljLog("[UNSL]< ON_USSD " + resp[0]);
+ if (RILJ_LOGD) unsljLogMore(response, resp[0]);
if (mUSSDRegistrant != null) {
mUSSDRegistrant.notifyRegistrant(
new AsyncResult (null, resp, null));
}
break;
case RIL_UNSOL_NITZ_TIME_RECEIVED:
- if (RILJ_LOG) riljLog("[UNSL]< NITZ_TIME_RECEIVED " + retToString(response, ret));
+ if (RILJ_LOGD) unsljLogRet(response, ret);
- // has bonus int containing time_t that the NITZ
+ // has bonus long containing milliseconds since boot that the NITZ
// time was received
- int nitzReceiveTime = p.readInt();
+ long nitzReceiveTime = p.readLong();
Object[] result = new Object[2];
result[0] = ret;
- result[1] = Integer.valueOf(nitzReceiveTime);
+ result[1] = Long.valueOf(nitzReceiveTime);
if (mNITZTimeRegistrant != null) {
@@ -2064,8 +2077,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
case RIL_UNSOL_SIGNAL_STRENGTH:
// Note this is set to "verbose" because it happens
// frequently
- if (Config.LOGV) Log.v(LOG_TAG, "[UNSL]< SIGNAL_STRENGTH "
- + retToString(response, ret));
+ if (RILJ_LOGV) unsljLogvRet(response, ret);
if (mSignalStrengthRegistrant != null) {
mSignalStrengthRegistrant.notifyRegistrant(
@@ -2073,17 +2085,14 @@ public final class RIL extends BaseCommands implements CommandsInterface
}
break;
case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED:
- if (RILJ_LOG) riljLog("[UNSL]< PDP_CONTEXT_CHANGED " + retToString(response, ret));
+ if (RILJ_LOGD) unsljLogRet(response, ret);
mPDPRegistrants
.notifyRegistrants(new AsyncResult(null, ret, null));
break;
case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< SUPP_SVC_NOTIFICATION "
- + retToString(response, ret));
- }
+ if (RILJ_LOGD) unsljLogRet(response, ret);
if (mSsnRegistrant != null) {
mSsnRegistrant.notifyRegistrant(
@@ -2092,9 +2101,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_STK_SESSION_END:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< STK_SESSION_END");
- }
+ if (RILJ_LOGD) unsljLog(response);
if (mStkSessionEndRegistrant != null) {
mStkSessionEndRegistrant.notifyRegistrant(
@@ -2103,10 +2110,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_STK_PROACTIVE_COMMAND:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< STK_PROACTIVE_COMMAND "
- + retToString(response, ret));
- }
+ if (RILJ_LOGD) unsljLogRet(response, ret);
if (mStkProCmdRegistrant != null) {
mStkProCmdRegistrant.notifyRegistrant(
@@ -2115,10 +2119,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_STK_EVENT_NOTIFY:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< STK_EVENT_NOTIFY "
- + retToString(response, ret));
- }
+ if (RILJ_LOGD) unsljLogRet(response, ret);
if (mStkEventRegistrant != null) {
mStkEventRegistrant.notifyRegistrant(
@@ -2127,10 +2128,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_STK_CALL_SETUP:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< STK_CALL_SETUP "
- + retToString(response, ret));
- }
+ if (RILJ_LOGD) unsljLogRet(response, ret);
if (mStkCallSetUpRegistrant != null) {
mStkCallSetUpRegistrant.notifyRegistrant(
@@ -2139,9 +2137,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_SIM_SMS_STORAGE_FULL:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< SIM_SMS_STORAGE_FULL");
- }
+ if (RILJ_LOGD) unsljLog(response);
if (mSimSmsFullRegistrant != null) {
mSimSmsFullRegistrant.notifyRegistrant();
@@ -2149,9 +2145,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_SIM_REFRESH:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< SIM_REFRESH " + retToString(response, ret));
- }
+ if (RILJ_LOGD) unsljLogRet(response, ret);
if (mSimRefreshRegistrant != null) {
mSimRefreshRegistrant.notifyRegistrant(
@@ -2160,9 +2154,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
break;
case RIL_UNSOL_CALL_RING:
- if (Config.LOGD) {
- if (RILJ_LOG) riljLog("[UNSL]< CALL_RING ");
- }
+ if (RILJ_LOGD) unsljLog(response);
if (mRingRegistrant != null) {
mRingRegistrant.notifyRegistrant();
@@ -2410,6 +2402,29 @@ public final class RIL extends BaseCommands implements CommandsInterface
return ret;
}
+ private Object
+ responseCellList(Parcel p)
+ {
+ int num;
+ ArrayList<NeighboringCellInfo> response;
+ NeighboringCellInfo cell;
+
+ num = p.readInt();
+ response = new ArrayList<NeighboringCellInfo>(num);
+
+ for (int i = 0 ; i < num ; i++) {
+ try {
+ int rssi = p.readInt();
+ int cid = Integer.valueOf(p.readString(), 16);
+ cell = new NeighboringCellInfo(rssi, cid);
+ response.add(cell);
+ } catch ( Exception e) {
+ }
+ }
+
+ return response;
+ }
+
static String
requestToString(int request)
@@ -2434,7 +2449,7 @@ public final class RIL extends BaseCommands implements CommandsInterface
case RIL_REQUEST_HANGUP: return "HANGUP";
case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: return "HANGUP_WAITING_OR_BACKGROUND";
case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: return "HANGUP_FOREGROUND_RESUME_BACKGROUND";
- case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: return "RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE";
+ case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: return "REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE";
case RIL_REQUEST_CONFERENCE: return "CONFERENCE";
case RIL_REQUEST_UDUB: return "UDUB";
case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: return "LAST_CALL_FAIL_CAUSE";
@@ -2486,21 +2501,74 @@ public final class RIL extends BaseCommands implements CommandsInterface
case RIL_REQUEST_DELETE_SMS_ON_SIM: return "DELETE_SMS_ON_SIM";
case RIL_REQUEST_SET_BAND_MODE: return "SET_BAND_MODE";
case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: return "QUERY_AVAILABLE_BAND_MODE";
- case RIL_REQUEST_STK_GET_PROFILE: return "RIL_REQUEST_STK_GET_PROFILE";
- case RIL_REQUEST_STK_SET_PROFILE: return "RIL_REQUEST_STK_SET_PROFILE";
- case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: return "RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND";
- case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: return "RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE";
- case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: return "RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM";
- case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: return "RIL_REQUEST_EXPLICIT_CALL_TRANSFER";
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: return "RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE";
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE";
- case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "RIL_REQUEST_GET_NEIGHBORING_CELL_IDS";
- case RIL_REQUEST_SET_LOCATION_UPDATES: return "RIL_REQUEST_SET_LOCATION_UPDATES";
+ case RIL_REQUEST_STK_GET_PROFILE: return "REQUEST_STK_GET_PROFILE";
+ case RIL_REQUEST_STK_SET_PROFILE: return "REQUEST_STK_SET_PROFILE";
+ case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: return "REQUEST_STK_SEND_ENVELOPE_COMMAND";
+ case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: return "REQUEST_STK_SEND_TERMINAL_RESPONSE";
+ case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: return "REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM";
+ case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: return "REQUEST_EXPLICIT_CALL_TRANSFER";
+ case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: return "REQUEST_SET_PREFERRED_NETWORK_TYPE";
+ case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "REQUEST_GET_PREFERRED_NETWORK_TYPE";
+ case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "REQUEST_GET_NEIGHBORING_CELL_IDS";
+ case RIL_REQUEST_SET_LOCATION_UPDATES: return "REQUEST_SET_LOCATION_UPDATES";
default: return "<unknown request>";
}
}
+ static String
+ responseToString(int request)
+ {
+/*
+ cat libs/telephony/ril_unsol_commands.h \
+ | egrep "^ *{RIL_" \
+ | sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/'
+*/
+ switch(request) {
+ case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
+ case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
+ case RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_NETWORK_STATE_CHANGED";
+ case RIL_UNSOL_RESPONSE_NEW_SMS: return "UNSOL_RESPONSE_NEW_SMS";
+ case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT";
+ case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: return "UNSOL_RESPONSE_NEW_SMS_ON_SIM";
+ case RIL_UNSOL_ON_USSD: return "UNSOL_ON_USSD";
+ case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST";
+ case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED";
+ case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH";
+ case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED: return "UNSOL_PDP_CONTEXT_LIST_CHANGED";
+ case RIL_UNSOL_SUPP_SVC_NOTIFICATION: return "UNSOL_SUPP_SVC_NOTIFICATION";
+ case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END";
+ case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND";
+ case RIL_UNSOL_STK_EVENT_NOTIFY: return "UNSOL_STK_EVENT_NOTIFY";
+ case RIL_UNSOL_STK_CALL_SETUP: return "UNSOL_STK_CALL_SETUP";
+ case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FULL";
+ case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH";
+ case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
+ default: return "<unknown reponse>";
+ }
+ }
+
private void riljLog(String msg) {
Log.d(LOG_TAG, msg);
}
+
+ private void riljLogv(String msg) {
+ Log.v(LOG_TAG, msg);
+ }
+
+ private void unsljLog(int response) {
+ riljLog("[UNSL]< " + responseToString(response));
+ }
+
+ private void unsljLogMore(int response, String more) {
+ riljLog("[UNSL]< " + responseToString(response) + " " + more);
+ }
+
+ private void unsljLogRet(int response, Object ret) {
+ riljLog("[UNSL]< " + responseToString(response) + " " + retToString(response, ret));
+ }
+
+ private void unsljLogvRet(int response, Object ret) {
+ riljLogv("[UNSL]< " + responseToString(response) + " " + retToString(response, ret));
+ }
+
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index ebbf501..75f56a3 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -16,14 +16,21 @@
package com.android.internal.telephony.gsm;
+import android.app.AlarmManager;
+import android.content.Context;
import android.os.AsyncResult;
import android.os.RegistrantList;
import android.os.Registrant;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemProperties;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
import java.util.ArrayList;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import java.util.Locale;
+import android.content.res.Configuration;
import static com.android.internal.telephony.TelephonyProperties.*;
import com.android.internal.telephony.SimCard;
@@ -149,6 +156,8 @@ public final class SIMRecords extends Handler implements SimConstants
private static final int EVENT_SIM_REFRESH = 31;
private static final int EVENT_GET_CFIS_DONE = 32;
+ private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
+
//***** Constructor
SIMRecords(GSMPhone phone)
@@ -199,7 +208,6 @@ public final class SIMRecords extends Handler implements SimConstants
adnCache.reset();
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_MAIL_WAITING, null);
phone.setSystemProperty(PROPERTY_SIM_OPERATOR_NUMERIC, null);
phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, null);
phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ISO_COUNTRY, null);
@@ -309,7 +317,7 @@ public final class SIMRecords extends Handler implements SimConstants
Message onComplete) {
if (isVoiceMailFixed) {
AsyncResult.forMessage((onComplete)).exception =
- new SimException("Voicemail number is fixed by operator");
+ new SimVmFixedException("Voicemail number is fixed by operator");
onComplete.sendToTarget();
return;
}
@@ -331,9 +339,9 @@ public final class SIMRecords extends Handler implements SimConstants
EF_EXT1, 1, null,
obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, onComplete));
- } else {
+ }else {
AsyncResult.forMessage((onComplete)).exception =
- new SimException("Update SIM voice mailbox error");
+ new SimVmNotSupportedException("Update SIM voice mailbox error");
onComplete.sendToTarget();
}
}
@@ -369,9 +377,6 @@ public final class SIMRecords extends Handler implements SimConstants
countVoiceMessages = countWaiting;
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_MAIL_WAITING,
- (countVoiceMessages != 0) ? "true" : "false");
-
phone.notifyMessageWaitingIndicator();
try {
@@ -437,9 +442,6 @@ public final class SIMRecords extends Handler implements SimConstants
callForwardingEnabled = enable;
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_CALL_FORWARDING,
- (callForwardingEnabled ? "true" : "false"));
-
phone.notifyCallForwardingIndicator();
try {
@@ -528,6 +530,73 @@ public final class SIMRecords extends Handler implements SimConstants
}
}
+ /**
+ * If the timezone is not already set, set it based on the MCC of the SIM.
+ * @param mcc Mobile Country Code of the SIM
+ */
+ private void setTimezoneFromMccIfNeeded(int mcc) {
+ String timezone = SystemProperties.get(TIMEZONE_PROPERTY);
+ if (timezone == null || timezone.length() == 0) {
+ String zoneId = MccTable.defaultTimeZoneForMcc(mcc);
+
+ if (zoneId != null && zoneId.length() > 0) {
+ // Set time zone based on MCC
+ AlarmManager alarm =
+ (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ alarm.setTimeZone(zoneId);
+ }
+ }
+ }
+
+ /**
+ * If the locale is not already set, set it based on the MCC of the SIM.
+ * @param mcc Mobile Country Code of the SIM
+ */
+ private void setLocaleFromMccIfNeeded(int mcc) {
+ String language = SystemProperties.get("persist.sys.language");
+ String country = SystemProperties.get("persist.sys.country");
+ Log.d(LOG_TAG,"setLocaleFromMcc");
+ if((language == null || language.length() == 0) && (country == null || country.length() == 0)) {
+ try {
+ language = MccTable.defaultLanguageForMcc(mcc);
+ country = MccTable.countryCodeForMcc(mcc).toUpperCase();
+ // try to find a good match
+ String[] locales = phone.getContext().getAssets().getLocales();
+ final int N = locales.length;
+ String bestMatch = null;
+ for(int i = 0; i < N; i++) {
+ Log.d(LOG_TAG," trying "+locales[i]);
+ if(locales[i]!=null && locales[i].length() >= 2 &&
+ locales[i].substring(0,2).equals(language)) {
+ if(locales[i].length() >= 5 &&
+ locales[i].substring(3,5).equals(country)) {
+ bestMatch = locales[i];
+ break;
+ } else if(bestMatch == null) {
+ bestMatch = locales[i];
+ }
+ }
+ }
+ Log.d(LOG_TAG," got bestmatch = "+bestMatch);
+ if(bestMatch != null) {
+ IActivityManager am = ActivityManagerNative.getDefault();
+ Configuration config = am.getConfiguration();
+
+ if(bestMatch.length() >= 5) {
+ config.locale = new Locale(bestMatch.substring(0,2),
+ bestMatch.substring(3,5));
+ } else {
+ config.locale = new Locale(bestMatch.substring(0,2));
+ }
+ config.userSetLocale = true;
+ am.updateConfiguration(config);
+ }
+ } catch (Exception e) {
+ // Intentionally left blank
+ }
+ }
+ }
+
//***** Overridden from Handler
public void handleMessage(Message msg)
{
@@ -554,7 +623,7 @@ public final class SIMRecords extends Handler implements SimConstants
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
- Log.e(LOG_TAG, "Exception querying IMSI", ar.exception);
+ Log.e(LOG_TAG, "Exception querying IMSI, Exception:" + ar.exception);
break;
}
@@ -571,6 +640,10 @@ public final class SIMRecords extends Handler implements SimConstants
phone.mSimCard.updateImsiConfiguration(imsi);
phone.mSimCard.broadcastSimStateChangedIntent(
SimCard.INTENT_VALUE_SIM_IMSI, null);
+
+ int mcc = Integer.parseInt(imsi.substring(0, 3));
+ setTimezoneFromMccIfNeeded(mcc);
+ setLocaleFromMccIfNeeded(mcc);
break;
case EVENT_GET_MBI_DONE:
@@ -716,8 +789,6 @@ public final class SIMRecords extends Handler implements SimConstants
countVoiceMessages = -1;
}
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_MAIL_WAITING,
- voiceMailWaiting ? "true" : "false");
phone.notifyMessageWaitingIndicator();
break;
@@ -747,9 +818,6 @@ public final class SIMRecords extends Handler implements SimConstants
countVoiceMessages = 0;
}
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_MAIL_WAITING,
- countVoiceMessages != 0
- ? "true" : "false");
phone.notifyMessageWaitingIndicator();
}
break;
@@ -831,9 +899,6 @@ public final class SIMRecords extends Handler implements SimConstants
callForwardingEnabled =
((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_CALL_FORWARDING,
- (callForwardingEnabled ? "true" : "false"));
-
phone.notifyCallForwardingIndicator();
}
break;
@@ -1010,6 +1075,7 @@ public final class SIMRecords extends Handler implements SimConstants
case EVENT_SIM_REFRESH:
isRecordLoadResponse = false;
ar = (AsyncResult)msg.obj;
+ if (DBG) log("Sim REFRESH with exception: " + ar.exception);
if (ar.exception == null) {
handleSimRefresh((int[])(ar.result));
}
@@ -1032,9 +1098,6 @@ public final class SIMRecords extends Handler implements SimConstants
// Refer TS 51.011 Section 10.3.46 for the content description
callForwardingEnabled = ((data[1] & 0x01) != 0);
- phone.setSystemProperty(PROPERTY_LINE1_VOICE_CALL_FORWARDING,
- (callForwardingEnabled ? "true" : "false"));
-
phone.notifyCallForwardingIndicator();
break;
@@ -1071,22 +1134,27 @@ public final class SIMRecords extends Handler implements SimConstants
}
}
- private void handleSimRefresh(int[] result) {
+ private void handleSimRefresh(int[] result) {
if (result == null || result.length == 0) {
+ if (DBG) log("handleSimRefresh without input");
return;
}
-
+
switch ((result[0])) {
case CommandsInterface.SIM_REFRESH_FILE_UPDATED:
- // result[1] contains the EFID of the updated file.
+ if (DBG) log("handleSimRefresh with SIM_REFRESH_FILE_UPDATED");
+ // result[1] contains the EFID of the updated file.
int efid = result[1];
handleFileUpdate(efid);
break;
case CommandsInterface.SIM_REFRESH_INIT:
+ if (DBG) log("handleSimRefresh with SIM_REFRESH_INIT");
// need to reload all files (that we care about)
+ adnCache.reset();
fetchSimRecords();
break;
case CommandsInterface.SIM_REFRESH_RESET:
+ if (DBG) log("handleSimRefresh with SIM_REFRESH_RESET");
phone.mCM.setRadioPower(false, null);
/* Note: no need to call setRadioPower(true). Assuming the desired
* radio power state is still ON (as tracked by ServiceStateTracker),
@@ -1098,6 +1166,7 @@ public final class SIMRecords extends Handler implements SimConstants
break;
default:
// unknown refresh operation
+ if (DBG) log("handleSimRefresh with unknown operation");
break;
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
index 258c058..daf4b9c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
@@ -33,6 +33,7 @@ import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.provider.Telephony;
+import android.provider.Settings;
import android.provider.Telephony.Sms.Intents;
import android.telephony.gsm.SmsMessage;
import android.telephony.gsm.SmsManager;
@@ -56,7 +57,7 @@ final class SMSDispatcher extends Handler {
private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;
/** Default number of SMS sent in checking period without uesr permit */
- private static final int DEFAULT_SMS_MAX_ALLOWED = 100;
+ private static final int DEFAULT_SMS_MAX_COUNT = 100;
/** Default timeout for SMS sent query */
private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
@@ -199,8 +200,14 @@ final class SMSDispatcher extends Handler {
mResolver = mContext.getContentResolver();
mCm = phone.mCM;
mSTracker = null;
- mCounter = new SmsCounter(DEFAULT_SMS_MAX_ALLOWED,
+
+ int check_period = Settings.Gservices.getInt(mResolver,
+ Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
DEFAULT_SMS_CHECK_PERIOD);
+ int max_count = Settings.Gservices.getInt(mResolver,
+ Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
+ DEFAULT_SMS_MAX_COUNT);
+ mCounter = new SmsCounter(max_count, check_period);
mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
@@ -245,8 +252,7 @@ final class SMSDispatcher extends Handler {
}
if (ar.exception != null) {
- Log.e(TAG, "Exception processing incoming SMS",
- ar.exception);
+ Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception);
return;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
index 1c337f9..a4b8b47 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
@@ -18,7 +18,6 @@ package com.android.internal.telephony.gsm;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISMANUAL;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
@@ -45,8 +44,10 @@ import android.provider.Telephony.Intents;
import android.telephony.gsm.GsmCellLocation;
import android.telephony.ServiceState;
import android.text.TextUtils;
+import android.util.Config;
import android.util.Log;
import android.util.TimeUtils;
+import android.util.EventLog;
import java.util.Arrays;
import java.util.Calendar;
@@ -130,6 +131,12 @@ final class ServiceStateTracker extends Handler
// SIMRecords object may not be instantiated yet.
private boolean mNeedToRegForSimLoaded;
+ // Started the recheck process after finding gprs should registerd but not
+ private boolean mStartedGprsRegCheck = false;
+ // Already sent the event-log for no gprs register
+ private boolean mReportedGprsNoReg = false;
+
+
// Keep track of SPN display rules, so we only broadcast intent if something changes.
private String curSpn = null;
private String curPlmn = null;
@@ -143,6 +150,9 @@ final class ServiceStateTracker extends Handler
// signal strength poll rate
static final int POLL_PERIOD_MILLIS = 20 * 1000;
+ // waiting period before recheck gprs and voice registration
+ static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
+
//***** Events
static final int EVENT_RADIO_STATE_CHANGED = 1;
@@ -163,7 +173,11 @@ final class ServiceStateTracker extends Handler
static final int EVENT_GET_PREFERRED_NETWORK_TYPE = 19;
static final int EVENT_SET_PREFERRED_NETWORK_TYPE = 20;
static final int EVENT_RESET_PREFERRED_NETWORK_TYPE = 21;
+ static final int EVENT_CHECK_REPORT_GPRS = 22;
+ // Event Log Tags
+ private static final int EVENT_LOG_CGREG_FAIL = 50107;
+ private static final int EVENT_DATA_STATE_RADIO_OFF = 50108;
//***** Time Zones
@@ -460,7 +474,7 @@ final class ServiceStateTracker extends Handler
ar = (AsyncResult) msg.obj;
String nitzString = (String)((Object[])ar.result)[0];
- int nitzReceiveTime = ((Integer)((Object[])ar.result)[1]).intValue();
+ long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue();
setTimeFromNITZString(nitzString, nitzReceiveTime);
break;
@@ -523,6 +537,23 @@ final class ServiceStateTracker extends Handler
cm.setPreferredNetworkType(toggledNetworkType, message);
break;
+ case EVENT_CHECK_REPORT_GPRS:
+ if (ss != null && !isGprsConsistant(gprsState, ss.getState())) {
+
+ // Can't register data sevice while voice service is ok
+ // i.e. CREG is ok while CGREG is not
+ // possible a network or baseband side error
+ int cid = -1;
+ GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+ if (loc != null) cid = loc.getCid();
+
+ EventLog.List val = new EventLog.List(ss.getOperatorNumeric(), cid);
+ EventLog.writeEvent(EVENT_LOG_CGREG_FAIL, val);
+ mReportedGprsNoReg = true;
+ }
+ mStartedGprsRegCheck = false;
+ break;
+
}
}
@@ -561,6 +592,14 @@ final class ServiceStateTracker extends Handler
) {
cm.setRadioPower(true, null);
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
+ DataConnectionTracker dcTracker = phone.mDataConnection;
+ if (! dcTracker.isDataConnectionAsDesired()) {
+
+ EventLog.List val = new EventLog.List(
+ dcTracker.getStateInString(),
+ (dcTracker.getAnyDataEnabled() ? 1 : 0) );
+ EventLog.writeEvent(EVENT_DATA_STATE_RADIO_OFF, val);
+ }
// If it's on and available and we want it off..
cm.setRadioPower(false, null);
} // Otherwise, we're in the desired state
@@ -609,7 +648,7 @@ final class ServiceStateTracker extends Handler
if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
Log.e(LOG_TAG,
- "RIL implementation has returned an error where it must succeed",
+ "RIL implementation has returned an error where it must succeed" +
ar.exception);
}
} else try {
@@ -882,8 +921,7 @@ final class ServiceStateTracker extends Handler
// need adjust time to reflect default timezone setting
long tzOffset;
tzOffset = zone.getOffset(System.currentTimeMillis());
- SystemClock.setCurrentTimeMillis(
- System.currentTimeMillis() - tzOffset);
+ setAndBroadcastNetworkSetTime(System.currentTimeMillis() - tzOffset);
} else if (iso.equals("")){
// Country code not found. This is likely a test network.
// Get a TimeZone based only on the NITZ parameters (best guess).
@@ -896,10 +934,8 @@ final class ServiceStateTracker extends Handler
mNeedFixZone = false;
if (zone != null) {
- Context context = phone.getContext();
if (getAutoTime()) {
- AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarm.setTimeZone(zone.getID());
+ setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
}
@@ -908,8 +944,6 @@ final class ServiceStateTracker extends Handler
phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
ss.getRoaming() ? "true" : "false");
- phone.setSystemProperty(PROPERTY_OPERATOR_ISMANUAL,
- ss.getIsManualSelection() ? "true" : "false");
updateSpnDisplay();
phone.notifyServiceStateChanged(ss);
@@ -938,8 +972,35 @@ final class ServiceStateTracker extends Handler
if (hasLocationChanged) {
phone.notifyLocationChanged();
}
+
+ if (! isGprsConsistant(gprsState, ss.getState())) {
+ if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
+ mStartedGprsRegCheck = true;
+
+ int check_period = Settings.Gservices.getInt(
+ phone.getContext().getContentResolver(),
+ Settings.Gservices.GPRS_REGISTER_CHECK_PERIOD_MS,
+ DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
+ sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
+ check_period);
+ }
+ } else {
+ mReportedGprsNoReg = false;
+ }
}
-
+
+ /**
+ * Check if GPRS got registred while voice is registered
+ *
+ * @param gprsState for GPRS registration state, i.e. CGREG in GSM
+ * @param serviceState for voice registration state, i.e. CREG in GSM
+ * @return false if device only register to voice but not gprs
+ */
+ private boolean isGprsConsistant (int gprsState, int serviceState) {
+ return !((serviceState == ServiceState.STATE_IN_SERVICE) &&
+ (gprsState != ServiceState.STATE_IN_SERVICE));
+ }
+
/**
* Returns a TimeZone object based only on parameters from the NITZ string.
*/
@@ -1162,13 +1223,14 @@ final class ServiceStateTracker extends Handler
*/
private
- void setTimeFromNITZString (String nitz, int nitzReceiveTime)
+ void setTimeFromNITZString (String nitz, long nitzReceiveTime)
{
// "yy/mm/dd,hh:mm:ss(+/-)tz"
// tz is in number of quarter-hours
- Log.i(LOG_TAG, "setTimeFromNITZString: " +
- nitz + "," + nitzReceiveTime);
+ long start = SystemClock.elapsedRealtime();
+ Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime +
+ " start=" + start + " delay=" + (start - nitzReceiveTime));
try {
/* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
@@ -1257,57 +1319,57 @@ final class ServiceStateTracker extends Handler
}
if (zone != null) {
- Context context = phone.getContext();
if (getAutoTime()) {
- AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarm.setTimeZone(zone.getID());
+ setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
}
-
- long millisSinceNitzReceived
- = System.currentTimeMillis() - (nitzReceiveTime * 1000L);
-
- if (millisSinceNitzReceived < 0) {
- // Sanity check: something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
- + "backwards since NITZ time received, "
- + nitz);
- return;
- }
-
- if (millisSinceNitzReceived > (1000L * 1000L)) {
- // If the time is this far off, something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, more than 1000 seconds "
- + " have elapsed since time received, "
- + nitz);
-
- return;
- }
-
- // Note: with range checks above, cast to int is safe
- c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
-
+
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
- Log.i(LOG_TAG,
- "Not setting clock because gsm.ignore-nitz is set");
+ Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
return;
}
if (getAutoTime()) {
- Log.i(LOG_TAG, "Setting time of day to " + c.getTime()
+ long millisSinceNitzReceived
+ = SystemClock.elapsedRealtime() - nitzReceiveTime;
+
+ if (millisSinceNitzReceived < 0) {
+ // Sanity check: something is wrong
+ Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ + "backwards since NITZ time was received, "
+ + nitz);
+ return;
+ }
+
+ if (millisSinceNitzReceived > Integer.MAX_VALUE) {
+ // If the time is this far off, something is wrong > 24 days!
+ Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ + (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ + " days");
+ return;
+ }
+
+ // Note: with range checks above, cast to int is safe
+ c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
+
+ Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime()
+ " NITZ receive delay(ms): " + millisSinceNitzReceived
+ " gained(ms): "
+ (c.getTimeInMillis() - System.currentTimeMillis())
+ " from " + nitz);
- SystemClock.setCurrentTimeMillis(c.getTimeInMillis());
+ setAndBroadcastNetworkSetTime(c.getTimeInMillis());
}
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
saveNitzTime(c.getTimeInMillis());
+ if (Config.LOGV) {
+ long end = SystemClock.elapsedRealtime();
+ Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ }
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "Parsing NITZ time " + nitz, ex);
+ Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
}
}
@@ -1319,26 +1381,44 @@ final class ServiceStateTracker extends Handler
return true;
}
}
-
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
- // Send out a sticky broadcast so the system can determine if
- // the timezone was set by the carrier...
- Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
- intent.putExtra("time-zone", zoneId);
- phone.getContext().sendStickyBroadcast(intent);
}
-
+
private void saveNitzTime(long time) {
mSavedTime = time;
mSavedAtTime = SystemClock.elapsedRealtime();
- // Send out a sticky broadcast so the system can determine if
- // the time was set by the carrier...
+ }
+
+ /**
+ * Set the timezone and send out a sticky broadcast so the system can
+ * determine if the timezone was set by the carrier.
+ *
+ * @param zoneId timezone set by carrier
+ */
+ private void setAndBroadcastNetworkSetTimeZone(String zoneId) {
+ AlarmManager alarm =
+ (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ alarm.setTimeZone(zoneId);
+ Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
+ intent.putExtra("time-zone", zoneId);
+ phone.getContext().sendStickyBroadcast(intent);
+ }
+
+ /**
+ * Set the time and Send out a sticky broadcast so the system can determine
+ * if the time was set by the carrier.
+ *
+ * @param time time set by network
+ */
+ private void setAndBroadcastNetworkSetTime(long time) {
+ SystemClock.setCurrentTimeMillis(time);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
intent.putExtra("time", time);
phone.getContext().sendStickyBroadcast(intent);
}
-
+
private void revertToNitz() {
if (Settings.System.getInt(phone.getContext().getContentResolver(),
Settings.System.AUTO_TIME, 0) == 0) {
@@ -1348,10 +1428,8 @@ final class ServiceStateTracker extends Handler
+ "' mSavedTime=" + mSavedTime
+ " mSavedAtTime=" + mSavedAtTime);
if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) {
- AlarmManager alarm =
- (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
- alarm.setTimeZone(mSavedTimeZone);
- SystemClock.setCurrentTimeMillis(mSavedTime
+ setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
+ setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimException.java b/telephony/java/com/android/internal/telephony/gsm/SimException.java
index 4a9d266..1c0daba 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimException.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimException.java
@@ -31,3 +31,28 @@ public class SimException extends Exception
super(s);
}
}
+
+final class SimVmFixedException extends SimException {
+ SimVmFixedException()
+ {
+
+ }
+
+ SimVmFixedException(String s)
+ {
+ super(s);
+ }
+}
+
+final class SimVmNotSupportedException extends SimException {
+ SimVmNotSupportedException()
+ {
+
+ }
+
+ SimVmNotSupportedException(String s)
+ {
+ super(s);
+ }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimUtils.java b/telephony/java/com/android/internal/telephony/gsm/SimUtils.java
index 5cd5a90..2eecdba 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimUtils.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimUtils.java
@@ -326,4 +326,151 @@ public class SimUtils
return ret;
}
+
+ /**
+ * Convert a TS 131.102 image instance of code scheme '11' into Bitmap
+ * @param data The raw data
+ * @param length The length of image body
+ * @return The bitmap
+ */
+ public static Bitmap parseToBnW(byte[] data, int length){
+ int valueIndex = 0;
+ int width = data[valueIndex++] & 0xFF;
+ int height = data[valueIndex++] & 0xFF;
+ int numOfPixels = width*height;
+
+ int[] pixels = new int[numOfPixels];
+
+ int pixelIndex = 0;
+ int bitIndex = 7;
+ byte currentByte = 0x00;
+ while (pixelIndex < numOfPixels) {
+ // reassign data and index for every byte (8 bits).
+ if (pixelIndex % 8 == 0) {
+ currentByte = data[valueIndex++];
+ bitIndex = 7;
+ }
+ pixels[pixelIndex++] = bitToRGB((currentByte >> bitIndex-- ) & 0x01);
+ };
+
+ if (pixelIndex != numOfPixels) {
+ Log.e(LOG_TAG, "parse end and size error");
+ }
+ return Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888);
+ }
+
+ private static int bitToRGB(int bit){
+ if(bit == 1){
+ return Color.WHITE;
+ } else {
+ return Color.BLACK;
+ }
+ }
+
+ /**
+ * a TS 131.102 image instance of code scheme '11' into color Bitmap
+ *
+ * @param data The raw data
+ * @param length the length of image body
+ * @param transparency with or without transparency
+ * @return The color bitmap
+ */
+ public static Bitmap parseToRGB(byte[] data, int length,
+ boolean transparency) {
+ int valueIndex = 0;
+ int width = data[valueIndex++] & 0xFF;
+ int height = data[valueIndex++] & 0xFF;
+ int bits = data[valueIndex++] & 0xFF;
+ int colorNumber = data[valueIndex++] & 0xFF;
+ int clutOffset = ((data[valueIndex++] & 0xFF) << 8)
+ | data[valueIndex++];
+ length = length - 6;
+
+ int[] colorIndexArray = getCLUT(data, clutOffset, colorNumber);
+ if (true == transparency) {
+ colorIndexArray[colorNumber - 1] = Color.TRANSPARENT;
+ }
+
+ int[] resultArray = null;
+ if (0 == (8 % bits)) {
+ resultArray = mapTo2OrderBitColor(data, valueIndex,
+ (width * height), colorIndexArray, bits);
+ } else {
+ resultArray = mapToNon2OrderBitColor(data, valueIndex,
+ (width * height), colorIndexArray, bits);
+ }
+
+ return Bitmap.createBitmap(resultArray, width, height,
+ Bitmap.Config.RGB_565);
+ }
+
+ private static int[] mapTo2OrderBitColor(byte[] data, int valueIndex,
+ int length, int[] colorArray, int bits) {
+ if (0 != (8 % bits)) {
+ Log.e(LOG_TAG, "not event number of color");
+ return mapToNon2OrderBitColor(data, valueIndex, length, colorArray,
+ bits);
+ }
+
+ int mask = 0x01;
+ switch (bits) {
+ case 1:
+ mask = 0x01;
+ break;
+ case 2:
+ mask = 0x03;
+ break;
+ case 4:
+ mask = 0x0F;
+ break;
+ case 8:
+ mask = 0xFF;
+ break;
+ }
+
+ int[] resultArray = new int[length];
+ int resultIndex = 0;
+ int run = 8 / bits;
+ while (resultIndex < length) {
+ byte tempByte = data[valueIndex++];
+ for (int runIndex = 0; runIndex < run; ++runIndex) {
+ int offset = run - runIndex - 1;
+ resultArray[resultIndex++] = colorArray[(tempByte >> (offset * bits))
+ & mask];
+ }
+ }
+ return resultArray;
+ }
+
+ private static int[] mapToNon2OrderBitColor(byte[] data, int valueIndex,
+ int length, int[] colorArray, int bits) {
+ if (0 == (8 % bits)) {
+ Log.e(LOG_TAG, "not odd number of color");
+ return mapTo2OrderBitColor(data, valueIndex, length, colorArray,
+ bits);
+ }
+
+ int[] resultArray = new int[length];
+ // TODO fix me:
+ return resultArray;
+ }
+
+ private static int[] getCLUT(byte[] rawData, int offset, int number) {
+ if (null == rawData) {
+ return null;
+ }
+
+ int[] result = new int[number];
+ int endIndex = offset + (number * 3); // 1 color use 3 bytes
+ int valueIndex = offset;
+ int colorIndex = 0;
+ int alpha = 0xff << 24;
+ do {
+ result[colorIndex++] = alpha
+ | ((rawData[valueIndex++] & 0xFF) << 16)
+ | ((rawData[valueIndex++] & 0xFF) << 8)
+ | ((rawData[valueIndex++] & 0xFF));
+ } while (valueIndex < endIndex);
+ return result;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/AppInterface.java b/telephony/java/com/android/internal/telephony/gsm/stk/AppInterface.java
index a43e32f..c002729 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/AppInterface.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/AppInterface.java
@@ -17,241 +17,74 @@
package com.android.internal.telephony.gsm.stk;
/**
- * Interface for communication from Apps to STK Service
+ * Interface for communication between STK App and STK Telephony
*
* {@hide}
*/
public interface AppInterface {
- /**
- * STK state
- */
- public enum State {
- /**
- * Idle state
- */
- IDLE,
- /**
- * Idle but main menu exists. Menu selection should be done by calling {@code
- * notifyMenuSelection()}.
- */
- MAIN_MENU,
- /**
- * Waiting for a key input. Key input should be notified by calling
- * {@code notifyInkey()}.
- */
- GET_INKEY,
- /**
- * Waiting for a user input. Text input should be notified by calling
- * {@code notifyInput()}.
- */
- GET_INPUT,
- /**
- * Waiting for a user selection. The selection should be notified by
- * calling {@code notifySelectedItem()}.
- */
- SELECT_ITEM,
- /**
- * Waiting for the user to accept or reject a call. It should be
- * notified by calling {@code acceptOrRejectCall()}.
- */
- CALL_SETUP,
- /**
- * Waiting for user to confirm Display Text message.
- * notified by calling {@code notifyDisplayTextEnded()}.
- */
- DISPLAY_TEXT,
- /**
- * Waiting for user to confirm launching the browser.
- * notified by calling {@code notifyLaunchedBrowserConfirmed()}.
- */
- LAUNCH_BROWSER,
- /**
- * Waiting for the application to play the requested tone.
- */
- PLAY_TONE
- }
-
- /**
- * Sets the {@link CommandListener CommandListener} object that is used for
- * notifying of proactive commands or events from the SIM/RIL.
- *
- * @param l CommandListener object that handles the proactive commands and
- * events from the SIM/RIL.
- */
- void setCommandListener(CommandListener l);
- /**
- * Gets the current state of STK service.
- * @return The current state.
+ /*
+ * Intent's actions which are broadcasted by the Telephony once a new STK
+ * proactive command, session end arrive.
*/
- State getState();
-
- /**
- * Gets the main menu that has been setup by the SIM.
- *
- * @return The main menu that has been setup by the SIM. It can be null.
- */
- Menu getCurrentMenu();
-
- /**
- * Notifies the SIM of the menu selection among a set of menu options
- * supplied by the SIM using SET UP MENU.
- *
- * @param menuId ID of the selected menu item. It can be between 1 and
- * 255.
- * @param helpRequired True if just help information is requested on a menu
- * item rather than menu selection. False if the menu item
- * is actually selected.
- */
- void notifyMenuSelection(int menuId, boolean helpRequired);
-
- /**
- * Notifies the SIM that a user activity has occurred. It is actually sent
- * to the SIM when it has registered to be notified of this event via SET
- * UP EVENT LIST command.
- */
- void notifyUserActivity();
-
- /**
- * Notifies the SIM that the idle screen is available. It is actually sent
- * to the SIM when it has registered to be notified of this event via SET
- * UP EVENT LIST command.
- */
- void notifyIdleScreenAvailable();
-
- /**
- * Notifies the SIM that the currently used language has changed. It is
- * actually sent to the SIM when it has registered to be notified of this
- * event via SET UP EVENT LIST command.
- *
- * @param langCode Language code of the currently selected language.
- * Language code is defined in ISO 639. This must be a
- * string of two characters.
- */
- void notifyLanguageSelection(String langCode);
-
- /**
- * Notifies the SIM that the browser is terminated. It is actually sent to
- * the SIM when it has registered to be notified of this event via SET UP
- * EVENT LIST command.
- *
- * @param isErrorTermination True if the cause is "Error Termination",
- * false if the cause is "User Termination".
- */
- void notifyBrowserTermination(boolean isErrorTermination);
-
- /**
- * Notifies the SIM about the launch browser confirmation. This method
- * should be called only after the application gets notified by {@code
- * CommandListener.onLaunchBrowser()} or inside that method.
- *
- * @param userConfirmed True if user choose to confirm browser launch,
- * False if user choose not to confirm browser launch.
- */
- void notifyLaunchBrowser(boolean userConfirmed);
-
- /**
- * Notifies the SIM that a tone had been played. This method should be called
- * only after the application gets notified by {@code
- * CommandListener.onPlayTone()} or inside that method.
- *
- */
- void notifyToneEnded();
-
- /**
- * Notifies the SIM that the user input a text. This method should be
- * called only after the application gets notified by {@code
- * CommandListener.onGetInput()} or inside that method.
- *
- * @param input The text string that the user has typed.
- * @param helpRequired True if just help information is requested on a menu
- * item rather than menu selection. False if the menu
- * item is actually selected.
- */
- void notifyInput(String input, boolean helpRequired);
-
- /**
- * Notifies the SIM that the user input a key in Yes/No scenario.
- * This method should be called only after the application gets notified by
- * {@code CommandListener.onGetInkey()} or inside that method.
- *
- * @param yesNoResponse User's choice for Yes/No scenario.
- * @param helpRequired True if just help information is requested on a menu
- * item rather than menu selection. False if the menu
- * item is actually selected.
- */
- void notifyInkey(boolean yesNoResponse, boolean helpRequired);
-
- /**
- * Notifies the SIM that the user input a key. This method should be called
- * only after the application gets notified by {@code
- * CommandListener.onGetInkey()} or inside that method.
- *
- * @param key The key that the user has typed. If the SIM required
- * @param helpRequired True if just help information is requested on a menu
- * item rather than menu selection. False if the menu
- * item is actually selected.
- */
- void notifyInkey(char key, boolean helpRequired);
-
- /**
- * Notifies the SIM that no response was received from the user.
- */
- void notifyNoResponse();
-
- /**
- * Send terminal response for backward move in the proactive SIM session
- * requested by the user
- *
- * Only available when responding following proactive commands
- * DISPLAY_TEXT(0x21),
- * GET_INKEY(0x22),
- * GET_INPUT(0x23),
- * SET_UP_MENU(0x25);
- *
- * @return true if stk can send backward move response
- */
- boolean backwardMove();
-
- /**
- * Send terminal response for proactive SIM session terminated by the user
- *
- * Only available when responding following proactive commands
- * DISPLAY_TEXT(0x21),
- * GET_INKEY(0x22),
- * GET_INPUT(0x23),
- * PLAY_TONE(0x20),
- * SET_UP_MENU(0x25);
- *
- * @return true if stk can send terminate session response
- */
- boolean terminateSession();
-
- /**
- * Notifies the SIM that the user selected an item. This method should be
- * called only after the application gets notified by {@code
- * CommandListener.onSelectItem()} or inside that method.
- *
- * @param id The menu item that the user has selected.
- * @param wantsHelp Indicates if the user requested help for the id item.
- */
- void notifySelectedItem(int id, boolean wantsHelp);
+ public static final String STK_CMD_ACTION =
+ "android.intent.action.stk.command";
+ public static final String STK_SESSION_END_ACTION =
+ "android.intent.action.stk.session_end";
- /**
- * Notifies the SIM that No response was received from the user for display
- * text message dialog.
- *
- * * @param terminationCode indication for display text termination. Uses
- * {@code ResultCode } values.
- */
- public void notifyDisplayTextEnded(ResultCode terminationCode);
+ /*
+ * Callback function from app to telephony to pass a result code and user's
+ * input back to the SIM.
+ */
+ void onCmdResponse(StkResponseMessage resMsg);
+
+ /*
+ * Enumeration for representing "Type of Command" of proactive commands.
+ * Those are the only commands which are supported by the Telephony. Any app
+ * implementation should support those.
+ */
+ public static enum CommandType {
+ DISPLAY_TEXT(0x21),
+ GET_INKEY(0x22),
+ GET_INPUT(0x23),
+ LAUNCH_BROWSER(0x15),
+ PLAY_TONE(0x20),
+ REFRESH(0x01),
+ SELECT_ITEM(0x24),
+ SEND_SS(0x11),
+ SEND_USSD(0x12),
+ SEND_SMS(0x13),
+ SEND_DTMF(0x14),
+ SET_UP_EVENT_LIST(0x05),
+ SET_UP_IDLE_MODE_TEXT(0x28),
+ SET_UP_MENU(0x25),
+ SET_UP_CALL(0x10);
+
+ private int mValue;
+
+ CommandType(int value) {
+ mValue = value;
+ }
+
+ public int value() {
+ return mValue;
+ }
- /**
- * Notifies the SIM whether the user accepted the call or not. This method
- * should be called only after the application gets notified by {@code
- * CommandListener.onCallSetup()} or inside that method.
- *
- * @param accept True if the user has accepted the call, false if not.
- */
- void acceptOrRejectCall(boolean accept);
+ /**
+ * Create a CommandType object.
+ *
+ * @param value Integer value to be converted to a CommandType object.
+ * @return CommandType object whose "Type of Command" value is {@code
+ * value}. If no CommandType object has that value, null is
+ * returned.
+ */
+ public static CommandType fromInt(int value) {
+ for (CommandType e : CommandType.values()) {
+ if (e.mValue == value) {
+ return e;
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java b/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
index f5268e5..26c2175 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
@@ -72,20 +72,7 @@ class BerTlv {
try {
/* tag */
tag = data[curIndex++] & 0xff;
- if (tag != BER_PROACTIVE_COMMAND_TAG) {
- // If the buffer doesn't contain proactive command tag, but
- // start with a command details tlv object ==> skip the length
- // parsing and look for tlv objects.
- ComprehensionTlv ctlv = ComprehensionTlv.decode(data,
- curIndex--);
- if (ctlv.getTag() == ComprehensionTlvTag.COMMAND_DETAILS.value()) {
- tag = BER_UNKNOWN_TAG;
- curIndex--;
- } else {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- } else {
-
+ if (tag == BER_PROACTIVE_COMMAND_TAG) {
/* length */
int temp = data[curIndex++] & 0xff;
if (temp < 0x80) {
@@ -101,8 +88,12 @@ class BerTlv {
throw new ResultException(
ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
+ } else {
+ if (ComprehensionTlvTag.COMMAND_DETAILS.value() == (tag & ~0x80)) {
+ tag = BER_UNKNOWN_TAG;
+ curIndex = 0;
+ }
}
-
} catch (IndexOutOfBoundsException e) {
throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
} catch (ResultException e) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandDetails.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandDetails.java
new file mode 100644
index 0000000..168361a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandDetails.java
@@ -0,0 +1,106 @@
+/*
+ * 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.gsm.stk;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+abstract class ValueObject {
+ abstract ComprehensionTlvTag getTag();
+}
+
+/**
+ * Class for Command Detailes object of proactive commands from SIM.
+ * {@hide}
+ */
+class CommandDetails extends ValueObject implements Parcelable {
+ public boolean compRequired;
+ public int commandNumber;
+ public int typeOfCommand;
+ public int commandQualifier;
+
+ public ComprehensionTlvTag getTag() {
+ return ComprehensionTlvTag.COMMAND_DETAILS;
+ }
+
+ CommandDetails() {
+ }
+
+ public boolean compareTo(CommandDetails other) {
+ return (this.compRequired == other.compRequired &&
+ this.commandNumber == other.commandNumber &&
+ this.commandQualifier == other.commandQualifier &&
+ this.typeOfCommand == other.typeOfCommand);
+ }
+
+ public CommandDetails(Parcel in) {
+ compRequired = true;
+ commandNumber = in.readInt();
+ typeOfCommand = in.readInt();
+ commandQualifier = in.readInt();
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(commandNumber);
+ dest.writeInt(typeOfCommand);
+ dest.writeInt(commandQualifier);
+ }
+
+ public static final Parcelable.Creator<CommandDetails> CREATOR =
+ new Parcelable.Creator<CommandDetails>() {
+ public CommandDetails createFromParcel(Parcel in) {
+ return new CommandDetails(in);
+ }
+
+ public CommandDetails[] newArray(int size) {
+ return new CommandDetails[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+}
+
+class DeviceIdentities extends ValueObject {
+ public int sourceId;
+ public int destinationId;
+
+ ComprehensionTlvTag getTag() {
+ return ComprehensionTlvTag.DEVICE_IDENTITIES;
+ }
+}
+
+// Container class to hold icon identifier value.
+class IconId extends ValueObject {
+ int recordNumber;
+ boolean selfExplanatory;
+
+ ComprehensionTlvTag getTag() {
+ return ComprehensionTlvTag.ICON_ID;
+ }
+}
+
+// Container class to hold item icon identifier list value.
+class ItemsIconId extends ValueObject {
+ int [] recordNumbers;
+ boolean selfExplanatory;
+
+ ComprehensionTlvTag getTag() {
+ return ComprehensionTlvTag.ITEM_ICON_ID_LIST;
+ }
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandListener.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandListener.java
deleted file mode 100644
index 5c9a3e9..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandListener.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.gsm.stk;
-
-import android.graphics.Bitmap;
-
-import java.util.BitSet;
-import java.util.List;
-
-
-/**
- * Interface for command notification from STK Service to Apps
- *
- * {@hide}
- */
-public interface CommandListener {
-
- /**
- * Call back function to be called when the session with the SIM ends.
- * Application must go back to the main SIM Toolkit application screen when
- * this is called.
- */
- void onSessionEnd();
-
- /**
- * Call back function to be called when the SIM wants a call to be set up.
- * Application must call {@code AppInterface.acceptOrRejectCall()} after
- * this method returns or inside this method.
- *
- * @param confirmMsg User confirmation phase message.
- * @param textAttrs List of text attributes to be applied. Can be null.
- * @param callMsg Call set up phase message.
- */
- void onCallSetup(String confirmMsg, List<TextAttribute> textAttrs,
- String callMsg);
-
- /**
- * Call back function to be called for handling DISPLAY_TEXT proactive
- * commands.
- * @param text A text to be displayed
- * @param textAttrs List of text attributes to be applied. Can be null.
- * @param isHighPriority High priority
- * @param userClear Wait for user to clear message if true, clear
- * message after a delay if false.
- */
- void onDisplayText(String text, List<TextAttribute> textAttrs,
- boolean isHighPriority, boolean userClear, boolean responseNeeded,
- Bitmap icon);
-
- /**
- * Call back function to be called for handling SET_UP_MENU proactive
- * commands. The menu can be retrieved by calling {@code
- * AppInterface.getMainMenu}.
- *
- * @param menu application main menu.
- */
- void onSetUpMenu(Menu menu);
-
- /**
- * Call back function to be called for handling GET_INKEY proactive
- * commands.
- * Application must call {@code AppInterface.notifyInkey()} after this
- * method returns or inside this method.
- *
- * @param text A text to be used as a prompt.
- * @param textAttrs List of text attributes to be applied. Can be null.
- * @param yesNo "Yes/No" response is requested if true. When this is
- * true, {@code digitOnly} and {@code ucs2} are ignored.
- * @param digitOnly Digits (0 to 9, *, # and +) only if true. Alphabet set
- * if false.
- * @param ucs2 UCS2 alphabet if true, SMS default alphabet if false.
- * @param immediateResponse An immediate digit response (0 to 9, * and #)
- * is required if true. User response shall be displayed
- * and the terminal may allow alteration and/or
- * confirmation if false.
- * @param helpAvailable Help information available.
- */
- void onGetInkey(String text, List<TextAttribute> textAttrs, boolean yesNo, boolean digitOnly,
- boolean ucs2, boolean immediateResponse, boolean helpAvailable);
- /**
- * Call back function to be called for handling GET_INPUT proactive
- * commands. Application must call {@code AppInterface.notifyInput()} after
- * this method returns or inside this method.
- *
- * @param text A text to be used as a prompt
- * @param defaultText A text to be used as a default input
- * @param minLen Mininum length of response (0 indicates there is no mininum
- * length requirement).
- * @param maxLen Maximum length of response (between 0 and 0xfe).
- * @param noMaxLimit If true, there is no limit in maximum length of
- * response.
- * @param textAttrs List of text attributes to be applied. Can be null.
- * @param digitOnly Digits (0 to 9, *, # and +) only if true. Alphabet set
- * if false.
- * @param ucs2 UCS2 alphabet if true, SMS default alphabet if false.
- * @param echo Terminal may echo user input on the display if true. User
- * input shall not be revealed in any way if false.
- * @param helpAvailable Help information available.
- */
- void onGetInput(String text, String defaultText, int minLen, int maxLen,
- boolean noMaxLimit, List<TextAttribute> textAttrs,
- boolean digitOnly, boolean ucs2, boolean echo, boolean helpAvailable);
-
- /**
- * Call back function to be called for handling SELECT_ITEM proactive
- * commands.
- * Application must call {@code AppInterface.notifySelectedItem()} after
- * this method returns or inside this method.
- *
- * @param menu Items menu.
- * @param presentationType Presentation type of the choices.
- */
- void onSelectItem(Menu menu, PresentationType presentationType);
-
- /**
- * Call back function to be called for handling SET_UP_EVENT_LIST proactive
- * commands.
- * @param events BitSet object each bit of which represents an event
- * that UICC wants the terminal to monitor.
- * <ul>
- * <li>0x00: MT call
- * <li>0x01: Call connected
- * <li>0x02: Call disconnected
- * <li>0x03: Location status
- * <li>0x04: User activity
- * <li>0x05: Idle screen available
- * <li>0x06: Card reader status
- * <li>0x07: Language selection
- * <li>0x08: Browser termination
- * <li>0x09: Data available
- * <li>0x0A: Channel status
- * <li>0x0B: Access Technology Change
- * <li>0x0C: Display parameters changed
- * <li>0x0D: Local connection
- * <li>0x0E: Network Search Mode Change
- * <li>0x0F: Browsing status
- * <li>0x10: Frames Information Change
- * <li>0x11: reserved for 3GPP (I-WLAN Access Status)
- * </ul>
- * These values are defined in Service as UICC_EVENT_*.
- * @throws ResultException must be BEYOND_TERMINAL_CAPABILITY
- * if the ME is not able to successfully accept all events
- */
- void onSetUpEventList(BitSet events) throws ResultException;
-
- /**
- * Call back function to be called for handling LAUNCH_BROWSER proactive
- * commands.
- *
- * @param useDefaultUrl If true, use the system default URL, otherwise use
- * {@code url} as the URL.
- * @param confirmMsg A text to be used as the user confirmation message. Can
- * be null.
- * @param confirmMsgAttrs List of text attributes to be applied to {code
- * confirmMsgAttrs}. Can be null.
- * @param mode Launch mode.
- */
- void onLaunchBrowser(String url, String confirmMsg,
- List<TextAttribute> confirmMsgAttrs, LaunchBrowserMode mode);
-
- /**
- * Call back function to be called for handling PLAY_TONE proactive
- * commands.
- *
- * @param tone Tone to be played
- * @param text A text to be displayed. Can be null.
- * @param textAttrs List of text attributes to be applied. Can be null.
- * @param duration Time duration to play the tone.
- * @throws ResultException
- */
- void onPlayTone(Tone tone, String text, List<TextAttribute> textAttrs,
- Duration duration) throws ResultException;
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
index d39ad7b..60e8148 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -18,102 +18,152 @@ package com.android.internal.telephony.gsm.stk;
import android.graphics.Bitmap;
-import java.util.List;
-
/**
* Container class for proactive command parameters.
*
*/
class CommandParams {
- public CtlvCommandDetails cmdDet;
+ CommandDetails cmdDet;
- CommandParams(CtlvCommandDetails cmdDet) {
+ CommandParams(CommandDetails cmdDet) {
this.cmdDet = cmdDet;
}
+
+ AppInterface.CommandType getCommandType() {
+ return AppInterface.CommandType.fromInt(cmdDet.typeOfCommand);
+ }
+
+ boolean setIcon(Bitmap icon) { return true; }
}
-class CommonUIParams extends CommandParams {
- String mText;
- Bitmap mIcon;
- boolean mIconSelfExplanatory;
- TextAttribute mTextAttrs;
+class DisplayTextParams extends CommandParams {
+ TextMessage textMsg;
- CommonUIParams(CtlvCommandDetails cmdDet, String text,
- TextAttribute textAttrs) {
+ DisplayTextParams(CommandDetails cmdDet, TextMessage textMsg) {
super(cmdDet);
+ this.textMsg = textMsg;
+ }
- mText = text;
- mTextAttrs = textAttrs;
- mIconSelfExplanatory = false;
- mIcon = null;
+ boolean setIcon(Bitmap icon) {
+ if (icon != null && textMsg != null) {
+ textMsg.icon = icon;
+ return true;
+ }
+ return false;
}
+}
+
+class LaunchBrowserParams extends CommandParams {
+ TextMessage confirmMsg;
+ LaunchBrowserMode mode;
+ String url;
- void setIcon(Bitmap icon) {
- mIcon = icon;
+ LaunchBrowserParams(CommandDetails cmdDet, TextMessage confirmMsg,
+ String url, LaunchBrowserMode mode) {
+ super(cmdDet);
+ this.confirmMsg = confirmMsg;
+ this.mode = mode;
+ this.url = url;
}
- void setIconSelfExplanatory(boolean iconSelfExplanatory) {
- mIconSelfExplanatory = iconSelfExplanatory;
+ boolean setIcon(Bitmap icon) {
+ if (icon != null && confirmMsg != null) {
+ confirmMsg.icon = icon;
+ return true;
+ }
+ return false;
}
}
-class DisplayTextParams extends CommandParams {
- String text = null;
- Bitmap icon = null;
- List<TextAttribute> textAttrs = null;
- boolean immediateResponse = false;
- boolean userClear = false;
- boolean isHighPriority = false;
-
- DisplayTextParams(CtlvCommandDetails cmdDet) {
+class PlayToneParams extends CommandParams {
+ TextMessage textMsg;
+ ToneSettings settings;
+
+ PlayToneParams(CommandDetails cmdDet, TextMessage textMsg,
+ Tone tone, Duration duration, boolean vibrate) {
super(cmdDet);
+ this.textMsg = textMsg;
+ this.settings = new ToneSettings(duration, tone, vibrate);
+ }
+
+ boolean setIcon(Bitmap icon) {
+ if (icon != null && textMsg != null) {
+ textMsg.icon = icon;
+ return true;
+ }
+ return false;
}
}
-class GetInkeyParams extends CommandParams {
- boolean isYesNo;
- boolean isUcs2;
+class CallSetupParams extends CommandParams {
+ TextMessage confirmMsg;
+ TextMessage callMsg;
- GetInkeyParams(CtlvCommandDetails cmdDet, boolean isYesNo,
- boolean isUcs2) {
+ CallSetupParams(CommandDetails cmdDet, TextMessage confirmMsg,
+ TextMessage callMsg) {
super(cmdDet);
+ this.confirmMsg = confirmMsg;
+ this.callMsg = callMsg;
+ }
- this.isYesNo = isYesNo;
- this.isUcs2 = isUcs2;
+ boolean setIcon(Bitmap icon) {
+ if (icon == null) {
+ return false;
+ }
+ if (confirmMsg != null && confirmMsg.icon == null) {
+ confirmMsg.icon = icon;
+ return true;
+ } else if (callMsg != null && callMsg.icon == null) {
+ callMsg.icon = icon;
+ return true;
+ }
+ return false;
}
}
-class GetInputParams extends CommandParams {
- boolean isUcs2;
- boolean isPacked;
+class SelectItemParams extends CommandParams {
+ Menu menu = null;
+ boolean loadTitleIcon = false;
- GetInputParams(CtlvCommandDetails cmdDet, boolean isUcs2,
- boolean isPacked) {
+ SelectItemParams(CommandDetails cmdDet, Menu menu, boolean loadTitleIcon) {
super(cmdDet);
+ this.menu = menu;
+ this.loadTitleIcon = loadTitleIcon;
+ }
- this.isUcs2 = isUcs2;
- this.isPacked = isPacked;
+ boolean setIcon(Bitmap icon) {
+ if (icon != null && menu != null) {
+ if (loadTitleIcon && menu.titleIcon == null) {
+ menu.titleIcon = icon;
+ } else {
+ for (Item item : menu.items) {
+ if (item.icon != null) {
+ continue;
+ }
+ item.icon = icon;
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
}
}
-class SelectItemParams extends CommandParams {
- Menu mMenu = null;
- PresentationType mPresentationType;
- int mIconLoadState = LOAD_NO_ICON;
-
- // loading icons state parameters.
- static final int LOAD_NO_ICON = 0;
- static final int LOAD_TITLE_ICON = 1;
- static final int LOAD_ITEMS_ICONS = 2;
- static final int LOAD_TITLE_ITEMS_ICONS = 3;
-
- SelectItemParams(CtlvCommandDetails cmdDet, Menu menu,
- PresentationType presentationType, int iconLoadState) {
+class GetInputParams extends CommandParams {
+ Input input = null;
+
+ GetInputParams(CommandDetails cmdDet, Input input) {
super(cmdDet);
+ this.input = input;
+ }
- mMenu = menu;
- mPresentationType = presentationType;
- mIconLoadState = iconLoadState;
+ boolean setIcon(Bitmap icon) {
+ if (icon != null && input != null) {
+ input.icon = icon;
+ }
+ return true;
}
}
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
new file mode 100644
index 0000000..2d2f9ae
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
@@ -0,0 +1,870 @@
+/*
+ * 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.gsm.stk;
+
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Message;
+
+import com.android.internal.telephony.gsm.GsmAlphabet;
+import com.android.internal.telephony.gsm.SIMFileHandler;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Factory class, used for decoding raw byte arrays, received from baseband,
+ * into a CommandParams object.
+ *
+ */
+class CommandParamsFactory extends Handler {
+ private static CommandParamsFactory sInstance = null;
+ private IconLoader mIconLoader;
+ private CommandParams mCmdParams = null;
+ private int mIconLoadState = LOAD_NO_ICON;
+ private Handler mCaller = null;
+
+ // constants
+ static final int MSG_ID_LOAD_ICON_DONE = 1;
+
+ // loading icons state parameters.
+ static final int LOAD_NO_ICON = 0;
+ static final int LOAD_SINGLE_ICON = 1;
+ static final int LOAD_MULTI_ICONS = 2;
+
+ // Command Qualifier values for refresh command
+ static final int REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE = 0x00;
+ static final int REFRESH_NAA_INIT_AND_FILE_CHANGE = 0x02;
+ static final int REFRESH_NAA_INIT = 0x03;
+ static final int REFRESH_UICC_RESET = 0x04;
+
+ private static final String TAG = "CmdParamsFactory";
+
+ static synchronized CommandParamsFactory getInstance(Handler caller,
+ SIMFileHandler fh) {
+ if (sInstance != null) {
+ return sInstance;
+ }
+ if (fh != null) {
+ return new CommandParamsFactory(caller, fh);
+ }
+ return null;
+ }
+
+ private CommandParamsFactory(Handler caller, SIMFileHandler fh) {
+ mCaller = caller;
+ mIconLoader = IconLoader.getInstance(this, fh);
+ }
+
+ private CommandDetails processCommandDetails(List<ComprehensionTlv> ctlvs) {
+ CommandDetails cmdDet = null;
+
+ if (ctlvs != null) {
+ // Search for the Command Details object.
+ ComprehensionTlv ctlvCmdDet = searchForTag(
+ ComprehensionTlvTag.COMMAND_DETAILS, ctlvs);
+ if (ctlvCmdDet != null) {
+ try {
+ cmdDet = ValueParser.retrieveCommandDetails(ctlvCmdDet);
+ } catch (ResultException e) {
+ StkLog.d(this, "Failed to procees command details");
+ }
+ }
+ }
+ return cmdDet;
+ }
+
+ void make(BerTlv berTlv) {
+ if (berTlv == null) {
+ return;
+ }
+ // reset global state parameters.
+ mCmdParams = null;
+ mIconLoadState = LOAD_NO_ICON;
+ // only proactive command messages are processed.
+ if (berTlv.getTag() != BerTlv.BER_PROACTIVE_COMMAND_TAG) {
+ sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
+ return;
+ }
+ boolean cmdPending = false;
+ List<ComprehensionTlv> ctlvs = berTlv.getComprehensionTlvs();
+ // process command dtails from the tlv list.
+ CommandDetails cmdDet = processCommandDetails(ctlvs);
+ if (cmdDet == null) {
+ sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
+ return;
+ }
+
+ // extract command type enumeration from the raw value stored inside
+ // the Command Details object.
+ AppInterface.CommandType cmdType = AppInterface.CommandType
+ .fromInt(cmdDet.typeOfCommand);
+ if (cmdType == null) {
+ sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
+ return;
+ }
+
+ try {
+ switch (cmdType) {
+ case SET_UP_MENU:
+ cmdPending = processSelectItem(cmdDet, ctlvs);
+ break;
+ case SELECT_ITEM:
+ cmdPending = processSelectItem(cmdDet, ctlvs);
+ break;
+ case DISPLAY_TEXT:
+ cmdPending = processDisplayText(cmdDet, ctlvs);
+ break;
+ case SET_UP_IDLE_MODE_TEXT:
+ cmdPending = processSetUpIdleModeText(cmdDet, ctlvs);
+ break;
+ case GET_INKEY:
+ cmdPending = processGetInkey(cmdDet, ctlvs);
+ break;
+ case GET_INPUT:
+ cmdPending = processGetInput(cmdDet, ctlvs);
+ break;
+ case SEND_DTMF:
+ case SEND_SMS:
+ case SEND_SS:
+ case SEND_USSD:
+ cmdPending = processEventNotify(cmdDet, ctlvs);
+ break;
+ case SET_UP_CALL:
+ cmdPending = processSetupCall(cmdDet, ctlvs);
+ break;
+ case REFRESH:
+ processRefresh(cmdDet, ctlvs);
+ cmdPending = false;
+ break;
+ case LAUNCH_BROWSER:
+ cmdPending = processLaunchBrowser(cmdDet, ctlvs);
+ break;
+ case PLAY_TONE:
+ cmdPending = processPlayTone(cmdDet, ctlvs);
+ break;
+ default:
+ // unsupported proactive commands
+ mCmdParams = new CommandParams(cmdDet);
+ sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
+ return;
+ }
+ } catch (ResultException e) {
+ mCmdParams = new CommandParams(cmdDet);
+ sendCmdParams(e.result());
+ return;
+ }
+ if (!cmdPending) {
+ sendCmdParams(ResultCode.OK);
+ }
+ }
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ID_LOAD_ICON_DONE:
+ sendCmdParams(setIcons(msg.obj));
+ break;
+ }
+ }
+
+ private ResultCode setIcons(Object data) {
+ Bitmap[] icons = null;
+ int iconIndex = 0;
+
+ if (data == null) {
+ return ResultCode.PRFRMD_ICON_NOT_DISPLAYED;
+ }
+ switch(mIconLoadState) {
+ case LOAD_SINGLE_ICON:
+ mCmdParams.setIcon((Bitmap) data);
+ break;
+ case LOAD_MULTI_ICONS:
+ icons = (Bitmap[]) data;
+ // set each item icon.
+ for (Bitmap icon : icons) {
+ mCmdParams.setIcon(icon);
+ }
+ break;
+ }
+ return ResultCode.OK;
+ }
+
+ private void sendCmdParams(ResultCode resCode) {
+ Message msg = mCaller.obtainMessage(RilMessageDecoder.CMD_PARAMS_READY);
+ msg.arg1 = resCode.value();
+ msg.obj = mCmdParams;
+ msg.sendToTarget();
+ }
+
+ /**
+ * Search for a COMPREHENSION-TLV object with the given tag from a list
+ *
+ * @param tag A tag to search for
+ * @param ctlvs List of ComprehensionTlv objects used to search in
+ *
+ * @return A ComprehensionTlv object that has the tag value of {@code tag}.
+ * If no object is found with the tag, null is returned.
+ */
+ private ComprehensionTlv searchForTag(ComprehensionTlvTag tag,
+ List<ComprehensionTlv> ctlvs) {
+ Iterator<ComprehensionTlv> iter = ctlvs.iterator();
+ return searchForNextTag(tag, iter);
+ }
+
+ /**
+ * Search for the next COMPREHENSION-TLV object with the given tag from a
+ * list iterated by {@code iter}. {@code iter} points to the object next to
+ * the found object when this method returns. Used for searching the same
+ * list for similar tags, usually item id.
+ *
+ * @param tag A tag to search for
+ * @param iter Iterator for ComprehensionTlv objects used for search
+ *
+ * @return A ComprehensionTlv object that has the tag value of {@code tag}.
+ * If no object is found with the tag, null is returned.
+ */
+ private ComprehensionTlv searchForNextTag(ComprehensionTlvTag tag,
+ Iterator<ComprehensionTlv> iter) {
+ int tagValue = tag.value();
+ while (iter.hasNext()) {
+ ComprehensionTlv ctlv = iter.next();
+ if (ctlv.getTag() == tagValue) {
+ return ctlv;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Processes DISPLAY_TEXT proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ * @throws ResultException
+ */
+ private boolean processDisplayText(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs)
+ throws ResultException {
+
+ StkLog.d(this, "process DisplayText");
+
+ TextMessage textMsg = new TextMessage();
+ IconId iconId = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
+ ctlvs);
+ if (ctlv != null) {
+ textMsg.text = ValueParser.retrieveTextString(ctlv);
+ }
+ // If the tlv object doesn't exist or the it is a null object reply
+ // with command not understood.
+ if (textMsg.text == null) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.IMMEDIATE_RESPONSE, ctlvs);
+ if (ctlv != null) {
+ textMsg.responseNeeded = false;
+ }
+ // parse icon identifier
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ textMsg.iconSelfExplanatory = iconId.selfExplanatory;
+ }
+ // parse tone duration
+ ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs);
+ if (ctlv != null) {
+ textMsg.duration = ValueParser.retrieveDuration(ctlv);
+ }
+
+ // Parse command qualifier parameters.
+ textMsg.isHighPriority = (cmdDet.commandQualifier & 0x01) != 0;
+ textMsg.userClear = (cmdDet.commandQualifier & 0x80) != 0;
+
+ mCmdParams = new DisplayTextParams(cmdDet, textMsg);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes SET_UP_IDLE_MODE_TEXT proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ * @throws ResultException
+ */
+ private boolean processSetUpIdleModeText(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(this, "process SetUpIdleModeText");
+
+ TextMessage textMsg = new TextMessage();
+ IconId iconId = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
+ ctlvs);
+ if (ctlv != null) {
+ textMsg.text = ValueParser.retrieveTextString(ctlv);
+ }
+ // load icons only when text exist.
+ if (textMsg.text != null) {
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ textMsg.iconSelfExplanatory = iconId.selfExplanatory;
+ }
+ }
+
+ mCmdParams = new DisplayTextParams(cmdDet, textMsg);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes GET_INKEY proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ * @throws ResultException
+ */
+ private boolean processGetInkey(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(this, "process GetInkey");
+
+ Input input = new Input();
+ IconId iconId = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
+ ctlvs);
+ if (ctlv != null) {
+ input.text = ValueParser.retrieveTextString(ctlv);
+ } else {
+ throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
+ }
+ // parse icon identifier
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ }
+
+ input.minLen = 1;
+ input.maxLen = 1;
+
+ input.digitOnly = (cmdDet.commandQualifier & 0x01) == 0;
+ input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
+ input.yesNo = (cmdDet.commandQualifier & 0x04) != 0;
+ input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
+
+ mCmdParams = new GetInputParams(cmdDet, input);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes GET_INPUT proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ * @throws ResultException
+ */
+ private boolean processGetInput(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(this, "process GetInput");
+
+ Input input = new Input();
+ IconId iconId = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
+ ctlvs);
+ if (ctlv != null) {
+ input.text = ValueParser.retrieveTextString(ctlv);
+ } else {
+ throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.RESPONSE_LENGTH, ctlvs);
+ if (ctlv != null) {
+ try {
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ input.minLen = rawValue[valueIndex] & 0xff;
+ input.maxLen = rawValue[valueIndex + 1] & 0xff;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ } else {
+ throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.DEFAULT_TEXT, ctlvs);
+ if (ctlv != null) {
+ input.defaultText = ValueParser.retrieveTextString(ctlv);
+ }
+ // parse icon identifier
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ }
+
+ input.digitOnly = (cmdDet.commandQualifier & 0x01) == 0;
+ input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
+ input.echo = (cmdDet.commandQualifier & 0x04) == 0;
+ input.packed = (cmdDet.commandQualifier & 0x08) != 0;
+ input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
+
+ mCmdParams = new GetInputParams(cmdDet, input);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes REFRESH proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ */
+ private boolean processRefresh(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) {
+
+ StkLog.d(this, "process Refresh");
+
+ // REFRESH proactive command is rerouted by the baseband and handled by
+ // the telephony layer. IDLE TEXT should be removed for a REFRESH command
+ // with "initialization" or "reset"
+ switch (cmdDet.commandQualifier) {
+ case REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE:
+ case REFRESH_NAA_INIT_AND_FILE_CHANGE:
+ case REFRESH_NAA_INIT:
+ case REFRESH_UICC_RESET:
+ mCmdParams = new DisplayTextParams(cmdDet, null);
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * Processes SELECT_ITEM proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ * @throws ResultException
+ */
+ private boolean processSelectItem(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(this, "process SelectItem");
+
+ Menu menu = new Menu();
+ IconId titleIconId = null;
+ ItemsIconId itemsIconId = null;
+ Iterator<ComprehensionTlv> iter = ctlvs.iterator();
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
+ ctlvs);
+ if (ctlv != null) {
+ menu.title = ValueParser.retrieveAlphaId(ctlv);
+ }
+
+ while (true) {
+ ctlv = searchForNextTag(ComprehensionTlvTag.ITEM, iter);
+ if (ctlv != null) {
+ menu.items.add(ValueParser.retrieveItem(ctlv));
+ } else {
+ break;
+ }
+ }
+
+ // We must have at least one menu item.
+ if (menu.items.size() == 0) {
+ throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.ITEM_ID, ctlvs);
+ if (ctlv != null) {
+ // STK items are listed 1...n while list start at 0, need to
+ // subtract one.
+ menu.defaultItem = ValueParser.retrieveItemId(ctlv) - 1;
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ titleIconId = ValueParser.retrieveIconId(ctlv);
+ menu.titleIconSelfExplanatory = titleIconId.selfExplanatory;
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.ITEM_ICON_ID_LIST, ctlvs);
+ if (ctlv != null) {
+ mIconLoadState = LOAD_MULTI_ICONS;
+ itemsIconId = ValueParser.retrieveItemsIconId(ctlv);
+ menu.itemsIconSelfExplanatory = itemsIconId.selfExplanatory;
+ }
+
+ boolean presentTypeSpecified = (cmdDet.commandQualifier & 0x01) != 0;
+ if (presentTypeSpecified) {
+ if ((cmdDet.commandQualifier & 0x02) == 0) {
+ menu.presentationType = PresentationType.DATA_VALUES;
+ } else {
+ menu.presentationType = PresentationType.NAVIGATION_OPTIONS;
+ }
+ }
+ menu.softKeyPreferred = (cmdDet.commandQualifier & 0x04) != 0;
+ menu.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
+
+ mCmdParams = new SelectItemParams(cmdDet, menu, titleIconId != null);
+
+ // Load icons data if needed.
+ switch(mIconLoadState) {
+ case LOAD_NO_ICON:
+ return false;
+ case LOAD_SINGLE_ICON:
+ mIconLoader.loadIcon(titleIconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ break;
+ case LOAD_MULTI_ICONS:
+ int[] recordNumbers = itemsIconId.recordNumbers;
+ if (titleIconId != null) {
+ // Create a new array for all the icons (title and items).
+ recordNumbers = new int[itemsIconId.recordNumbers.length + 1];
+ recordNumbers[0] = titleIconId.recordNumber;
+ System.arraycopy(itemsIconId.recordNumbers, 0, recordNumbers,
+ 1, itemsIconId.recordNumbers.length);
+ }
+ mIconLoader.loadIcons(recordNumbers, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * Processes EVENT_NOTIFY message from baseband.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ */
+ private boolean processEventNotify(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(this, "process EventNotify");
+
+ TextMessage textMsg = new TextMessage();
+ IconId iconId = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
+ ctlvs);
+ if (ctlv != null) {
+ textMsg.text = ValueParser.retrieveAlphaId(ctlv);
+ } else {
+ throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ textMsg.iconSelfExplanatory = iconId.selfExplanatory;
+ }
+
+ textMsg.responseNeeded = false;
+ mCmdParams = new DisplayTextParams(cmdDet, textMsg);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes SET_UP_EVENT_LIST proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details object retrieved.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ */
+ private boolean processSetUpEventList(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) {
+
+ StkLog.d(this, "process SetUpEventList");
+ //
+ // ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.EVENT_LIST,
+ // ctlvs);
+ // if (ctlv != null) {
+ // try {
+ // byte[] rawValue = ctlv.getRawValue();
+ // int valueIndex = ctlv.getValueIndex();
+ // int valueLen = ctlv.getLength();
+ //
+ // } catch (IndexOutOfBoundsException e) {}
+ // }
+ return true;
+ }
+
+ /**
+ * Processes LAUNCH_BROWSER proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ * @throws ResultException
+ */
+ private boolean processLaunchBrowser(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(this, "process LaunchBrowser");
+
+ TextMessage confirmMsg = new TextMessage();
+ IconId iconId = null;
+ String url = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.URL, ctlvs);
+ if (ctlv != null) {
+ try {
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ int valueLen = ctlv.getLength();
+ if (valueLen > 0) {
+ url = GsmAlphabet.gsm8BitUnpackedToString(rawValue,
+ valueIndex, valueLen);
+ } else {
+ url = null;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+
+ // parse alpha identifier.
+ ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
+ if (ctlv != null) {
+ confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
+ }
+ // parse icon identifier
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ confirmMsg.iconSelfExplanatory = iconId.selfExplanatory;
+ }
+
+ // parse command qualifier value.
+ LaunchBrowserMode mode;
+ switch (cmdDet.commandQualifier) {
+ case 0x00:
+ default:
+ mode = LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED;
+ break;
+ case 0x02:
+ mode = LaunchBrowserMode.USE_EXISTING_BROWSER;
+ break;
+ case 0x03:
+ mode = LaunchBrowserMode.LAUNCH_NEW_BROWSER;
+ break;
+ }
+
+ mCmdParams = new LaunchBrowserParams(cmdDet, confirmMsg, url, mode);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes PLAY_TONE proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details container object.
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.t
+ * @throws ResultException
+ */
+ private boolean processPlayTone(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+
+ StkLog.d(TAG, "process PlayTone");
+
+ Tone tone = null;
+ TextMessage textMsg = new TextMessage();
+ Duration duration = null;
+ IconId iconId = null;
+
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TONE, ctlvs);
+ if (ctlv != null) {
+ // Nothing to do for null objects.
+ if (ctlv.getLength() > 0) {
+ try {
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ int toneVal = rawValue[valueIndex];
+ tone = Tone.fromInt(toneVal);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(
+ ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+ }
+ // parse alpha identifier
+ ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
+ if (ctlv != null) {
+ textMsg.text = ValueParser.retrieveAlphaId(ctlv);
+ }
+ // parse tone duration
+ ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs);
+ if (ctlv != null) {
+ duration = ValueParser.retrieveDuration(ctlv);
+ }
+ // parse icon identifier
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ iconId = ValueParser.retrieveIconId(ctlv);
+ textMsg.iconSelfExplanatory = iconId.selfExplanatory;
+ }
+
+ boolean vibrate = (cmdDet.commandQualifier & 0x01) != 0x00;
+
+ textMsg.responseNeeded = false;
+ mCmdParams = new PlayToneParams(cmdDet, textMsg, tone, duration, vibrate);
+
+ if (iconId != null) {
+ mIconLoadState = LOAD_SINGLE_ICON;
+ mIconLoader.loadIcon(iconId.recordNumber, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Processes SETUP_CALL proactive command from the SIM card.
+ *
+ * @param cmdDet Command Details object retrieved from the proactive command
+ * object
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return true if the command is processing is pending and additional
+ * asynchronous processing is required.
+ */
+ private boolean processSetupCall(CommandDetails cmdDet,
+ List<ComprehensionTlv> ctlvs) throws ResultException {
+ StkLog.d(TAG, "process SetupCall");
+
+ Iterator<ComprehensionTlv> iter = ctlvs.iterator();
+ ComprehensionTlv ctlv = null;
+ // User confirmation phase message.
+ TextMessage confirmMsg = new TextMessage();
+ // Call set up phase message.
+ TextMessage callMsg = new TextMessage();
+ IconId confirmIconId = null;
+ IconId callIconId = null;
+
+ // get confirmation message string.
+ ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
+ if (ctlv != null) {
+ confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ confirmIconId = ValueParser.retrieveIconId(ctlv);
+ confirmMsg.iconSelfExplanatory = confirmIconId.selfExplanatory;
+ }
+
+ // get call set up message string.
+ ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
+ if (ctlv != null) {
+ callMsg.text = ValueParser.retrieveAlphaId(ctlv);
+ }
+
+ ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+ if (ctlv != null) {
+ callIconId = ValueParser.retrieveIconId(ctlv);
+ callMsg.iconSelfExplanatory = callIconId.selfExplanatory;
+ }
+
+ mCmdParams = new CallSetupParams(cmdDet, confirmMsg, callMsg);
+
+ if (confirmIconId != null || callIconId != null) {
+ mIconLoadState = LOAD_MULTI_ICONS;
+ int[] recordNumbers = new int[2];
+ recordNumbers[0] = confirmIconId != null
+ ? confirmIconId.recordNumber : -1;
+ recordNumbers[1] = callIconId != null ? callIconId.recordNumber
+ : -1;
+
+ mIconLoader.loadIcons(recordNumbers, this
+ .obtainMessage(MSG_ID_LOAD_ICON_DONE));
+ return true;
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java b/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
index 3cf8ca6..833ff3c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
@@ -33,7 +33,7 @@ class ComprehensionTlv {
private int mLength;
private int mValueIndex;
private byte[] mRawValue;
-
+
/**
* Constructor. Private on purpose. Use
* {@link #decodeMany(byte[], int) decodeMany} or
@@ -45,7 +45,7 @@ class ComprehensionTlv {
* @param data Byte array containing the value
* @param valueIndex Index in data at which the value starts
*/
- private ComprehensionTlv(int tag, boolean cr, int length, byte[] data,
+ protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data,
int valueIndex) {
mTag = tag;
mCr = cr;
@@ -165,9 +165,9 @@ class ComprehensionTlv {
} else {
throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
-
+
return new ComprehensionTlv(tag, cr, length, data, curIndex);
-
+
} catch (IndexOutOfBoundsException e) {
throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/Duration.java b/telephony/java/com/android/internal/telephony/gsm/stk/Duration.java
index 9ca8fb5..9d8cc97 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/Duration.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/Duration.java
@@ -16,13 +16,16 @@
package com.android.internal.telephony.gsm.stk;
+import android.os.Parcel;
+import android.os.Parcelable;
+
/**
* Class for representing "Duration" object for STK.
*
* {@hide}
*/
-public class Duration {
+public class Duration implements Parcelable {
public int timeInterval;
public TimeUnit timeUnit;
@@ -49,4 +52,28 @@ public class Duration {
this.timeInterval = timeInterval;
this.timeUnit = timeUnit;
}
+
+ private Duration(Parcel in) {
+ timeInterval = in.readInt();
+ timeUnit = TimeUnit.values()[in.readInt()];
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(timeInterval);
+ dest.writeInt(timeUnit.ordinal());
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<Duration> CREATOR = new Parcelable.Creator<Duration>() {
+ public Duration createFromParcel(Parcel in) {
+ return new Duration(in);
+ }
+
+ public Duration[] newArray(int size) {
+ return new Duration[size];
+ }
+ };
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java b/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
index ee91541..2219f58 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
@@ -27,6 +27,8 @@ import android.os.Looper;
import android.os.Message;
import android.util.Log;
+import java.util.HashMap;
+
/**
* Class for loading icons from the SIM card. Has two states: single, for loading
* one icon. Multi, for loading icons list.
@@ -34,17 +36,18 @@ import android.util.Log;
*/
class IconLoader extends Handler {
// members
- int mState = STATE_SINGLE_ICON;
- ImageDescriptor mId = null;
- Bitmap mCurrentIcon = null;
- int mRecordNumber;
- SIMFileHandler mSimFH = null;
- Message mEndMsg = null;
- byte[] mIconData = null;
+ private int mState = STATE_SINGLE_ICON;
+ private ImageDescriptor mId = null;
+ private Bitmap mCurrentIcon = null;
+ private int mRecordNumber;
+ private SIMFileHandler mSimFH = null;
+ private Message mEndMsg = null;
+ private byte[] mIconData = null;
// multi icons state members
- int[] mRecordNumbers = null;
- int mCurrentRecordIndex = 0;
- Bitmap[] mIcons = null;
+ private int[] mRecordNumbers = null;
+ private int mCurrentRecordIndex = 0;
+ private Bitmap[] mIcons = null;
+ private HashMap<Integer, Bitmap> mIconsCache = null;
private static IconLoader sLoader = null;
@@ -69,14 +72,16 @@ class IconLoader extends Handler {
private IconLoader(Looper looper , SIMFileHandler fh) {
super(looper);
mSimFH = fh;
+
+ mIconsCache = new HashMap<Integer, Bitmap>(50);
}
- static IconLoader getInstance(Handler caller , SIMFileHandler fh) {
+ static IconLoader getInstance(Handler caller, SIMFileHandler fh) {
if (sLoader != null) {
return sLoader;
}
if (fh != null) {
- HandlerThread thread = new HandlerThread("Stk Icon Laoder");
+ HandlerThread thread = new HandlerThread("Stk Icon Loader");
thread.start();
return new IconLoader(thread.getLooper(), fh);
}
@@ -104,7 +109,7 @@ class IconLoader extends Handler {
mState = STATE_SINGLE_ICON;
startLoadingIcon(recordNumber);
}
-
+
private void startLoadingIcon(int recordNumber) {
// Reset the load variables.
mId = null;
@@ -112,6 +117,13 @@ class IconLoader extends Handler {
mCurrentIcon = null;
mRecordNumber = recordNumber;
+ // make sure the icon was not already loaded and saved in the local cache.
+ if (mIconsCache.containsKey(recordNumber)) {
+ mCurrentIcon = mIconsCache.get(recordNumber);
+ postIcon();
+ return;
+ }
+
// start the first phase ==> loading Image Descriptor.
readId();
}
@@ -134,6 +146,7 @@ class IconLoader extends Handler {
byte[] rawData = ((byte[]) ar.result);
if (mId.codingScheme == ImageDescriptor.CODING_SCHEME_BASIC) {
mCurrentIcon = parseToBnW(rawData, rawData.length);
+ mIconsCache.put(mRecordNumber, mCurrentIcon);
postIcon();
} else if (mId.codingScheme == ImageDescriptor.CODING_SCHEME_COLOUR) {
mIconData = rawData;
@@ -145,6 +158,7 @@ class IconLoader extends Handler {
byte [] clut = ((byte[]) ar.result);
mCurrentIcon = parseToRGB(mIconData, mIconData.length,
false, clut);
+ mIconsCache.put(mRecordNumber, mCurrentIcon);
postIcon();
break;
}
@@ -181,6 +195,11 @@ class IconLoader extends Handler {
// Start reading Image Descriptor from SIM card.
private void readId() {
+ if (mRecordNumber < 0) {
+ mCurrentIcon = null;
+ postIcon();
+ return;
+ }
Message msg = this.obtainMessage(EVENT_READ_EF_IMG_RECOED_DONE);
mSimFH.loadEFImgLinearFixed(mRecordNumber, msg);
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/Input.java b/telephony/java/com/android/internal/telephony/gsm/stk/Input.java
new file mode 100644
index 0000000..1f0d971
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/Input.java
@@ -0,0 +1,97 @@
+/*
+ * 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.gsm.stk;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container class for STK GET INPUT, GET IN KEY commands parameters.
+ *
+ */
+public class Input implements Parcelable {
+ public String text;
+ public String defaultText;
+ public Bitmap icon;
+ public int minLen;
+ public int maxLen;
+ public boolean ucs2;
+ public boolean packed;
+ public boolean digitOnly;
+ public boolean echo;
+ public boolean yesNo;
+ public boolean helpAvailable;
+
+ Input() {
+ text = "";
+ defaultText = null;
+ icon = null;
+ minLen = 0;
+ maxLen = 1;
+ ucs2 = false;
+ packed = false;
+ digitOnly = false;
+ echo = false;
+ yesNo = false;
+ helpAvailable = false;
+ }
+
+ private Input(Parcel in) {
+ text = in.readString();
+ defaultText = in.readString();
+ icon = in.readParcelable(null);
+ minLen = in.readInt();
+ maxLen = in.readInt();
+ ucs2 = in.readInt() == 1 ? true : false;
+ packed = in.readInt() == 1 ? true : false;
+ digitOnly = in.readInt() == 1 ? true : false;
+ echo = in.readInt() == 1 ? true : false;
+ yesNo = in.readInt() == 1 ? true : false;
+ helpAvailable = in.readInt() == 1 ? true : false;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(text);
+ dest.writeString(defaultText);
+ dest.writeParcelable(icon, 0);
+ dest.writeInt(minLen);
+ dest.writeInt(maxLen);
+ dest.writeInt(ucs2 ? 1 : 0);
+ dest.writeInt(packed ? 1 : 0);
+ dest.writeInt(digitOnly ? 1 : 0);
+ dest.writeInt(echo ? 1 : 0);
+ dest.writeInt(yesNo ? 1 : 0);
+ dest.writeInt(helpAvailable ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<Input> CREATOR = new Parcelable.Creator<Input>() {
+ public Input createFromParcel(Parcel in) {
+ return new Input(in);
+ }
+
+ public Input[] newArray(int size) {
+ return new Input[size];
+ }
+ };
+
+ boolean setIcon(Bitmap Icon) { return true; }
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/Item.java b/telephony/java/com/android/internal/telephony/gsm/stk/Item.java
index 0122c86..b2f338c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/Item.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/Item.java
@@ -42,6 +42,7 @@ public class Item implements Parcelable {
public Item(Parcel in) {
id = in.readInt();
text = in.readString();
+ icon = in.readParcelable(null);
}
public int describeContents() {
@@ -51,6 +52,7 @@ public class Item implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(text);
+ dest.writeParcelable(icon, flags);
}
public static final Parcelable.Creator<Item> CREATOR = new Parcelable.Creator<Item>() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/Menu.java b/telephony/java/com/android/internal/telephony/gsm/stk/Menu.java
index 5f9de15..40a6b37 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/Menu.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/Menu.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -23,10 +23,15 @@ import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Container class for STK menu (SET UP MENU, SELECT ITEM) parameters.
+ *
+ */
public class Menu implements Parcelable {
public List<Item> items;
- public String title;
public List<TextAttribute> titleAttrs;
+ public PresentationType presentationType;
+ public String title;
public Bitmap titleIcon;
public int defaultItem;
public boolean softKeyPreferred;
@@ -36,28 +41,22 @@ public class Menu implements Parcelable {
public Menu() {
// Create an empty list.
- this.items = new ArrayList<Item>();
- this.title = null;
- this.titleAttrs = null;
- this.defaultItem = 0;
- this.softKeyPreferred = false;
- this.helpAvailable = false;
- this.titleIconSelfExplanatory = false;
- this.titleIcon = null;
- }
-
- public Menu(List<Item> items, String title, List<TextAttribute> titleAttrs,
- boolean softKeyPreferred, boolean helpAvailable, int defaultItem) {
- this.items = items;
- this.title = title;
- this.titleAttrs = titleAttrs;
- this.defaultItem = defaultItem;
- this.softKeyPreferred = softKeyPreferred;
- this.helpAvailable = helpAvailable;
+ items = new ArrayList<Item>();
+ title = null;
+ titleAttrs = null;
+ defaultItem = 0;
+ softKeyPreferred = false;
+ helpAvailable = false;
+ titleIconSelfExplanatory = false;
+ itemsIconSelfExplanatory = false;
+ titleIcon = null;
+ // set default style to be navigation menu.
+ presentationType = PresentationType.NAVIGATION_OPTIONS;
}
private Menu(Parcel in) {
title = in.readString();
+ titleIcon = in.readParcelable(null);
// rebuild items list.
items = new ArrayList<Item>();
int size = in.readInt();
@@ -68,6 +67,9 @@ public class Menu implements Parcelable {
defaultItem = in.readInt();
softKeyPreferred = in.readInt() == 1 ? true : false;
helpAvailable = in.readInt() == 1 ? true : false;
+ titleIconSelfExplanatory = in.readInt() == 1 ? true : false;
+ itemsIconSelfExplanatory = in.readInt() == 1 ? true : false;
+ presentationType = PresentationType.values()[in.readInt()];
}
public int describeContents() {
@@ -76,6 +78,7 @@ public class Menu implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
+ dest.writeParcelable(titleIcon, flags);
// write items list to the parcel.
int size = items.size();
dest.writeInt(size);
@@ -85,6 +88,9 @@ public class Menu implements Parcelable {
dest.writeInt(defaultItem);
dest.writeInt(softKeyPreferred ? 1 : 0);
dest.writeInt(helpAvailable ? 1 : 0);
+ dest.writeInt(titleIconSelfExplanatory ? 1 : 0);
+ dest.writeInt(itemsIconSelfExplanatory ? 1 : 0);
+ dest.writeInt(presentationType.ordinal());
}
public static final Parcelable.Creator<Menu> CREATOR = new Parcelable.Creator<Menu>() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java b/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
new file mode 100644
index 0000000..9afa063
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006-2007 Google Inc.
+ *
+ * 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.stk;
+
+import com.android.internal.telephony.gsm.EncodeException;
+import com.android.internal.telephony.gsm.GsmAlphabet;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+
+abstract class ResponseData {
+ /**
+ * Format the data appropriate for TERMINAL RESPONSE and write it into
+ * the ByteArrayOutputStream object.
+ */
+ public abstract void format(ByteArrayOutputStream buf);
+}
+
+class SelectItemResponseData extends ResponseData {
+ // members
+ private int id;
+
+ public SelectItemResponseData(int id) {
+ super();
+ this.id = id;
+ }
+
+ @Override
+ public void format(ByteArrayOutputStream buf) {
+ // Item identifier object
+ int tag = 0x80 | ComprehensionTlvTag.ITEM_ID.value();
+ buf.write(tag); // tag
+ buf.write(1); // length
+ buf.write(id); // identifier of item chosen
+ }
+}
+
+class GetInkeyInputResponseData extends ResponseData {
+ // members
+ private boolean mIsUcs2;
+ private boolean mIsPacked;
+ private boolean mIsYesNo;
+ private boolean mYesNoResponse;
+ public String mInData;
+
+ // GetInKey Yes/No response characters constants.
+ protected static final byte GET_INKEY_YES = 0x01;
+ protected static final byte GET_INKEY_NO = 0x00;
+
+ public GetInkeyInputResponseData(String inData, boolean ucs2, boolean packed) {
+ super();
+ this.mIsUcs2 = ucs2;
+ this.mIsPacked = packed;
+ this.mInData = inData;
+ this.mIsYesNo = false;
+ }
+
+ public GetInkeyInputResponseData(boolean yesNoResponse) {
+ super();
+ this.mIsUcs2 = false;
+ this.mIsPacked = false;
+ this.mInData = "";
+ this.mIsYesNo = true;
+ this.mYesNoResponse = yesNoResponse;
+ }
+
+ @Override
+ public void format(ByteArrayOutputStream buf) {
+ if (buf == null) {
+ return;
+ }
+
+ // Text string object
+ int tag = 0x80 | ComprehensionTlvTag.TEXT_STRING.value();
+ buf.write(tag); // tag
+
+ byte[] data;
+
+ if (mIsYesNo) {
+ data = new byte[1];
+ data[0] = mYesNoResponse ? GET_INKEY_YES : GET_INKEY_NO;
+ } else if (mInData != null && mInData.length() > 0) {
+ try {
+ if (mIsUcs2) {
+ data = mInData.getBytes("UTF-16");
+ } else if (mIsPacked) {
+ int size = mInData.length();
+
+ byte[] tempData = GsmAlphabet
+ .stringToGsm7BitPacked(mInData);
+ data = new byte[size];
+ // Since stringToGsm7BitPacked() set byte 0 in the
+ // returned byte array to the count of septets used...
+ // copy to a new array without byte 0.
+ System.arraycopy(tempData, 1, data, 0, size);
+ } else {
+ data = GsmAlphabet.stringToGsm8BitPacked(mInData);
+ }
+ } catch (UnsupportedEncodingException e) {
+ data = new byte[0];
+ } catch (EncodeException e) {
+ data = new byte[0];
+ }
+ } else {
+ data = new byte[0];
+ }
+
+ // length - one more for data coding scheme.
+ buf.write(data.length + 1);
+
+ // data coding scheme
+ if (mIsUcs2) {
+ buf.write(0x08); // UCS2
+ } else if (mIsPacked) {
+ buf.write(0x00); // 7 bit packed
+ } else {
+ buf.write(0x04); // 8 bit unpacked
+ }
+
+ for (byte b : data) {
+ buf.write(b);
+ }
+ }
+}
+
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ResultCode.java b/telephony/java/com/android/internal/telephony/gsm/stk/ResultCode.java
index 6559c73..b96a524 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ResultCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ResultCode.java
@@ -171,7 +171,16 @@ public enum ResultCode {
* Retrieves the actual result code that this object represents.
* @return Actual result code
*/
- public int code() {
+ public int value() {
return mCode;
}
+
+ public static ResultCode fromInt(int value) {
+ for (ResultCode r : ResultCode.values()) {
+ if (r.mCode == value) {
+ return r;
+ }
+ }
+ return null;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
new file mode 100644
index 0000000..746b1f1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
@@ -0,0 +1,145 @@
+/*
+ * 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.gsm.stk;
+
+import com.android.internal.telephony.gsm.SIMFileHandler;
+import com.android.internal.telephony.gsm.SimUtils;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * Class used for queuing raw ril messages, decoding them into CommanParams
+ * objects and sending the result back to the STK Service.
+ *
+ */
+class RilMessageDecoder extends Handler {
+
+ // members
+ private final BlockingQueue<RilMessage> mInQueue;
+ private static RilMessageDecoder sInstance = null;
+ private CommandParamsFactory mCmdParamsFactory = null;
+ private RilMessage mCurrentRilMessage = null;
+ private Handler mCaller = null;
+
+ // constants
+ static final int START = 1;
+ static final int CMD_PARAMS_READY = 2;
+
+ static RilMessageDecoder getInstance(BlockingQueue<RilMessage> inQ,
+ Handler caller, SIMFileHandler fh) {
+ if (sInstance != null) {
+ return sInstance;
+ }
+ if (inQ != null) {
+ HandlerThread thread = new HandlerThread("Stk RIL Messages decoder");
+ thread.start();
+ return new RilMessageDecoder(thread.getLooper(), inQ, caller, fh);
+ }
+ return null;
+ }
+
+ private RilMessageDecoder(Looper looper, BlockingQueue<RilMessage> inQ,
+ Handler caller, SIMFileHandler fh) {
+ super(looper);
+ mInQueue = inQ;
+ mCaller = caller;
+ mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh);
+ }
+
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case START:
+ start();
+ break;
+ case CMD_PARAMS_READY:
+ mCurrentRilMessage.mResCode = ResultCode.fromInt(msg.arg1);
+ mCurrentRilMessage.mData = msg.obj;
+ sendCmdForExecution();
+ break;
+ }
+ }
+
+ private void start() {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ mCurrentRilMessage = mInQueue.take();
+ StkLog.d(this, "Decoding new message");
+ break;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ // fall through and retry
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ if (mCurrentRilMessage != null) {
+ decodeMessage(mCurrentRilMessage);
+ }
+ }
+ }
+
+ private void decodeMessage(RilMessage msg) {
+ switch(msg.mId) {
+ case Service.MSG_ID_SESSION_END:
+ case Service.MSG_ID_CALL_SETUP:
+ mCurrentRilMessage.mResCode = ResultCode.OK;
+ sendCmdForExecution();
+ break;
+ case Service.MSG_ID_PROACTIVE_COMMAND:
+ case Service.MSG_ID_EVENT_NOTIFY:
+ case Service.MSG_ID_REFRESH:
+ byte[] rawData = null;
+ try {
+ rawData = SimUtils.hexStringToBytes((String) msg.mData);
+ } catch (Exception e) {
+ // zombie messages are dropped
+ getNextMessage();
+ return;
+ }
+ try {
+ // Start asynch parsing of the command parameters.
+ mCmdParamsFactory.make(BerTlv.decode(rawData));
+ } catch (ResultException e) {
+ // send to Service for proper RIL communication.
+ mCurrentRilMessage.mResCode = e.result();
+ sendCmdForExecution();
+ }
+ break;
+ }
+ }
+
+ private void sendCmdForExecution() {
+ Message msg = mCaller.obtainMessage(Service.MSG_ID_RIL_MSG_DECODED,
+ new RilMessage(mCurrentRilMessage));
+ msg.sendToTarget();
+ getNextMessage();
+ }
+
+ private void getNextMessage() {
+ Message nextMsg = this.obtainMessage(START);
+ nextMsg.sendToTarget();
+ }
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/Service.java b/telephony/java/com/android/internal/telephony/gsm/stk/Service.java
index e002202..aae9b30 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/Service.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/Service.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -16,41 +16,24 @@
package com.android.internal.telephony.gsm.stk;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.os.AsyncResult;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Message;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
import com.android.internal.telephony.gsm.CommandsInterface;
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
import com.android.internal.telephony.gsm.GsmSimCard;
import com.android.internal.telephony.gsm.SIMFileHandler;
import com.android.internal.telephony.gsm.SIMRecords;
import com.android.internal.telephony.gsm.SimUtils;
-import com.android.internal.telephony.gsm.stk.Duration.TimeUnit;
import android.util.Config;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.RemoteViews;
-import android.widget.TextView;
-import android.widget.Toast;
import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
/**
* Enumeration for representing the tag value of COMPREHENSION-TLV objects. If
@@ -93,51 +76,12 @@ enum ComprehensionTlvTag {
*
* @return Actual tag value of this object
*/
- public int value() {
- return mValue;
- }
-}
-
-/**
- * Enumeration for representing "Type of Command" of proactive commands. If you
- * want to create a CommandType object, call the static method {@link
- * #fromInt(int) fromInt}.
- *
- * {@hide}
- */
-enum CommandType {
- DISPLAY_TEXT(0x21),
- GET_INKEY(0x22),
- GET_INPUT(0x23),
- LAUNCH_BROWSER(0x15),
- PLAY_TONE(0x20),
- REFRESH(0x01),
- SELECT_ITEM(0x24),
- SEND_SS(0x11),
- SEND_USSD(0x12),
- SEND_SMS(0x13),
- SEND_DTMF(0x14),
- SET_UP_EVENT_LIST(0x05),
- SET_UP_IDLE_MODE_TEXT(0x28),
- SET_UP_MENU(0x25),
- SET_UP_CALL(0x10);
-
- private int mValue;
-
- CommandType(int value) {
- mValue = value;
- }
+ public int value() {
+ return mValue;
+ }
- /**
- * Create a CommandType object.
- *
- * @param value Integer value to be converted to a CommandType object.
- * @return CommandType object whose "Type of Command" value is {@code
- * value}. If no CommandType object has that value, null is
- * returned.
- */
- public static CommandType fromInt(int value) {
- for (CommandType e : CommandType.values()) {
+ public static ComprehensionTlvTag fromInt(int value) {
+ for (ComprehensionTlvTag e : ComprehensionTlvTag.values()) {
if (e.mValue == value) {
return e;
}
@@ -146,8 +90,26 @@ enum CommandType {
}
}
+class RilMessage {
+ int mId;
+ Object mData;
+ ResultCode mResCode;
+
+ RilMessage(int msgId, String rawData) {
+ mId = msgId;
+ mData = rawData;
+ }
+
+ RilMessage(RilMessage other) {
+ this.mId = other.mId;
+ this.mData = other.mData;
+ this.mResCode = other.mResCode;
+ }
+}
+
/**
- * Main class that implements SIM Toolkit Service.
+ * Class that implements SIM Toolkit Telephony Service. Interacts with the RIL
+ * and application.
*
* {@hide}
*/
@@ -158,30 +120,26 @@ public class Service extends Handler implements AppInterface {
private CommandsInterface mCmdIf;
private SIMRecords mSimRecords;
private Context mContext;
- private GsmSimCard mSimCard;
- private CommandListener mCmdListener;
- private Object mCmdListenerLock = new Object();
- private CommandParams mCmdParams = null;
- private CommandParams mNextCmdParams = null;
- private State mState = State.IDLE;
- private Menu mMainMenu = null;
- private String mServiceName = "";
- private NotificationManager mNm = null;
- private int mAppIndicator = APP_INDICATOR_PRE_BOOT;
- private int mInstallIndicator = APP_INDICATOR_UNINSTALLED;
- private IconLoader mIconLoader = null;
-
- private static final String TAG = "STK";
+ private StkCmdMessage mCurrntCmd = null;
+ private StkCmdMessage mMenuCmd = null;
+
+ private BlockingQueue<RilMessage> mRilMessagesQ = null;
+ private RilMessageDecoder mMsgDecoder = null;
+
+ public static final String TAG = "STK";
// Service constants.
- private static final int EVENT_SESSION_END = 1;
- private static final int EVENT_PROACTIVE_COMMAND = 2;
- private static final int EVENT_EVENT_NOTIFY = 3;
- private static final int EVENT_CALL_SETUP = 4;
+ static final int MSG_ID_SESSION_END = 1;
+ static final int MSG_ID_PROACTIVE_COMMAND = 2;
+ static final int MSG_ID_EVENT_NOTIFY = 3;
+ static final int MSG_ID_CALL_SETUP = 4;
+ static final int MSG_ID_REFRESH = 5;
+ static final int MSG_ID_RESPONSE = 6;
+
+ static final int MSG_ID_RIL_MSG_DECODED = 10;
+
// Events to signal SIM presence or absent in the device.
- private static final int EVENT_SIM_LOADED = 12;
- private static final int EVENT_SIM_ABSENT = 13;
- static final int EVENT_LOAD_ICON_DONE = 14;
+ private static final int MSG_ID_SIM_LOADED = 20;
private static final int DEV_ID_KEYPAD = 0x01;
private static final int DEV_ID_DISPLAY = 0x02;
@@ -190,64 +148,6 @@ public class Service extends Handler implements AppInterface {
private static final int DEV_ID_TERMINAL = 0x82;
private static final int DEV_ID_NETWORK = 0x83;
- // Event value for Event List COMPREHENSION-TLV object
- public static final int UICC_EVENT_MT_CALL = 0x00;
- public static final int UICC_EVENT_CALL_CONNECTED = 0x01;
- public static final int UICC_EVENT_CALL_DISCONNECTED = 0x02;
- public static final int UICC_EVENT_LOCATION_STATUS = 0x03;
- public static final int UICC_EVENT_USER_ACTIVITY = 0x04;
- public static final int UICC_EVENT_IDLE_SCREEN_AVAILABLE = 0x05;
- public static final int UICC_EVENT_CARD_READER_STATUS = 0x06;
- public static final int UICC_EVENT_LANGUAGE_SELECTION = 0x07;
- public static final int UICC_EVENT_BROWSER_TERMINATION = 0x08;
- public static final int UICC_EVENT_DATA_AVAILABLE = 0x09;
- public static final int UICC_EVENT_CHANNEL_STATUS = 0x0a;
- public static final int UICC_EVENT_ACCESS_TECH_CHANGE = 0x0b;
- public static final int UICC_EVENT_DISPLAY_PARAMS_CHANGE = 0x0c;
- public static final int UICC_EVENT_LOCAL_CONNECTION = 0x0d;
- public static final int UICC_EVENT_NETWORK_SEARCH_MODE_CHANGE = 0x0e;
- public static final int UICC_EVENT_BROWSING_STATUS = 0x0f;
- public static final int UICC_EVENT_FRAMES_INFO_CHANGE = 0x10;
- public static final int UICC_EVENT_I_WLAN_ACESS_STATUS = 0x11;
-
- // Command Qualifier values
- static final int REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE = 0x00;
- static final int REFRESH_NAA_INIT_AND_FILE_CHANGE = 0x02;
- static final int REFRESH_NAA_INIT = 0x03;
- static final int REFRESH_UICC_RESET = 0x04;
-
- // GetInKey Yes/No response characters constants.
- private static final byte GET_INKEY_YES = 0x01;
- private static final byte GET_INKEY_NO = 0x00;
-
- // Notification id used to display Idle Mode text in NotificationManager.
- static final int STK_NOTIFICATION_ID = 333;
-
- private static String APP_PACKAGE_NAME = "com.android.stk";
- private static String APP_FULL_NAME = APP_PACKAGE_NAME + ".StkActivity";
-
- // Application indicators constants
- static final int APP_INDICATOR_PRE_BOOT = 0;
- static final int APP_INDICATOR_UNINSTALLED = 1;
- static final int APP_INDICATOR_INSTALLED_NORMAL = 2;
- static final int APP_INDICATOR_INSTALLED_SPECIAL = 3;
- private static final int APP_INDICATOR_LAUNCHED = 4;
- // Use setAppIndication(APP_INSTALL_INDICATOR) to go back for the original
- // install indication.
- private static final int APP_INSTALL_INDICATOR = 5;
-
- // Container class to hold temporary icon identifier TLV object info.
- class IconId {
- int recordNumber;
- boolean selfExplanatory;
- }
-
- // Container class to hold temporary item icon identifier list TLV object info.
- class ItemsIconId {
- int [] recordNumbers;
- boolean selfExplanatory;
- }
-
/* Intentionally private for singleton */
private Service(CommandsInterface ci, SIMRecords sr, Context context,
SIMFileHandler fh, GsmSimCard sc) {
@@ -259,108 +159,200 @@ public class Service extends Handler implements AppInterface {
mCmdIf = ci;
mContext = context;
- mCmdIf.setOnStkSessionEnd(this, EVENT_SESSION_END, null);
- mCmdIf.setOnStkProactiveCmd(this, EVENT_PROACTIVE_COMMAND, null);
- mCmdIf.setOnStkEvent(this, EVENT_EVENT_NOTIFY, null);
- mCmdIf.setOnStkCallSetUp(this, EVENT_CALL_SETUP, null);
-
- mSimRecords = sr;
+ // Initialize a blocking queue to be used for ril messages, and a
+ // RilMessagesDecoder for decoding the messages into a CommandParams.
+ // Each CommandParams is put into a SynchronousQueue and pulled by the
+ // Service take() when its ready to handle the next command.
+ mRilMessagesQ = new LinkedBlockingQueue<RilMessage>();
+ mMsgDecoder = RilMessageDecoder.getInstance(mRilMessagesQ, this, fh);
- mSimCard = sc;
- mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- mIconLoader = IconLoader.getInstance(this, fh);
+ // Register ril events handling.
+ mCmdIf.setOnStkSessionEnd(this, MSG_ID_SESSION_END, null);
+ mCmdIf.setOnStkProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null);
+ mCmdIf.setOnStkEvent(this, MSG_ID_EVENT_NOTIFY, null);
+ mCmdIf.setOnStkCallSetUp(this, MSG_ID_CALL_SETUP, null);
+ //mCmdIf.setOnSimRefresh(this, MSG_ID_REFRESH, null);
- // Register a receiver for install/unistall application.
- StkAppStateReceiver receiver = new StkAppStateReceiver();
- IntentFilter filter = new IntentFilter();
- filter.addAction(StkAppInstaller.STK_APP_INSTALL_ACTION);
- filter.addAction(StkAppInstaller.STK_APP_UNINSTALL_ACTION);
- mContext.registerReceiver(receiver, filter);
+ mSimRecords = sr;
// Register for SIM ready event.
- mSimRecords.registerForRecordsLoaded(this, EVENT_SIM_LOADED, null);
- mSimCard.registerForAbsent(this, EVENT_SIM_ABSENT, null);
+ mSimRecords.registerForRecordsLoaded(this, MSG_ID_SIM_LOADED, null);
+ // start decoding ril messages.
+ mMsgDecoder.obtainMessage(RilMessageDecoder.START).sendToTarget();
}
- /**
- * Used for retrieving the only Service object in the system. There is only
- * one Service object.
- *
- * @param ci CommandsInterface object
- * @param sr SIMRecords object
- * @return The only Service object in the system
- */
- public static Service getInstance(CommandsInterface ci, SIMRecords sr,
- Context context, SIMFileHandler fh, GsmSimCard sc) {
- if (sInstance == null) {
- if (ci == null || sr == null || context == null || fh == null
- || sc == null) {
- return null;
+ private void handleRilMsg(RilMessage rilMsg) {
+ if (rilMsg == null) {
+ return;
+ }
+
+ // dispatch messages
+ CommandParams cmdParams = null;
+ switch (rilMsg.mId) {
+ case MSG_ID_EVENT_NOTIFY:
+ if (rilMsg.mResCode == ResultCode.OK) {
+ cmdParams = (CommandParams) rilMsg.mData;
+ if (cmdParams != null) {
+ handleProactiveCommand(cmdParams);
+ }
}
- sInstance = new Service(ci, sr, context, fh, sc);
+ break;
+ case MSG_ID_PROACTIVE_COMMAND:
+ cmdParams = (CommandParams) rilMsg.mData;
+ if (cmdParams != null) {
+ if (rilMsg.mResCode == ResultCode.OK) {
+ handleProactiveCommand(cmdParams);
+ } else {
+ // for proactive commands that couldn't be decoded
+ // successfully respond with the code generated by the
+ // message decoder.
+ sendTerminalResponse(cmdParams.cmdDet, rilMsg.mResCode,
+ false, 0, null);
+ }
+ }
+ break;
+ case MSG_ID_REFRESH:
+ cmdParams = (CommandParams) rilMsg.mData;
+ if (cmdParams != null) {
+ handleProactiveCommand(cmdParams);
+ }
+ break;
+ case MSG_ID_SESSION_END:
+ handleSessionEnd();
+ break;
+ case MSG_ID_CALL_SETUP:
+ // prior event notify command supplied all the information
+ // needed for set up call processing.
+ break;
}
- return sInstance;
}
/**
- * Used for retrieving the only Service object in the system. There is only
- * one Service object.
+ * Handles RIL_UNSOL_STK_PROACTIVE_COMMAND unsolicited command from RIL.
+ * Sends valid proactive command data to the application using intents.
*
- * @return The only Service object in the system
*/
- public static Service getInstance() {
- return getInstance(null, null, null, null, null);
- }
+ private void handleProactiveCommand(CommandParams cmdParams) {
+ StkLog.d(this, cmdParams.getCommandType().name());
- /**
- * {@inheritDoc}
- */
- public void setCommandListener(CommandListener l) {
- synchronized (mCmdListenerLock) {
- mCmdListener = l;
- if (mCmdListener != null) {
- setAppIndication(APP_INDICATOR_LAUNCHED);
+ StkCmdMessage cmdMsg = new StkCmdMessage(cmdParams);
+ switch (cmdParams.getCommandType()) {
+ case SET_UP_MENU:
+ if (removeMenu(cmdMsg.getMenu())) {
+ mMenuCmd = null;
} else {
- setAppIndication(APP_INSTALL_INDICATOR);
+ mMenuCmd = cmdMsg;
+ }
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0,
+ null);
+ break;
+ case DISPLAY_TEXT:
+ // when application is not required to respond, send an immediate
+ // response.
+ if (!cmdMsg.geTextMessage().responseNeeded) {
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false,
+ 0, null);
}
- }
- }
-
- synchronized void setAppIndication(int indication) {
- switch(indication) {
- case APP_INDICATOR_PRE_BOOT:
- case APP_INDICATOR_UNINSTALLED:
- case APP_INDICATOR_INSTALLED_NORMAL:
- case APP_INDICATOR_INSTALLED_SPECIAL:
- case APP_INDICATOR_LAUNCHED:
- mAppIndicator = indication;
break;
- case APP_INSTALL_INDICATOR:
- mAppIndicator = mInstallIndicator;
+ case REFRESH:
+ // ME side only handles refresh commands which meant to remove IDLE
+ // MODE TEXT.
+ cmdParams.cmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT
+ .value();
+ break;
+ case SET_UP_IDLE_MODE_TEXT:
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false,
+ 0, null);
+ break;
+ case LAUNCH_BROWSER:
+ case SELECT_ITEM:
+ case GET_INPUT:
+ case GET_INKEY:
+ case SEND_DTMF:
+ case SEND_SMS:
+ case SEND_SS:
+ case SEND_USSD:
+ case PLAY_TONE:
+ case SET_UP_CALL:
+ // nothing to do on telephony!
break;
default:
- throw new NullPointerException("Trying to set wrong app indication");
+ StkLog.d(this, "Unsupported command");
+ return;
}
- }
-
- public synchronized int getAppIndication() {
- return mAppIndicator;
+ mCurrntCmd = cmdMsg;
+ Intent intent = new Intent(AppInterface.STK_CMD_ACTION);
+ intent.putExtra("STK CMD", cmdMsg);
+ mContext.sendBroadcast(intent);
}
/**
- * {@inheritDoc}
+ * Handles RIL_UNSOL_STK_SESSION_END unsolicited command from RIL.
+ *
*/
- public State getState() {
- return mState;
+ private void handleSessionEnd() {
+ StkLog.d(this, "SESSION END");
+
+ mCurrntCmd = mMenuCmd;
+ Intent intent = new Intent(AppInterface.STK_SESSION_END_ACTION);
+ mContext.sendBroadcast(intent);
}
- /**
- * {@inheritDoc}
- */
- public void notifyMenuSelection(int menuId, boolean helpRequired) {
- if (mState != State.MAIN_MENU) {
+ private void sendTerminalResponse(CommandDetails cmdDet,
+ ResultCode resultCode, boolean includeAdditionalInfo,
+ int additionalInfo, ResponseData resp) {
+
+ if (cmdDet == null) {
return;
}
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ // command details
+ int tag = ComprehensionTlvTag.COMMAND_DETAILS.value();
+ if (cmdDet.compRequired) {
+ tag |= 0x80;
+ }
+ buf.write(tag);
+ buf.write(0x03); // length
+ buf.write(cmdDet.commandNumber);
+ buf.write(cmdDet.typeOfCommand);
+ buf.write(cmdDet.commandQualifier);
+
+ // device identities
+ tag = 0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value();
+ buf.write(tag);
+ buf.write(0x02); // length
+ buf.write(DEV_ID_TERMINAL); // source device id
+ buf.write(DEV_ID_UICC); // destination device id
+
+ // result
+ tag = 0x80 | ComprehensionTlvTag.RESULT.value();
+ buf.write(tag);
+ int length = includeAdditionalInfo ? 2 : 1;
+ buf.write(length);
+ buf.write(resultCode.value());
+
+ // additional info
+ if (includeAdditionalInfo) {
+ buf.write(additionalInfo);
+ }
+
+ // Fill optional data for each corresponding command
+ if (resp != null) {
+ resp.format(buf);
+ }
+
+ byte[] rawData = buf.toByteArray();
+ String hexString = SimUtils.bytesToHexString(rawData);
+ if (Config.LOGD) {
+ StkLog.d(this, "TERMINAL RESPONSE: " + hexString);
+ }
+
+ mCmdIf.sendTerminalResponse(hexString, null);
+ }
+
+
+ private void sendMenuSelection(int menuId, boolean helpRequired) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
@@ -402,112 +394,6 @@ public class Service extends Handler implements AppInterface {
mCmdIf.sendEnvelope(hexString, null);
}
- /**
- * {@inheritDoc}
- */
- public void notifyUserActivity() {
- eventDownload(UICC_EVENT_USER_ACTIVITY, DEV_ID_TERMINAL, DEV_ID_UICC,
- null, true);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyDisplayTextEnded(ResultCode terminationCode) {
- if (mState != State.DISPLAY_TEXT) {
- return;
- }
- ResultCode rc = ResultCode.OK;
-
- switch (terminationCode) {
- case OK:
- case BACKWARD_MOVE_BY_USER:
- case NO_RESPONSE_FROM_USER:
- rc = terminationCode;
- break;
- default:
- Log.d(TAG, "Invalid termination code for Display Text");
- return;
- }
- sendTerminalResponse(mCmdParams.cmdDet, rc, false, 0, null);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyToneEnded() {
- if (mState != State.PLAY_TONE) {
- return;
- }
-
- sendTerminalResponse(mCmdParams.cmdDet, ResultCode.OK, false, 0,
- null);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyIdleScreenAvailable() {
- eventDownload(UICC_EVENT_IDLE_SCREEN_AVAILABLE, DEV_ID_DISPLAY,
- DEV_ID_UICC, null, true);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyLanguageSelection(String langCode) {
- assert langCode.length() == 2 : "Language code must be two characters";
-
- byte[] lang = GsmAlphabet.stringToGsm8BitPacked(langCode);
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- // language
- int tag = 0x80 | ComprehensionTlvTag.LANGUAGE.value();
- buf.write(tag);
- buf.write(0x02); // length
- buf.write(lang[0]);
- buf.write(lang[1]);
-
- byte[] info = buf.toByteArray();
-
- eventDownload(UICC_EVENT_LANGUAGE_SELECTION, DEV_ID_TERMINAL,
- DEV_ID_UICC, info, false);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyBrowserTermination(boolean isErrorTermination) {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- int cause = isErrorTermination ? 1 : 0;
-
- // browser termination cause
- int tag = 0x80 | ComprehensionTlvTag.BROWSER_TERMINATION_CAUSE.value();
- buf.write(tag);
- buf.write(0x01); // length
- buf.write(cause);
-
- byte[] info = buf.toByteArray();
-
- eventDownload(UICC_EVENT_BROWSER_TERMINATION, DEV_ID_TERMINAL,
- DEV_ID_UICC, info, true);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyLaunchBrowser(boolean userConfirmed) {
-
- if (mState != State.LAUNCH_BROWSER) {
- return;
- }
-
- ResultCode rc = userConfirmed ? ResultCode.OK
- : ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS;
- sendTerminalResponse(mCmdParams.cmdDet, rc, false, 0, null);
- }
-
private void eventDownload(int event, int sourceId, int destinationId,
byte[] additionalInfo, boolean oneShot) {
@@ -552,1916 +438,170 @@ public class Service extends Handler implements AppInterface {
}
/**
- * {@inheritDoc}
- */
- public void notifyInkey(char key, boolean helpRequired) {
- if (mState != State.GET_INKEY) {
- return;
- }
-
- GetInkeyInputResponseData resp = null;
- ResultCode result = ResultCode.OK;
- GetInkeyParams request = (GetInkeyParams) mCmdParams;
- if (helpRequired) {
- result = ResultCode.HELP_INFO_REQUIRED;
- } else {
- resp = new GetInkeyInputResponseData(Character.toString(key),
- request.isUcs2, false);
- }
-
- sendTerminalResponse(request.cmdDet, result, false, 0, resp);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyInkey(boolean yesNoResponse, boolean helpRequired) {
- if (mState != State.GET_INKEY) {
- return;
- }
-
- GetInkeyInputResponseData resp = null;
- ResultCode result = ResultCode.OK;
- GetInkeyParams cmdParams = (GetInkeyParams) mCmdParams;
- if (!cmdParams.isYesNo) {
- // Illegal use of this call.
- return;
- }
- if (helpRequired) {
- result = ResultCode.HELP_INFO_REQUIRED;
- } else {
- resp = new GetInkeyInputResponseData(yesNoResponse);
- }
-
- sendTerminalResponse(cmdParams.cmdDet, result, false, 0, resp);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyInput(String input, boolean helpRequired) {
- if (mState != State.GET_INPUT) {
- return;
- }
-
- GetInkeyInputResponseData resp = null;
- GetInputParams cmdParams = (GetInputParams) mCmdParams;
- ResultCode result = ResultCode.OK;
-
- if (helpRequired) {
- result = ResultCode.HELP_INFO_REQUIRED;
- } else {
- resp = new GetInkeyInputResponseData(input, cmdParams.isUcs2,
- cmdParams.isPacked);
- }
- sendTerminalResponse(cmdParams.cmdDet, result, false, 0, resp);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifySelectedItem(int id, boolean helpRequired) {
- if (mState != State.SELECT_ITEM) {
- return;
- }
-
- SelectItemResponseData resp = new SelectItemResponseData(id);
- ResultCode result = helpRequired ? ResultCode.HELP_INFO_REQUIRED
- : ResultCode.OK;
-
- sendTerminalResponse(mCmdParams.cmdDet, result, false, 0, resp);
- }
-
- /**
- * {@inheritDoc}
- */
- public void notifyNoResponse() {
- CtlvCommandDetails cmdDet = getCurrentCmdDet();
- if (cmdDet == null) {
- // Unable to continue;
- return;
- }
- sendTerminalResponse(cmdDet, ResultCode.NO_RESPONSE_FROM_USER, false,
- 0, null);
- }
-
- /**
- * {@inheritDoc}
- */
- public void acceptOrRejectCall(boolean accept) {
- if (mState != State.CALL_SETUP) {
- return;
- }
- mCmdIf.handleCallSetupRequestFromSim(accept, null);
- }
-
- /**
- * Indicates if STK is supported by the SIM card.
+ * Used for instantiating the Service from the GsmPhone constructor.
+ *
+ * @param ci CommandsInterface object
+ * @param sr SIMRecords object
+ * @param context phone app context
+ * @param fh SIM file handler
+ * @param sc GSM SIM card
+ * @return The only Service object in the system
*/
- public boolean isStkSupported() {
- switch (getAppIndication()) {
- case APP_INDICATOR_PRE_BOOT:
- case APP_INDICATOR_UNINSTALLED:
- return false;
+ public static Service getInstance(CommandsInterface ci, SIMRecords sr,
+ Context context, SIMFileHandler fh, GsmSimCard sc) {
+ if (sInstance == null) {
+ if (ci == null || sr == null || context == null || fh == null
+ || sc == null) {
+ return null;
+ }
+ HandlerThread thread = new HandlerThread("Stk Telephony service");
+ thread.start();
+ sInstance = new Service(ci, sr, context, fh, sc);
}
-
- return true;
+ return sInstance;
}
/**
- * Returns the unique service name for STK.
+ * Used by application to get an AppInterface object.
+ *
+ * @return The only Service object in the system
*/
- public String getServiceName() {
- return mServiceName;
+ public static AppInterface getInstance() {
+ return getInstance(null, null, null, null, null);
}
/**
* {@inheritDoc}
*/
public void handleMessage(Message msg) {
- AsyncResult ar;
switch (msg.what) {
- case EVENT_SESSION_END:
- ar = (AsyncResult) msg.obj;
- handleSessionEnd(ar.result);
- break;
- case EVENT_PROACTIVE_COMMAND:
- ar = (AsyncResult) msg.obj;
- handleProactiveCommand((String) ar.result);
+ case MSG_ID_SESSION_END:
+ case MSG_ID_PROACTIVE_COMMAND:
+ case MSG_ID_EVENT_NOTIFY:
+ case MSG_ID_REFRESH:
+ StkLog.d(this, "ril message arrived");
+ String data = null;
+ if (msg.obj != null) {
+ AsyncResult ar = (AsyncResult) msg.obj;
+ if (ar != null && ar.result != null) {
+ try {
+ data = (String) ar.result;
+ } catch (ClassCastException e) {
+ break;
+ }
+ }
+ }
+ mRilMessagesQ.add(new RilMessage(msg.what, data));
break;
- case EVENT_EVENT_NOTIFY:
- ar = (AsyncResult) msg.obj;
- handleEventNotify((String) ar.result);
+ case MSG_ID_CALL_SETUP:
+ mRilMessagesQ.add(new RilMessage(msg.what, null));
break;
- case EVENT_CALL_SETUP:
- mState = State.CALL_SETUP;
+ case MSG_ID_SIM_LOADED:
break;
- case EVENT_SIM_LOADED:
- case EVENT_SIM_ABSENT:
- if (!isStkSupported()) {
- setAppState(false);
- }
+ case MSG_ID_RIL_MSG_DECODED:
+ handleRilMsg((RilMessage) msg.obj);
break;
- case EVENT_LOAD_ICON_DONE:
- handleProactiveCommandIcons(msg.obj);
+ case MSG_ID_RESPONSE:
+ handleCmdResponse((StkResponseMessage) msg.obj);
break;
default:
throw new AssertionError("Unrecognized STK command: " + msg.what);
}
}
-
- /**
- * Send terminal response for backward move in the proactive SIM session
- * requested by the user
- *
- * Only available when responding following proactive commands
- * DISPLAY_TEXT(0x21),
- * GET_INKEY(0x22),
- * GET_INPUT(0x23),
- * SET_UP_MENU(0x25);
- *
- * @return true if stk can send backward move response
- *
- */
- public boolean backwardMove() {
- CtlvCommandDetails cmdDet = null;
-
- cmdDet = getCurrentCmdDet();
-
- if (cmdDet == null) {
- return false;
- }
-
- sendTerminalResponse(cmdDet, ResultCode.BACKWARD_MOVE_BY_USER, false,
- 0, null);
- return true;
- }
-
- /**
- * Send terminal response for proactive SIM session terminated by the user
- *
- * Only available when responding following proactive commands
- * DISPLAY_TEXT(0x21),
- * GET_INKEY(0x22),
- * GET_INPUT(0x23),
- * PLAY_TONE(0x20),
- * SET_UP_MENU(0x25);
- *
- * @return true if stk can send terminate session response
- */
- public boolean terminateSession() {
- CtlvCommandDetails cmdDet = null;
-
- cmdDet = getCurrentCmdDet();
-
- if (cmdDet == null) {
- return false;
- }
-
- sendTerminalResponse(cmdDet, ResultCode.UICC_SESSION_TERM_BY_USER,
- false, 0, null);
- mState = State.MAIN_MENU;
- return true;
- }
-
- private CtlvCommandDetails getCurrentCmdDet() {
- CtlvCommandDetails cmdDet = null;
- if (mCmdParams != null) {
- cmdDet = mCmdParams.cmdDet;
+ public synchronized void onCmdResponse(StkResponseMessage resMsg) {
+ if (resMsg == null) {
+ return;
}
-
- return cmdDet;
+ // queue a response message.
+ Message msg = this.obtainMessage(MSG_ID_RESPONSE, resMsg);
+ msg.sendToTarget();
}
- /**
- * Handles RIL_UNSOL_STK_SESSION_END unsolicited command from RIL.
- *
- * @param data Null object. Do not use this.
- */
- private void handleSessionEnd(Object data) {
- if (Config.LOGD) {
- Log.d(TAG, "handleSessionEnd begins");
+ private boolean validateResponse(StkResponseMessage resMsg) {
+ if (mCurrntCmd != null) {
+ return (resMsg.cmdDet.compareTo(mCurrntCmd.mCmdDet));
}
- switch (mInstallIndicator) {
- case APP_INDICATOR_INSTALLED_NORMAL:
- mState = State.MAIN_MENU;
- break;
- case APP_INDICATOR_INSTALLED_SPECIAL:
- case APP_INDICATOR_UNINSTALLED:
- mState = State.IDLE;
- break;
- default:
- Log.d(TAG, "Can't set service state");
- }
- synchronized (mCmdListenerLock) {
- if (mCmdListener != null) {
- mCmdListener.onSessionEnd();
- }
- }
- }
-
- class CtlvDeviceIdentities {
- public int sourceId;
- public int destinationId;
- }
-
- abstract class ResponseData {
- /**
- * Format the data appropriate for TERMINAL RESPONSE and write it into
- * the ByteArrayOutputStream object.
- */
- public abstract void format(ByteArrayOutputStream buf);
+ return false;
}
- class GetInkeyInputResponseData extends ResponseData {
- private boolean mIsUcs2;
- private boolean mIsPacked;
- private boolean mIsYesNo;
- private boolean mYesNoResponse;
- public String mInData;
-
- public GetInkeyInputResponseData(String inData, boolean ucs2,
- boolean packed) {
- super();
- this.mIsUcs2 = ucs2;
- this.mIsPacked = packed;
- this.mInData = inData;
- this.mIsYesNo = false;
- }
-
- public GetInkeyInputResponseData(boolean yesNoResponse) {
- super();
- this.mIsUcs2 = false;
- this.mIsPacked = false;
- this.mInData = "";
- this.mIsYesNo = true;
- this.mYesNoResponse = yesNoResponse;
- }
-
- @Override
- public void format(ByteArrayOutputStream buf) {
- if (buf == null) {
- return;
- }
-
- // Text string object
- int tag = 0x80 | ComprehensionTlvTag.TEXT_STRING.value();
- buf.write(tag); // tag
-
- byte[] data;
-
- if (mIsYesNo) {
- data = new byte[1];
- data[0] = mYesNoResponse ? GET_INKEY_YES : GET_INKEY_NO;
- } else if (mInData != null && mInData.length() > 0) {
- try {
- if (mIsUcs2) {
- data = mInData.getBytes("UTF-16");
- } else if (mIsPacked) {
- int size = mInData.length();
-
- byte[] tempData = GsmAlphabet
- .stringToGsm7BitPacked(mInData);
- data = new byte[size];
- // Since stringToGsm7BitPacked() set byte 0 in the
- // returned byte array to the count of septets used...
- // copy to a new array without byte 0.
- System.arraycopy(tempData, 1, data, 0, size);
- } else {
- data = GsmAlphabet.stringToGsm8BitPacked(mInData);
- }
- } catch (UnsupportedEncodingException e) {
- data = new byte[0];
- } catch (EncodeException e) {
- data = new byte[0];
- }
- } else {
- data = new byte[0];
- }
-
- // length - one more for data coding scheme.
- buf.write(data.length + 1);
-
- // data coding scheme
- if (mIsUcs2) {
- buf.write(0x08); // UCS2
- } else if (mIsPacked) {
- buf.write(0x00); // 7 bit packed
- } else {
- buf.write(0x04); // 8 bit unpacked
- }
-
- for (byte b : data) {
- buf.write(b);
+ private boolean removeMenu(Menu menu) {
+ try {
+ if (menu.items.size() == 1 && menu.items.get(0) == null) {
+ return true;
}
+ } catch (NullPointerException e) {
+ StkLog.d(this, "Unable to get Menu's items size");
+ return true;
}
+ return false;
}
- class SelectItemResponseData extends ResponseData {
- private int id;
-
- public SelectItemResponseData(int id) {
- super();
- this.id = id;
- }
-
- @Override
- public void format(ByteArrayOutputStream buf) {
- // Item identifier object
- int tag = 0x80 | ComprehensionTlvTag.ITEM_ID.value();
- buf.write(tag); // tag
- buf.write(1); // length
- buf.write(id); // identifier of item chosen
- }
- }
-
- /**
- * Handles RIL_UNSOL_STK_PROACTIVE_COMMAND unsolicited command from RIL.
- * This method parses the data transmitted from the SIM card, and handles
- * the command according to the "Type of Command". Each proactive command is
- * handled by a corresponding handleXXX() method.
- *
- * @param data String containing SAT/USAT proactive command in hexadecimal
- * format starting with command tag
- */
- private void handleProactiveCommand(String data) {
- if (Config.LOGD) {
- Log.d(TAG, "handleProactiveCommand begins");
- }
- // If commands arrives before the SIM loaded/SIM absent events have
- // arrived post a message for a delayed processing in 2 seconds.
- if (getAppIndication() == APP_INDICATOR_PRE_BOOT) {
- Message installMsg = this.obtainMessage(EVENT_PROACTIVE_COMMAND);
- AsyncResult.forMessage(installMsg, data, null);
- sendMessageDelayed(installMsg, 2000);
+ private void handleCmdResponse(StkResponseMessage resMsg) {
+ // make sure the response details match the last valid command.
+ if (!validateResponse(resMsg)) {
return;
}
+ ResponseData resp = null;
+ boolean helpRequired = false;
+ CommandDetails cmdDet = resMsg.getCmdDetails();
- CtlvCommandDetails cmdDet = null;
- try {
- byte[] rawData = SimUtils.hexStringToBytes(data);
- BerTlv berTlv = BerTlv.decode(rawData);
-
- List<ComprehensionTlv> ctlvs = berTlv.getComprehensionTlvs();
- cmdDet = retrieveCommandDetails(ctlvs);
-
- CommandType cmdType = CommandType.fromInt(cmdDet.typeOfCommand);
- if (cmdType == null) {
- throw new ResultException(ResultCode.BEYOND_TERMINAL_CAPABILITY);
- }
-
- // SET UP MENU & SET up IDLE MODE TEXT commands should not trigger
- // the special install & launch sequence.
- if (cmdType != CommandType.SET_UP_MENU
- && cmdType != CommandType.SET_UP_IDLE_MODE_TEXT) {
- switch (getAppIndication()) {
- case APP_INDICATOR_UNINSTALLED:
- setAppState(true);
- setAppIndication(APP_INDICATOR_INSTALLED_SPECIAL);
- mInstallIndicator = APP_INDICATOR_INSTALLED_SPECIAL;
- Message installMsg = this
- .obtainMessage(EVENT_PROACTIVE_COMMAND);
- AsyncResult.forMessage(installMsg, data, null);
- sendMessageDelayed(installMsg, 20);
- return;
- case APP_INDICATOR_INSTALLED_SPECIAL:
- case APP_INDICATOR_INSTALLED_NORMAL:
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName("com.android.stk",
- "com.android.stk.StkActivity");
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- Message launchMsg = this
- .obtainMessage(EVENT_PROACTIVE_COMMAND);
- AsyncResult.forMessage(launchMsg, data, null);
- sendMessageDelayed(launchMsg, 2000);
- return;
- }
- }
-
- CtlvDeviceIdentities devIds = retrieveDeviceIdentities(ctlvs);
- boolean cmdPending = false;
- boolean responseNeeded = false;
-
- switch (cmdType) {
- case DISPLAY_TEXT:
- cmdPending = processDisplayText(cmdDet, devIds, ctlvs);
- responseNeeded = true;
- break;
+ switch (resMsg.resCode) {
+ case HELP_INFO_REQUIRED:
+ helpRequired = true;
+ case OK:
+ case PRFRMD_WITH_PARTIAL_COMPREHENSION:
+ case PRFRMD_WITH_MISSING_INFO:
+ case PRFRMD_WITH_ADDITIONAL_EFS_READ:
+ case PRFRMD_ICON_NOT_DISPLAYED:
+ case PRFRMD_MODIFIED_BY_NAA:
+ case PRFRMD_LIMITED_SERVICE:
+ case PRFRMD_WITH_MODIFICATION:
+ case PRFRMD_NAA_NOT_ACTIVE:
+ case PRFRMD_TONE_NOT_PLAYED:
+ switch (AppInterface.CommandType.fromInt(cmdDet.typeOfCommand)) {
case SET_UP_MENU:
- cmdPending = processSetUpMenu(cmdDet, devIds, ctlvs);
- responseNeeded = true;
- break;
- case SET_UP_IDLE_MODE_TEXT:
- cmdPending = processSetUpIdleModeText(cmdDet, devIds, ctlvs);
- responseNeeded = true;
- break;
- case GET_INKEY:
- cmdPending = processGetInkey(cmdDet, devIds, ctlvs);
- break;
- case GET_INPUT:
- cmdPending = processGetInput(cmdDet, devIds, ctlvs);
- break;
- case REFRESH:
- processRefresh(cmdDet, devIds, ctlvs);
- responseNeeded = true;
- break;
+ helpRequired = resMsg.resCode == ResultCode.HELP_INFO_REQUIRED;
+ sendMenuSelection(resMsg.usersMenuSelection, helpRequired);
+ return;
case SELECT_ITEM:
- cmdPending = processSelectItem(cmdDet, devIds, ctlvs);
- break;
- case LAUNCH_BROWSER:
- cmdPending = processLaunchBrowser(cmdDet, devIds, ctlvs);
- break;
- case PLAY_TONE:
- cmdPending = processPlayTone(cmdDet, devIds, ctlvs);
+ resp = new SelectItemResponseData(resMsg.usersMenuSelection);
break;
- default:
- // This should never be reached!
- throw new AssertionError(
- "Add case statements for the newly added "
- + "command types!");
- }
- if (!cmdPending) {
- callStkApp(cmdType);
- }
- if (responseNeeded) {
- sendTerminalResponse(cmdDet, ResultCode.OK, false, 0, null);
- }
- } catch (ResultException e) {
- sendTerminalResponse(cmdDet, e.result(), e.hasAdditionalInfo(), e
- .additionalInfo(), null);
- }
- }
-
- private void handleProactiveCommandIcons(Object data) {
- CommandType cmdType = CommandType
- .fromInt(mNextCmdParams.cmdDet.typeOfCommand);
- boolean needsResponse = false;
- Bitmap[] icons = null;
- int iconIndex = 0;
-
- switch (cmdType) {
- case SET_UP_IDLE_MODE_TEXT:
- ((CommonUIParams) mNextCmdParams).mIcon = (Bitmap) (data);
- callStkApp(CommandType.SET_UP_IDLE_MODE_TEXT);
- break;
- case DISPLAY_TEXT:
- ((DisplayTextParams) mNextCmdParams).icon = (Bitmap) (data);
- callStkApp(CommandType.DISPLAY_TEXT);
- break;
- case SELECT_ITEM:
-
- SelectItemParams params = ((SelectItemParams) mNextCmdParams);
- Menu menu = params.mMenu;
- switch(params.mIconLoadState) {
- case SelectItemParams.LOAD_TITLE_ICON:
- menu.titleIcon = (Bitmap) data;
- break;
- case SelectItemParams.LOAD_ITEMS_ICONS:
- icons = (Bitmap[]) data;
- // set each item icon.
- for (Item item : menu.items) {
- item.icon = icons[iconIndex++];
- }
- break;
- case SelectItemParams.LOAD_TITLE_ITEMS_ICONS:
- icons = (Bitmap[]) data;
- // set title icon
- menu.titleIcon = icons[iconIndex++];
- // set each item icon.
- for (Item item : menu.items) {
- item.icon = icons[iconIndex++];
- }
- }
- callStkApp(CommandType.SELECT_ITEM);
- break;
- default:
- // This should never be reached!
- throw new AssertionError("Add case statements for the newly added "
- + "command types!");
- }
- }
-
- private void callStkApp(CommandType cmdType) {
- boolean needsResponse = false;
- mCmdParams = mNextCmdParams;
-
- synchronized (mCmdListenerLock) {
- switch (cmdType) {
- case SET_UP_IDLE_MODE_TEXT:
- if (mNm == null) {
- break;
- }
- CommonUIParams i = (CommonUIParams) mCmdParams;
- if (i.mText == null) {
- mNm.cancel(STK_NOTIFICATION_ID);
- } else {
- Notification notification = new Notification();
- RemoteViews contentView = new RemoteViews(
- mContext.getPackageName(),
- com.android.internal.R.layout.status_bar_latest_event_content);
-
- // Set text and icon for the status bar.
- notification.icon = com.android.internal.R.drawable.stat_notify_sim_toolkit;
- notification.tickerText = i.mText;
- notification.flags |= Notification.FLAG_NO_CLEAR;
-
- // Set text and icon for the notification body.
- if (!i.mIconSelfExplanatory) {
- contentView.setTextViewText(
- com.android.internal.R.id.text, i.mText);
- }
- if (i.mIcon != null) {
- contentView.setImageViewBitmap(
- com.android.internal.R.id.icon, i.mIcon);
- } else {
- contentView
- .setImageViewResource(
- com.android.internal.R.id.icon,
- com.android.internal.R.drawable.stat_notify_sim_toolkit);
+ case GET_INPUT:
+ case GET_INKEY:
+ Input input = mCurrntCmd.geInput();
+ if (!input.yesNo) {
+ // when help is requested there is no need to send the text
+ // string object.
+ if (!helpRequired) {
+ resp = new GetInkeyInputResponseData(resMsg.usersInput,
+ input.ucs2, input.packed);
}
- notification.contentView = contentView;
-
- mNm.notify(STK_NOTIFICATION_ID, notification);
+ } else {
+ resp = new GetInkeyInputResponseData(
+ resMsg.usersYesNoSelection);
}
- case SET_UP_MENU:
- needsResponse = true;
- break;
- case SELECT_ITEM:
- mState = State.SELECT_ITEM;
- SelectItemParams s = (SelectItemParams) mCmdParams;
- mCmdListener.onSelectItem(s.mMenu, s.mPresentationType);
- needsResponse = false;
break;
case DISPLAY_TEXT:
- mState = State.DISPLAY_TEXT;
- DisplayTextParams d = (DisplayTextParams) mCmdParams;
- mCmdListener.onDisplayText(d.text, d.textAttrs, d.isHighPriority,
- d.userClear, !d.immediateResponse, d.icon);
-
- needsResponse = d.immediateResponse;
- break;
- default:
- // This should never be reached!
- throw new AssertionError(
- "Add case statements for the newly added "
- + "command types!");
- }
- }
-
- if (needsResponse) {
- sendTerminalResponse(mCmdParams.cmdDet, ResultCode.OK, false, 0, null);
- }
- }
-
- private void sendTerminalResponse(CtlvCommandDetails cmdDet,
- ResultCode resultCode, boolean includeAdditionalInfo,
- int additionalInfo, ResponseData resp) {
-
- if (cmdDet == null) {
- return;
- }
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- // command details
- int tag = ComprehensionTlvTag.COMMAND_DETAILS.value();
- if (cmdDet.compRequired) {
- tag |= 0x80;
- }
- buf.write(tag);
- buf.write(0x03); // length
- buf.write(cmdDet.commandNumber);
- buf.write(cmdDet.typeOfCommand);
- buf.write(cmdDet.commandQualifier);
-
- // device identities
- tag = 0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value();
- buf.write(tag);
- buf.write(0x02); // length
- buf.write(DEV_ID_TERMINAL); // source device id
- buf.write(DEV_ID_UICC); // destination device id
-
- // result
- tag = 0x80 | ComprehensionTlvTag.RESULT.value();
- buf.write(tag);
- int length = includeAdditionalInfo ? 2 : 1;
- buf.write(length);
- buf.write(resultCode.code());
-
- // additional info
- if (includeAdditionalInfo) {
- buf.write(additionalInfo);
- }
-
- // Fill optional data for each corresponding command
- if (resp != null) {
- resp.format(buf);
- }
-
- byte[] rawData = buf.toByteArray();
- String hexString = SimUtils.bytesToHexString(rawData);
- if (Config.LOGD) {
- Log.d(TAG, "TERMINAL RESPONSE: " + hexString);
- }
-
- mCmdIf.sendTerminalResponse(hexString, null);
- }
-
- /**
- * Search for a COMPREHENSION-TLV object with the given tag from a list
- *
- * @param tag A tag to search for
- * @param ctlvs List of ComprehensionTlv objects used to search in
- *
- * @return A ComprehensionTlv object that has the tag value of {@code tag}.
- * If no object is found with the tag, null is returned.
- */
- private ComprehensionTlv searchForTag(ComprehensionTlvTag tag,
- List<ComprehensionTlv> ctlvs) {
- Iterator<ComprehensionTlv> iter = ctlvs.iterator();
- return searchForNextTag(tag, iter);
- }
-
- /**
- * Search for the next COMPREHENSION-TLV object with the given tag from a
- * list iterated by {@code iter}. {@code iter} points to the object next to
- * the found object when this method returns. Used for searching the same
- * list for similar tags, usually item id.
- *
- * @param tag A tag to search for
- * @param iter Iterator for ComprehensionTlv objects used for search
- *
- * @return A ComprehensionTlv object that has the tag value of {@code tag}.
- * If no object is found with the tag, null is returned.
- */
- private ComprehensionTlv searchForNextTag(ComprehensionTlvTag tag,
- Iterator<ComprehensionTlv> iter) {
- int tagValue = tag.value();
- while (iter.hasNext()) {
- ComprehensionTlv ctlv = iter.next();
- if (ctlv.getTag() == tagValue) {
- return ctlv;
- }
- }
- return null;
- }
-
- /**
- * Search for a Command Details object from a list.
- *
- * @param ctlvs List of ComprehensionTlv objects used for search
- * @return An CtlvCommandDetails object found from the objects. If no
- * Command Details object is found, ResultException is thrown.
- * @throws ResultException
- */
- private CtlvCommandDetails retrieveCommandDetails(
- List<ComprehensionTlv> ctlvs) throws ResultException {
-
- ComprehensionTlv ctlv = searchForTag(
- ComprehensionTlvTag.COMMAND_DETAILS, ctlvs);
- if (ctlv != null) {
- CtlvCommandDetails cmdDet = new CtlvCommandDetails();
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- try {
- cmdDet.compRequired = ctlv.isComprehensionRequired();
- cmdDet.commandNumber = rawValue[valueIndex] & 0xff;
- cmdDet.typeOfCommand = rawValue[valueIndex + 1] & 0xff;
- cmdDet.commandQualifier = rawValue[valueIndex + 2] & 0xff;
- return cmdDet;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- } else {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
- }
-
- /**
- * Search for a Device Identities object from a list.
- *
- * @param ctlvs List of ComprehensionTlv objects used for search
- * @return An CtlvDeviceIdentities object found from the objects. If no
- * Command Details object is found, ResultException is thrown.
- * @throws ResultException
- */
- private CtlvDeviceIdentities retrieveDeviceIdentities(
- List<ComprehensionTlv> ctlvs) throws ResultException {
-
- ComprehensionTlv ctlv = searchForTag(
- ComprehensionTlvTag.DEVICE_IDENTITIES, ctlvs);
- if (ctlv != null) {
- CtlvDeviceIdentities devIds = new CtlvDeviceIdentities();
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- try {
- devIds.sourceId = rawValue[valueIndex] & 0xff;
- devIds.destinationId = rawValue[valueIndex + 1] & 0xff;
- return devIds;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
- } else {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
- }
-
- /**
- * Processes SETUP_CALL proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- */
- private void processSetupCall(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs) {
- if (Config.LOGD) {
- Log.d(TAG, "processSetupCall begins");
- }
-
- // User confirmation phase message.
- String confirmMsg = null;
- // Call set up phase message.
- String callMsg = null;
- List<TextAttribute> textAttrs = null;
- Iterator<ComprehensionTlv> iter = ctlvs.iterator();
- ComprehensionTlv ctlv = null;
-
- try {
- // get confirmation message string.
- ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
- if (ctlv != null) {
- confirmMsg = retrieveAlphaId(ctlv);
- } else {
- // No message to show.
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
- // get call set up message string.
- ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
- if (ctlv != null) {
- callMsg = retrieveAlphaId(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- textAttrs = retrieveTextAttribute(ctlv);
- }
- } catch (ResultException e) {
- // Unable to process command. Send terminal response when service is
- // in call state.
- while (mState != State.CALL_SETUP) {
- Thread.yield();
- }
- sendTerminalResponse(cmdDet, ResultCode.REQUIRED_VALUES_MISSING,
- false, 0, null);
- return;
- }
-
- synchronized (mCmdListenerLock) {
- if (mCmdListener != null) {
- mCmdListener.onCallSetup(confirmMsg, textAttrs, callMsg);
- }
- }
- }
-
- /**
- * Processes DISPLAY_TEXT proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processDisplayText(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processDisplayText begins");
- }
-
- DisplayTextParams params = new DisplayTextParams(cmdDet);
- IconId iconId = null;
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
- ctlvs);
- if (ctlv != null) {
- params.text = retrieveTextString(ctlv);
- }
- // If the tlv object doesn't exist or the it is a null object reply
- // with command not understood.
- if (params.text == null) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- params.textAttrs = retrieveTextAttribute(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.IMMEDIATE_RESPONSE, ctlvs);
- if (ctlv != null) {
- params.immediateResponse = true;
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
- if (ctlv != null) {
- iconId = retrieveIconId(ctlv);
- }
-
- // Parse command qualifier parameters.
- params.isHighPriority = (cmdDet.commandQualifier & 0x01) != 0;
- params.userClear = (cmdDet.commandQualifier & 0x80) != 0;
-
- mNextCmdParams = params;
-
- // If there's no icon to load call stk application.
- if (iconId != null) {
- mIconLoader.loadIcon(iconId.recordNumber, this
- .obtainMessage(EVENT_LOAD_ICON_DONE));
- return true;
- }
- return false;
- }
-
- /**
- * Processes SET_UP_MENU proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs Iterator for ComprehensionTlv objects following Command
- * Details object and Device Identities object within the proactive
- * command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processSetUpMenu(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processSetUpMenu begins");
- }
-
- Menu menu = new Menu();
- boolean first = true;
- boolean removeExistingMenu = false;
- Iterator<ComprehensionTlv> iter = ctlvs.iterator();
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
- ctlvs);
- if (ctlv != null) {
- menu.title = retrieveAlphaId(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- menu.titleAttrs = retrieveTextAttribute(ctlv);
- }
-
- while (true) {
- ctlv = searchForNextTag(ComprehensionTlvTag.ITEM, iter);
- if (ctlv != null) {
- Item item = retrieveItem(ctlv);
- // If the first item is a "null" object, it means that
- // the existing menu should be removed.
- if (first && item == null) {
- removeExistingMenu = true;
- break;
- }
- menu.items.add(retrieveItem(ctlv));
- first = false;
- } else {
- break;
- }
- }
-
- // Extract command details.
- menu.softKeyPreferred = (cmdDet.commandQualifier & 0x01) != 0;
- menu.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
-
- // We must have at least one menu item.
- if (menu.items.size() == 0 && !removeExistingMenu) {
- if (Config.LOGD) {
- Log.d(TAG, "processSetUpMenu: Need at least one menu item");
- }
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
- mCmdParams = new CommandParams(cmdDet);
- if (removeExistingMenu) {
- mState = State.IDLE;
- mMainMenu = null;
- setAppState(false);
- } else {
- Menu currentMenu = mMainMenu;
- mState = State.MAIN_MENU;
- mMainMenu = menu;
- if (!isStkSupported()) {
- setAppState(true);
- setAppIndication(APP_INDICATOR_INSTALLED_NORMAL);
- mInstallIndicator = APP_INDICATOR_INSTALLED_NORMAL;
- }
- }
- return true;
- }
-
- private void setAppState(boolean installed) {
- if (installed) {
- StkAppInstaller.installApp(mContext);
- } else {
- setAppIndication(APP_INDICATOR_UNINSTALLED);
- mInstallIndicator = APP_INDICATOR_UNINSTALLED;
- StkAppInstaller.unInstallApp(mContext);
- }
- }
-
- public Menu getCurrentMenu() {
- Menu menu = null;
- switch(mState) {
- case MAIN_MENU:
- menu = mMainMenu;
- break;
- case SELECT_ITEM:
- menu = ((SelectItemParams) mCmdParams).mMenu;
- break;
- }
- return menu;
- }
-
- /**
- * Processes SET_UP_IDLE_MODE_TEXT proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processSetUpIdleModeText(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processSetUpIdleModeText begins");
- }
-
- if (mNm == null) {
- throw new ResultException(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
- }
-
- String text = null;
- IconId iconId = null;
- List<TextAttribute> textAttrs = null;
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
- ctlvs);
- if (ctlv != null) {
- text = retrieveTextString(ctlv);
- } else {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
- if (ctlv != null) {
- iconId = retrieveIconId(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- textAttrs = retrieveTextAttribute(ctlv);
- }
-
- CommonUIParams params = new CommonUIParams(cmdDet, text, null);
- mNextCmdParams = params;
- if (iconId != null) {
- params.mIconSelfExplanatory = iconId.selfExplanatory;
- mIconLoader.loadIcon(iconId.recordNumber, this
- .obtainMessage(EVENT_LOAD_ICON_DONE));
- return true;
- }
- return false;
- }
-
- /**
- * Processes GET_INKEY proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processGetInkey(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processGetInkey begins");
- }
-
- String text = null;
- List<TextAttribute> textAttrs = null;
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
- ctlvs);
- if (ctlv != null) {
- text = retrieveTextString(ctlv);
- } else {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- textAttrs = retrieveTextAttribute(ctlv);
- }
-
- boolean digitOnly = (cmdDet.commandQualifier & 0x01) == 0;
- boolean ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
- boolean yesNo = (cmdDet.commandQualifier & 0x04) != 0;
- boolean immediateResponse = (cmdDet.commandQualifier & 0x08) != 0;
- boolean helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
-
- synchronized (mCmdListenerLock) {
- if (mCmdListener != null) {
- mCmdParams = new GetInkeyParams(cmdDet, yesNo, ucs2);
- mState = State.GET_INKEY;
-
- mCmdListener.onGetInkey(text, textAttrs, yesNo, digitOnly,
- ucs2, immediateResponse, helpAvailable);
- return true;
- } else {
- // '0' means "No specific cause can be given"
- throw new ResultException(
- ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS, 0);
- }
- }
- }
-
- /**
- * Processes GET_INPUT proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processGetInput(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processGetInput begins");
- }
-
- String text = null;
- String defaultText = null;
- int minLen, maxLen;
- List<TextAttribute> textAttrs = null;
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
- ctlvs);
- if (ctlv != null) {
- text = retrieveTextString(ctlv);
- } else {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.RESPONSE_LENGTH, ctlvs);
- if (ctlv != null) {
- try {
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- minLen = rawValue[valueIndex] & 0xff;
- maxLen = rawValue[valueIndex + 1] & 0xff;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- } else {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- textAttrs = retrieveTextAttribute(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.DEFAULT_TEXT, ctlvs);
- if (ctlv != null) {
- defaultText = retrieveTextString(ctlv);
- }
-
- boolean digitOnly = (cmdDet.commandQualifier & 0x01) == 0;
- boolean ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
- boolean echo = (cmdDet.commandQualifier & 0x04) == 0;
- boolean packed = (cmdDet.commandQualifier & 0x08) != 0;
- boolean helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
-
- synchronized (mCmdListenerLock) {
- if (mCmdListener != null) {
- mCmdParams = new GetInputParams(cmdDet, ucs2, packed);
- mState = State.GET_INPUT;
-
- boolean noMaxLimit = maxLen == 0xff;
- mCmdListener.onGetInput(text, defaultText, minLen, maxLen,
- noMaxLimit, textAttrs, digitOnly, ucs2, echo,
- helpAvailable);
- return true;
- } else {
- // '0' means "No specific cause can be given"
- throw new ResultException(
- ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS, 0);
- }
- }
- }
-
- /**
- * Processes REFRESH proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @throws ResultException
- */
- private void processRefresh(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processRefresh begins");
- }
-
- // REFRESH proactive command is rerouted by the baseband and handled by
- // the telephony layer. IDLE TEXT should be removed for a REFRESH command
- // with "initialization" or "reset"
-
- if (mNm == null) {
- throw new ResultException(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
- }
-
- boolean removeIdleText = false;
-
- switch (cmdDet.commandQualifier) {
- case REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE:
- case REFRESH_NAA_INIT_AND_FILE_CHANGE:
- case REFRESH_NAA_INIT:
- case REFRESH_UICC_RESET:
- removeIdleText = true;
- }
- if (removeIdleText) {
- mNm.cancel(STK_NOTIFICATION_ID);
- }
- }
-
- /**
- * Processes SELECT_ITEM proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processSelectItem(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processSelectItem begins");
- }
-
- Menu menu = new Menu();
- IconId titleIconId = null;
- ItemsIconId itemsIconId = null;
- int iconLoadState = SelectItemParams.LOAD_NO_ICON;
- PresentationType presentType = PresentationType.NOT_SPECIFIED;
- Iterator<ComprehensionTlv> iter = ctlvs.iterator();
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
- ctlvs);
- if (ctlv != null) {
- menu.title = retrieveAlphaId(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- menu.titleAttrs = retrieveTextAttribute(ctlv);
- }
-
- while (true) {
- ctlv = searchForNextTag(ComprehensionTlvTag.ITEM, iter);
- if (ctlv != null) {
- menu.items.add(retrieveItem(ctlv));
- } else {
+ case LAUNCH_BROWSER:
break;
- }
- }
-
- // We must have at least one menu item.
- if (menu.items.size() == 0) {
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.ITEM_ID, ctlvs);
- if (ctlv != null) {
- // STK items are listed 1...n while list start at 0, need to
- // subtract one.
- menu.defaultItem = retrieveItemId(ctlv) - 1;
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
- if (ctlv != null) {
- iconLoadState = SelectItemParams.LOAD_TITLE_ICON;
- titleIconId = retrieveIconId(ctlv);
- menu.titleIconSelfExplanatory = titleIconId.selfExplanatory;
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.ITEM_ICON_ID_LIST, ctlvs);
- if (ctlv != null) {
- if (iconLoadState == SelectItemParams.LOAD_TITLE_ICON) {
- iconLoadState = SelectItemParams.LOAD_TITLE_ITEMS_ICONS;
- } else {
- iconLoadState = SelectItemParams.LOAD_ITEMS_ICONS;
- }
- itemsIconId = retrieveItemsIconId(ctlv);
- menu.itemsIconSelfExplanatory = itemsIconId.selfExplanatory;
- }
-
- boolean presentTypeSpecified = (cmdDet.commandQualifier & 0x01) != 0;
- if (presentTypeSpecified) {
- if ((cmdDet.commandQualifier & 0x02) == 0) {
- presentType = PresentationType.DATA_VALUES;
- } else {
- presentType = PresentationType.NAVIGATION_OPTIONS;
- }
- }
- menu.softKeyPreferred = (cmdDet.commandQualifier & 0x04) != 0;
- menu.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
-
- mNextCmdParams = new SelectItemParams(cmdDet, menu, presentType,
- iconLoadState);
-
- // Load icons data if needed.
- switch(iconLoadState) {
- case SelectItemParams.LOAD_NO_ICON:
- return false;
- case SelectItemParams.LOAD_TITLE_ICON:
- mIconLoader.loadIcon(titleIconId.recordNumber, this
- .obtainMessage(EVENT_LOAD_ICON_DONE));
- break;
- case SelectItemParams.LOAD_ITEMS_ICONS:
- mIconLoader.loadIcons(itemsIconId.recordNumbers, this
- .obtainMessage(EVENT_LOAD_ICON_DONE));
- break;
- case SelectItemParams.LOAD_TITLE_ITEMS_ICONS:
- // Create a new array for all the icons (title and items).
- int[] recordNumbers = new int[itemsIconId.recordNumbers.length + 1];
- recordNumbers[0] = titleIconId.recordNumber;
- System.arraycopy(itemsIconId.recordNumbers, 0, recordNumbers, 1,
- itemsIconId.recordNumbers.length);
- mIconLoader.loadIcons(recordNumbers, this
- .obtainMessage(EVENT_LOAD_ICON_DONE));
- break;
- }
- return true;
- }
-
- /**
- * Processes EVENT_NOTIFY message from baseband.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- */
- synchronized private void processEventNotify(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs) {
-
- if (Config.LOGD) {
- Log.d(TAG, "processEventNotify begins");
- }
-
- String text = null;
- List<TextAttribute> textAttrs = null;
-
- try {
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
- ctlvs);
- if (ctlv != null) {
- text = retrieveAlphaId(ctlv);
- } else {
- // No message to show.
- throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- textAttrs = retrieveTextAttribute(ctlv);
- }
- } catch (ResultException e) {
- // Unable to process command.
- return;
- }
-
- Toast toast = Toast.makeText(mContext.getApplicationContext(), text,
- Toast.LENGTH_LONG);
- toast.setGravity(Gravity.BOTTOM, 0, 0);
- toast.show();
- }
-
- /**
- * Processes SET_UP_EVENT_LIST proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- */
- private boolean processSetUpEventList(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs) {
-
- if (Config.LOGD) {
- Log.d(TAG, "processSetUpEventList begins");
- }
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.EVENT_LIST,
- ctlvs);
- if (ctlv != null) {
- try {
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int valueLen = ctlv.getLength();
-
- } catch (IndexOutOfBoundsException e) {}
- }
- return true;
- }
-
- /**
- * Processes LAUNCH_BROWSER proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.
- * @throws ResultException
- */
- private boolean processLaunchBrowser(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processLaunchBrowser begins");
- }
-
- String url = null;
- String confirmMsg = null;
- List<TextAttribute> confirmMsgAttrs = null;
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.URL, ctlvs);
- if (ctlv != null) {
- try {
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int valueLen = ctlv.getLength();
- if (valueLen > 0) {
- url = GsmAlphabet.gsm8BitUnpackedToString(rawValue,
- valueIndex, valueLen);
- } else {
- url = null;
+ case SET_UP_CALL:
+ mCmdIf.handleCallSetupRequestFromSim(resMsg.usersConfirm, null);
+ if (!resMsg.usersConfirm) {
+ resMsg.resCode = ResultCode.USER_NOT_ACCEPT;
}
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
- if (ctlv != null) {
- confirmMsg = retrieveAlphaId(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- confirmMsgAttrs = retrieveTextAttribute(ctlv);
- }
-
- LaunchBrowserMode mode;
- switch (cmdDet.commandQualifier) {
- case 0x00:
- default:
- mode = LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED;
- break;
- case 0x02:
- mode = LaunchBrowserMode.USE_EXISTING_BROWSER;
break;
- case 0x03:
- mode = LaunchBrowserMode.LAUNCH_NEW_BROWSER;
+ case NO_RESPONSE_FROM_USER:
+ case UICC_SESSION_TERM_BY_USER:
+ case BACKWARD_MOVE_BY_USER:
+ resp = null;
break;
- }
-
- synchronized (mCmdListenerLock) {
- if (mCmdListener != null) {
- mCmdParams = new CommandParams(cmdDet);
- mState = State.LAUNCH_BROWSER;
-
- mCmdListener.onLaunchBrowser(url, confirmMsg, confirmMsgAttrs,
- mode);
- return true;
- } else {
- // '0' means "No specific cause can be given"
- throw new ResultException(
- ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS, 0);
- }
- }
- }
-
- /**
- * Processes PLAY_TONE proactive command from the SIM card.
- *
- * @param cmdDet Command Details object retrieved from the proactive command
- * object
- * @param devIds Device Identities object retrieved from the proactive
- * command object
- * @param ctlvs List of ComprehensionTlv objects following Command Details
- * object and Device Identities object within the proactive command
- * @return true if the command is processing is pending and additional
- * asynchronous processing is required.t
- * @throws ResultException
- */
- private boolean processPlayTone(CtlvCommandDetails cmdDet,
- CtlvDeviceIdentities devIds, List<ComprehensionTlv> ctlvs)
- throws ResultException {
-
- if (Config.LOGD) {
- Log.d(TAG, "processPlayTone begins");
- }
-
- Tone tone = null;
- String text = null;
- List<TextAttribute> textAttrs = null;
- Duration duration = null;
-
- ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TONE, ctlvs);
- if (ctlv != null) {
- // Nothing to do for null objects.
- if (ctlv.getLength() > 0) {
- try {
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int toneVal = rawValue[valueIndex];
- tone = Tone.fromInt(toneVal);
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(
- ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- }
- }
- ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
- if (ctlv != null) {
- text = retrieveAlphaId(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.TEXT_ATTRIBUTE, ctlvs);
- if (ctlv != null) {
- textAttrs = retrieveTextAttribute(ctlv);
- }
-
- ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs);
- if (ctlv != null) {
- duration = retrieveDuration(ctlv);
- }
-
- synchronized (mCmdListenerLock) {
- if (mCmdListener != null) {
- mState = State.PLAY_TONE;
- mCmdParams = new CommandParams(cmdDet);
- mCmdListener.onPlayTone(tone, text, textAttrs, duration);
- return true;
- } else {
- // '0' means "No specific cause can be given"
- throw new ResultException(
- ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS, 0);
- }
- }
- }
-
- /**
- * Retrieves text from the Text COMPREHENSION-TLV object, and decodes it
- * into a {@link java.lang.String}.
- *
- * @param ctlv A Text COMPREHENSION-TLV object
- * @return A {@link java.lang.String} object decoded from the Text object
- * @throws ResultException
- */
- private String retrieveTextString(ComprehensionTlv ctlv)
- throws ResultException {
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- byte codingScheme = 0x00;
- String text = null;
- int textLen = ctlv.getLength();
-
- // In case the text length is 0, return a null string.
- if (textLen == 0) {
- return text;
- } else {
- // one byte is coding scheme
- textLen -= 1;
- }
-
- try {
- codingScheme = (byte) (rawValue[valueIndex] & 0x0c);
-
- if (codingScheme == 0x00) { // GSM 7-bit packed
- text = GsmAlphabet.gsm7BitPackedToString(rawValue,
- valueIndex + 1, (textLen * 8) / 7);
- } else if (codingScheme == 0x04) { // GSM 8-bit unpacked
- text = GsmAlphabet.gsm8BitUnpackedToString(rawValue,
- valueIndex + 1, textLen);
- } else if (codingScheme == 0x08) { // UCS2
- text = new String(rawValue, valueIndex + 1, textLen, "UTF-16");
- } else {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
-
- return text;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- } catch (UnsupportedEncodingException e) {
- // This should never happen.
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- }
-
- /**
- * Retrieves Duration information from the Duration COMPREHENSION-TLV
- * object.
- *
- * @param ctlv A Text Attribute COMPREHENSION-TLV object
- * @return A Duration object
- * @throws ResultException
- */
- private Duration retrieveDuration(ComprehensionTlv ctlv)
- throws ResultException {
- int timeInterval = 0;
- TimeUnit timeUnit = TimeUnit.SECOND;
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
-
- try {
- timeUnit = TimeUnit.values()[(rawValue[valueIndex] & 0xff)];
- timeInterval = rawValue[valueIndex + 1] & 0xff;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- return new Duration(timeInterval, timeUnit);
- }
-
- /**
- * Retrieves Item information from the COMPREHENSION-TLV object.
- *
- * @param ctlv A Text Attribute COMPREHENSION-TLV object
- * @return An Item
- * @throws ResultException
- */
- private Item retrieveItem(ComprehensionTlv ctlv) throws ResultException {
- Item item = null;
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int length = ctlv.getLength();
-
- if (length != 0) {
- int textLen = length - 1;
-
- try {
- int id = rawValue[valueIndex] & 0xff;
- String text = SimUtils.adnStringFieldToString(rawValue,
- valueIndex + 1, textLen);
- item = new Item(id, text);
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- }
-
- return item;
- }
-
- /**
- * Retrieves Item id information from the COMPREHENSION-TLV object.
- *
- * @param ctlv A Text Attribute COMPREHENSION-TLV object
- * @return An Item id
- * @throws ResultException
- */
- private int retrieveItemId(ComprehensionTlv ctlv) throws ResultException {
- int id = 0;
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
-
- try {
- id = rawValue[valueIndex] & 0xff;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
-
- return id;
- }
-
- /**
- * Retrieves icon id from an Icon Identifier COMPREHENSION-TLV object
- *
- * @param ctlv An Icon Identifier COMPREHENSION-TLV object
- * @return IconId instance
- * @throws ResultException
- */
- private IconId retrieveIconId(ComprehensionTlv ctlv) throws ResultException {
- IconId id = new IconId();
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- try {
- id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00;
- id.recordNumber = rawValue[valueIndex] & 0xff;
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
-
- return id;
- }
-
- /**
- * Retrieves item icons id from an Icon Identifier List COMPREHENSION-TLV object
- *
- * @param ctlv An Item Icon List Identifier COMPREHENSION-TLV object
- * @return ItemsIconId instance
- * @throws ResultException
- */
- private ItemsIconId retrieveItemsIconId(ComprehensionTlv ctlv)
- throws ResultException{
- Log.d(TAG, "retrieveIconIdList:");
- ItemsIconId id = new ItemsIconId();
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int numOfItems = ctlv.getLength() - 1;
- id.recordNumbers = new int[numOfItems];
-
- try {
- // get icon self-explanatory
- id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00;
-
- for (int index = 0; index < numOfItems;) {
- id.recordNumbers[index++] = rawValue[valueIndex++];
- }
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- return id;
- }
-
- /**
- * Retrieves text attribute information from the Text Attribute
- * COMPREHENSION-TLV object.
- *
- * @param ctlv A Text Attribute COMPREHENSION-TLV object
- * @return A list of TextAttribute objects
- * @throws ResultException
- */
- private List<TextAttribute> retrieveTextAttribute(ComprehensionTlv ctlv)
- throws ResultException {
- ArrayList<TextAttribute> lst = new ArrayList<TextAttribute>();
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int length = ctlv.getLength();
-
- if (length != 0) {
- // Each attribute is consisted of four bytes
- int itemCount = length / 4;
-
- try {
- for (int i = 0; i < itemCount; i++, valueIndex += 4) {
- int start = rawValue[valueIndex] & 0xff;
- int textLength = rawValue[valueIndex + 1] & 0xff;
- int format = rawValue[valueIndex + 2] & 0xff;
- int colorValue = rawValue[valueIndex + 3] & 0xff;
-
- int alignValue = format & 0x03;
- TextAlignment align = TextAlignment.fromInt(alignValue);
-
- int sizeValue = (format >> 2) & 0x03;
- FontSize size = FontSize.fromInt(sizeValue);
- if (size == null) {
- // Font size value is not defined. Use default.
- size = FontSize.NORMAL;
- }
-
- boolean bold = (format & 0x10) != 0;
- boolean italic = (format & 0x20) != 0;
- boolean underlined = (format & 0x40) != 0;
- boolean strikeThrough = (format & 0x80) != 0;
-
- TextColor color = TextColor.fromInt(colorValue);
-
- TextAttribute attr = new TextAttribute(start, textLength,
- align, size, bold, italic, underlined,
- strikeThrough, color);
- lst.add(attr);
- }
-
- return lst;
-
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- }
- return null;
- }
-
- /**
- * Retrieves alpha identifier from an Alpha Identifier COMPREHENSION-TLV
- * object.
- *
- * @param ctlv An Alpha Identifier COMPREHENSION-TLV object
- * @return String corresponding to the alpha identifier
- * @throws ResultException
- */
- private String retrieveAlphaId(ComprehensionTlv ctlv)
- throws ResultException {
-
- byte[] rawValue = ctlv.getRawValue();
- int valueIndex = ctlv.getValueIndex();
- int length = ctlv.getLength();
- if (length != 0) {
- try {
- return SimUtils.adnStringFieldToString(rawValue, valueIndex,
- length);
- } catch (IndexOutOfBoundsException e) {
- throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
- }
- }
- return null;
- }
-
- /**
- * Handles RIL_UNSOL_STK_EVENT_NOTIFY unsolicited command from RIL.
- *
- * @param data String containing SAT/USAT commands or responses sent by ME
- * to SIM or commands handled by ME, in hexadecimal format starting
- * with first byte of response data or command tag
- */
- private void handleEventNotify(String data) {
- if (Config.LOGD) {
- Log.d(TAG, "handleEventNotify begins");
- }
- byte[] rawData = null;
- BerTlv berTlv = null;
- CtlvCommandDetails cmdDet = null;
- CtlvDeviceIdentities devIds = null;
- CommandType cmdType = null;
-
- // Nothing to do for empty strings.
- if (data.length() == 0) {
- return;
- }
- rawData = SimUtils.hexStringToBytes(data);
- try {
- berTlv = BerTlv.decode(rawData);
- } catch (ResultException e) {
- // Can't parse command buffer.
- return;
- }
-
- // Extract command details & Device identities tlv objects list.
- List<ComprehensionTlv> ctlvs = berTlv.getComprehensionTlvs();
- try {
- cmdDet = retrieveCommandDetails(ctlvs);
- devIds = retrieveDeviceIdentities(ctlvs);
- } catch (ResultException e) {
- if (Config.LOGD) {
- Log.d(TAG, "invlaid command details/device identities");
- }
- return;
- }
-
- // Check to see if we support this command.
- cmdType = CommandType.fromInt(cmdDet.typeOfCommand);
- if (cmdType == null) {
+ default:
return;
}
-
- // There are two scenarios for EVENT_NOTIFY messages:
- // 1. A proactive command which is partially handled by the baseband and
- // requires UI processing from the application. This messages will be
- // tagged with PROACTIVE COMMAND tag.
- // 2. A notification for an action completed by the baseband. This
- // messages will be tagged with UNKNOWN tag and the command type inside
- // the Command details object should indicate which action was completed.
- if (berTlv.getTag() == BerTlv.BER_PROACTIVE_COMMAND_TAG) {
- switch (cmdType) {
- case SEND_SS:
- case SEND_USSD:
- case SEND_SMS:
- case SEND_DTMF:
- processEventNotify(cmdDet, devIds, ctlvs);
- break;
- case SET_UP_EVENT_LIST:
- processSetUpEventList(cmdDet, devIds, ctlvs);
- break;
- case SET_UP_CALL:
- processSetupCall(cmdDet, devIds, ctlvs);
- break;
- default:
- // nada
- break;
- }
- }
+ sendTerminalResponse(cmdDet, resMsg.resCode, false, 0, resp);
+ mCurrntCmd = null;
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkAppInstaller.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkAppInstaller.java
deleted file mode 100644
index 07e3e56..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/stk/StkAppInstaller.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.gsm.stk;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.util.Log;
-
-/**
- * Application installer for SIM Toolkit.
- *
- */
-public class StkAppInstaller {
- // Application state actions: install, uninstall used by StkAppStateReceiver.
- static final String STK_APP_INSTALL_ACTION = "com.android.stk.action.INSTALL";
- static final String STK_APP_UNINSTALL_ACTION = "com.android.stk.action.UNINSTALL";
-
- public static void installApp(Context context) {
- setAppState(context, PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
- }
-
- public static void unInstallApp(Context context) {
- setAppState(context, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
- }
-
- private static void setAppState(Context context, int state) {
- if (context == null) {
- return;
- }
- PackageManager pm = context.getPackageManager();
- if (pm == null) {
- return;
- }
- // check that STK app package is known to the PackageManager
- ComponentName cName = new ComponentName("com.android.stk",
- "com.android.stk.StkActivity");
-
- try {
- pm.setComponentEnabledSetting(cName, state,
- PackageManager.DONT_KILL_APP);
- } catch (Exception e) {
- Log.w("StkAppInstaller", "Could not change STK app state");
- }
- }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkAppStateReceiver.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkAppStateReceiver.java
deleted file mode 100644
index 778ca2e..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/stk/StkAppStateReceiver.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.gsm.stk;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import com.android.internal.telephony.gsm.stk.Service;
-import android.util.Log;
-
-/**
- * This class implements a Broadcast receiver. It waits for an intent sent by
- * the STK service and install/uninstall the STK application. If no intent is
- * received when the device finished booting, the application is then unistalled.
- */
-public class StkAppStateReceiver extends BroadcastReceiver {
-
- private static final String TAG = "StkAppStateReceiver";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "onReceive");
-
- String action = intent.getAction();
- Service stkService = Service.getInstance();
- if (stkService == null) {
- return;
- }
- if (action.equals(StkAppInstaller.STK_APP_INSTALL_ACTION)) {
- stkService.setAppIndication(Service.APP_INDICATOR_INSTALLED_NORMAL);
- StkAppInstaller.installApp(context);
- } else if (action.equals(StkAppInstaller.STK_APP_UNINSTALL_ACTION)) {
- stkService.setAppIndication(Service.APP_INDICATOR_UNINSTALLED);
- StkAppInstaller.unInstallApp(context);
- }
- }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkCmdMessage.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkCmdMessage.java
new file mode 100644
index 0000000..62a778e
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkCmdMessage.java
@@ -0,0 +1,175 @@
+/*
+ * 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.gsm.stk;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Class used to pass STK messages from telephony to application. Application
+ * should call getXXX() to get commands's specific values.
+ *
+ */
+public class StkCmdMessage implements Parcelable {
+ // members
+ CommandDetails mCmdDet;
+ private TextMessage mTextMsg;
+ private Menu mMenu;
+ private Input mInput;
+ private BrowserSettings mBrowserSettings = null;
+ private ToneSettings mToneSettings = null;
+ private CallSettings mCallSettings = null;
+
+ /*
+ * Container for Launch Browser command settings.
+ */
+ public class BrowserSettings {
+ public String url;
+ public LaunchBrowserMode mode;
+ }
+
+ /*
+ * Container for Call Setup command settings.
+ */
+ public class CallSettings {
+ public TextMessage confirmMsg;
+ public TextMessage callMsg;
+ }
+
+ StkCmdMessage(CommandParams cmdParams) {
+ mCmdDet = cmdParams.cmdDet;
+ switch(getCmdType()) {
+ case SET_UP_MENU:
+ case SELECT_ITEM:
+ mMenu = ((SelectItemParams) cmdParams).menu;
+ break;
+ case DISPLAY_TEXT:
+ case SET_UP_IDLE_MODE_TEXT:
+ case SEND_DTMF:
+ case SEND_SMS:
+ case SEND_SS:
+ case SEND_USSD:
+ mTextMsg = ((DisplayTextParams) cmdParams).textMsg;
+ break;
+ case GET_INPUT:
+ case GET_INKEY:
+ mInput = ((GetInputParams) cmdParams).input;
+ break;
+ case LAUNCH_BROWSER:
+ mTextMsg = ((LaunchBrowserParams) cmdParams).confirmMsg;
+ mBrowserSettings = new BrowserSettings();
+ mBrowserSettings.url = ((LaunchBrowserParams) cmdParams).url;
+ mBrowserSettings.mode = ((LaunchBrowserParams) cmdParams).mode;
+ break;
+ case PLAY_TONE:
+ PlayToneParams params = (PlayToneParams) cmdParams;
+ mToneSettings = params.settings;
+ mTextMsg = params.textMsg;
+ break;
+ case SET_UP_CALL:
+ mCallSettings = new CallSettings();
+ mCallSettings.confirmMsg = ((CallSetupParams) cmdParams).confirmMsg;
+ mCallSettings.callMsg = ((CallSetupParams) cmdParams).callMsg;
+ break;
+ }
+ }
+
+ public StkCmdMessage(Parcel in) {
+ mCmdDet = in.readParcelable(null);
+ mTextMsg = in.readParcelable(null);
+ mMenu = in.readParcelable(null);
+ mInput = in.readParcelable(null);
+ switch (getCmdType()) {
+ case LAUNCH_BROWSER:
+ mBrowserSettings = new BrowserSettings();
+ mBrowserSettings.url = in.readString();
+ mBrowserSettings.mode = LaunchBrowserMode.values()[in.readInt()];
+ break;
+ case PLAY_TONE:
+ mToneSettings = in.readParcelable(null);
+ break;
+ case SET_UP_CALL:
+ mCallSettings = new CallSettings();
+ mCallSettings.confirmMsg = in.readParcelable(null);
+ mCallSettings.callMsg = in.readParcelable(null);
+ break;
+ }
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mCmdDet, 0);
+ dest.writeParcelable(mTextMsg, 0);
+ dest.writeParcelable(mMenu, 0);
+ dest.writeParcelable(mInput, 0);
+ switch(getCmdType()) {
+ case LAUNCH_BROWSER:
+ dest.writeString(mBrowserSettings.url);
+ dest.writeInt(mBrowserSettings.mode.ordinal());
+ break;
+ case PLAY_TONE:
+ dest.writeParcelable(mToneSettings, 0);
+ break;
+ case SET_UP_CALL:
+ dest.writeParcelable(mCallSettings.confirmMsg, 0);
+ dest.writeParcelable(mCallSettings.callMsg, 0);
+ break;
+ }
+ }
+
+ public static final Parcelable.Creator<StkCmdMessage> CREATOR = new Parcelable.Creator<StkCmdMessage>() {
+ public StkCmdMessage createFromParcel(Parcel in) {
+ return new StkCmdMessage(in);
+ }
+
+ public StkCmdMessage[] newArray(int size) {
+ return new StkCmdMessage[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+
+ /* external API to be used by application */
+ public AppInterface.CommandType getCmdType() {
+ return AppInterface.CommandType.fromInt(mCmdDet.typeOfCommand);
+ }
+
+ public Menu getMenu() {
+ return mMenu;
+ }
+
+ public Input geInput() {
+ return mInput;
+ }
+
+ public TextMessage geTextMessage() {
+ return mTextMsg;
+ }
+
+ public BrowserSettings getBrowserSettings() {
+ return mBrowserSettings;
+ }
+
+ public ToneSettings getToneSettings() {
+ return mToneSettings;
+ }
+
+ public CallSettings getCallSettings() {
+ return mCallSettings;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CtlvCommandDetails.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkLog.java
index 6389537..f6e5685 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CtlvCommandDetails.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -16,14 +16,26 @@
package com.android.internal.telephony.gsm.stk;
+import android.util.Log;
-/**
- * Class for Command Detailes object of proactive commands from SIM.
- * {@hide}
- */
-public class CtlvCommandDetails {
- public boolean compRequired;
- public int commandNumber;
- public int typeOfCommand;
- public int commandQualifier;
+public abstract class StkLog {
+ static final boolean DEBUG = true;
+
+ public static void d(Object caller, String msg) {
+ if (!DEBUG) {
+ return;
+ }
+
+ String className = caller.getClass().getName();
+ Log.d("STK", className.substring(className.lastIndexOf('.') + 1) + ": "
+ + msg);
+ }
+
+ public static void d(String caller, String msg) {
+ if (!DEBUG) {
+ return;
+ }
+
+ Log.d("STK", caller + ": " + msg);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkResponseMessage.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkResponseMessage.java
new file mode 100644
index 0000000..04a52e6
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkResponseMessage.java
@@ -0,0 +1,54 @@
+/*
+ * 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.gsm.stk;
+
+public class StkResponseMessage {
+ CommandDetails cmdDet = null;
+ ResultCode resCode = ResultCode.OK;
+ int usersMenuSelection = 0;
+ String usersInput = null;
+ boolean usersYesNoSelection = false;
+ boolean usersConfirm = false;
+
+ public StkResponseMessage(StkCmdMessage cmdMsg) {
+ this.cmdDet = cmdMsg.mCmdDet;
+ }
+
+ public void setResultCode(ResultCode resCode) {
+ this.resCode = resCode;
+ }
+
+ public void setMenuSelection(int selection) {
+ this.usersMenuSelection = selection;
+ }
+
+ public void setInput(String input) {
+ this.usersInput = input;
+ }
+
+ public void setYesNo(boolean yesNo) {
+ usersYesNoSelection = yesNo;
+ }
+
+ public void setConfirmation(boolean confirm) {
+ usersConfirm = confirm;
+ }
+
+ CommandDetails getCmdDetails() {
+ return cmdDet;
+ }
+ } \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/TextMessage.java b/telephony/java/com/android/internal/telephony/gsm/stk/TextMessage.java
new file mode 100644
index 0000000..3b6a09a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/TextMessage.java
@@ -0,0 +1,71 @@
+/*
+ * 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.gsm.stk;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class TextMessage implements Parcelable {
+ public String title = "";
+ public String text = null;
+ public Bitmap icon = null;
+ public boolean iconSelfExplanatory = false;
+ public boolean isHighPriority = false;
+ public boolean responseNeeded = true;
+ public boolean userClear = false;
+ public Duration duration = null;
+
+ TextMessage() {
+ }
+
+ private TextMessage(Parcel in) {
+ title = in.readString();
+ text = in.readString();
+ icon = in.readParcelable(null);
+ iconSelfExplanatory = in.readInt() == 1 ? true : false;
+ isHighPriority = in.readInt() == 1 ? true : false;
+ responseNeeded = in.readInt() == 1 ? true : false;
+ userClear = in.readInt() == 1 ? true : false;
+ duration = in.readParcelable(null);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(title);
+ dest.writeString(text);
+ dest.writeParcelable(icon, 0);
+ dest.writeInt(iconSelfExplanatory ? 1 : 0);
+ dest.writeInt(isHighPriority ? 1 : 0);
+ dest.writeInt(responseNeeded ? 1 : 0);
+ dest.writeInt(userClear ? 1 : 0);
+ dest.writeParcelable(duration, 0);
+ }
+
+ public static final Parcelable.Creator<TextMessage> CREATOR = new Parcelable.Creator<TextMessage>() {
+ public TextMessage createFromParcel(Parcel in) {
+ return new TextMessage(in);
+ }
+
+ public TextMessage[] newArray(int size) {
+ return new TextMessage[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/Tone.java b/telephony/java/com/android/internal/telephony/gsm/stk/Tone.java
index c96f164..b64e777 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/Tone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/Tone.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.gsm.stk;
+import android.os.Parcel;
+import android.os.Parcelable;
/**
* Enumeration for representing the tone values for use with PLAY TONE
@@ -23,7 +25,7 @@ package com.android.internal.telephony.gsm.stk;
*
* {@hide}
*/
-public enum Tone {
+public enum Tone implements Parcelable {
// Standard supervisory tones
/**
@@ -163,4 +165,26 @@ public enum Tone {
}
return null;
}
+
+ Tone(Parcel in) {
+ mValue = in.readInt();
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(ordinal());
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<Tone> CREATOR = new Parcelable.Creator<Tone>() {
+ public Tone createFromParcel(Parcel in) {
+ return Tone.values()[in.readInt()];
+ }
+
+ public Tone[] newArray(int size) {
+ return new Tone[size];
+ }
+ };
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ToneSettings.java b/telephony/java/com/android/internal/telephony/gsm/stk/ToneSettings.java
new file mode 100644
index 0000000..bbc925e
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ToneSettings.java
@@ -0,0 +1,62 @@
+/*
+ * 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.gsm.stk;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container class for PlayTone commands parameters.
+ *
+ */
+public class ToneSettings implements Parcelable {
+ public Duration duration;
+ public Tone tone;
+ public boolean vibrate;
+
+ public ToneSettings(Duration duration, Tone tone, boolean vibrate) {
+ this.duration = duration;
+ this.tone = tone;
+ this.vibrate = vibrate;
+ }
+
+ private ToneSettings(Parcel in) {
+ duration = in.readParcelable(null);
+ tone = in.readParcelable(null);
+ vibrate = in.readInt() == 1;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(duration, 0);
+ dest.writeParcelable(tone, 0);
+ dest.writeInt(vibrate ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<ToneSettings> CREATOR = new Parcelable.Creator<ToneSettings>() {
+ public ToneSettings createFromParcel(Parcel in) {
+ return new ToneSettings(in);
+ }
+
+ public ToneSettings[] newArray(int size) {
+ return new ToneSettings[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java b/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
new file mode 100644
index 0000000..cd02a8b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2006-2007 Google Inc.
+ *
+ * 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.stk;
+
+import android.util.Log;
+
+import com.android.internal.telephony.gsm.GsmAlphabet;
+import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.gsm.stk.Duration.TimeUnit;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+abstract class ValueParser {
+
+ private static final String TAG = "ValueParser";
+
+ /**
+ * Search for a Command Details object from a list.
+ *
+ * @param ctlvs List of ComprehensionTlv objects used for search
+ * @return An CtlvCommandDetails object found from the objects. If no
+ * Command Details object is found, ResultException is thrown.
+ * @throws ResultException
+ */
+ static CommandDetails retrieveCommandDetails(ComprehensionTlv ctlv)
+ throws ResultException {
+
+ CommandDetails cmdDet = new CommandDetails();
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ try {
+ cmdDet.compRequired = ctlv.isComprehensionRequired();
+ cmdDet.commandNumber = rawValue[valueIndex] & 0xff;
+ cmdDet.typeOfCommand = rawValue[valueIndex + 1] & 0xff;
+ cmdDet.commandQualifier = rawValue[valueIndex + 2] & 0xff;
+ return cmdDet;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+
+ /**
+ * Search for a Device Identities object from a list.
+ *
+ * @param ctlvs List of ComprehensionTlv objects used for search
+ * @return An CtlvDeviceIdentities object found from the objects. If no
+ * Command Details object is found, ResultException is thrown.
+ * @throws ResultException
+ */
+ static DeviceIdentities retrieveDeviceIdentities(ComprehensionTlv ctlv)
+ throws ResultException {
+
+ DeviceIdentities devIds = new DeviceIdentities();
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ try {
+ devIds.sourceId = rawValue[valueIndex] & 0xff;
+ devIds.destinationId = rawValue[valueIndex + 1] & 0xff;
+ return devIds;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
+ }
+ }
+
+ /**
+ * Retrieves Duration information from the Duration COMPREHENSION-TLV
+ * object.
+ *
+ * @param ctlv A Text Attribute COMPREHENSION-TLV object
+ * @return A Duration object
+ * @throws ResultException
+ */
+ static Duration retrieveDuration(ComprehensionTlv ctlv) throws ResultException {
+ int timeInterval = 0;
+ TimeUnit timeUnit = TimeUnit.SECOND;
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+
+ try {
+ timeUnit = TimeUnit.values()[(rawValue[valueIndex] & 0xff)];
+ timeInterval = rawValue[valueIndex + 1] & 0xff;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ return new Duration(timeInterval, timeUnit);
+ }
+
+ /**
+ * Retrieves Item information from the COMPREHENSION-TLV object.
+ *
+ * @param ctlv A Text Attribute COMPREHENSION-TLV object
+ * @return An Item
+ * @throws ResultException
+ */
+ static Item retrieveItem(ComprehensionTlv ctlv) throws ResultException {
+ Item item = null;
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ int length = ctlv.getLength();
+
+ if (length != 0) {
+ int textLen = length - 1;
+
+ try {
+ int id = rawValue[valueIndex] & 0xff;
+ String text = SimUtils.adnStringFieldToString(rawValue,
+ valueIndex + 1, textLen);
+ item = new Item(id, text);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+
+ return item;
+ }
+
+ /**
+ * Retrieves Item id information from the COMPREHENSION-TLV object.
+ *
+ * @param ctlv A Text Attribute COMPREHENSION-TLV object
+ * @return An Item id
+ * @throws ResultException
+ */
+ static int retrieveItemId(ComprehensionTlv ctlv) throws ResultException {
+ int id = 0;
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+
+ try {
+ id = rawValue[valueIndex] & 0xff;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+
+ return id;
+ }
+
+ /**
+ * Retrieves icon id from an Icon Identifier COMPREHENSION-TLV object
+ *
+ * @param ctlv An Icon Identifier COMPREHENSION-TLV object
+ * @return IconId instance
+ * @throws ResultException
+ */
+ static IconId retrieveIconId(ComprehensionTlv ctlv) throws ResultException {
+ IconId id = new IconId();
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ try {
+ id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00;
+ id.recordNumber = rawValue[valueIndex] & 0xff;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+
+ return id;
+ }
+
+ /**
+ * Retrieves item icons id from an Icon Identifier List COMPREHENSION-TLV
+ * object
+ *
+ * @param ctlv An Item Icon List Identifier COMPREHENSION-TLV object
+ * @return ItemsIconId instance
+ * @throws ResultException
+ */
+ static ItemsIconId retrieveItemsIconId(ComprehensionTlv ctlv)
+ throws ResultException {
+ Log.d(TAG, "retrieveIconIdList:");
+ ItemsIconId id = new ItemsIconId();
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ int numOfItems = ctlv.getLength() - 1;
+ id.recordNumbers = new int[numOfItems];
+
+ try {
+ // get icon self-explanatory
+ id.selfExplanatory = (rawValue[valueIndex++] & 0xff) == 0x00;
+
+ for (int index = 0; index < numOfItems;) {
+ id.recordNumbers[index++] = rawValue[valueIndex++];
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ return id;
+ }
+
+ /**
+ * Retrieves text attribute information from the Text Attribute
+ * COMPREHENSION-TLV object.
+ *
+ * @param ctlv A Text Attribute COMPREHENSION-TLV object
+ * @return A list of TextAttribute objects
+ * @throws ResultException
+ */
+ static List<TextAttribute> retrieveTextAttribute(ComprehensionTlv ctlv)
+ throws ResultException {
+ ArrayList<TextAttribute> lst = new ArrayList<TextAttribute>();
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ int length = ctlv.getLength();
+
+ if (length != 0) {
+ // Each attribute is consisted of four bytes
+ int itemCount = length / 4;
+
+ try {
+ for (int i = 0; i < itemCount; i++, valueIndex += 4) {
+ int start = rawValue[valueIndex] & 0xff;
+ int textLength = rawValue[valueIndex + 1] & 0xff;
+ int format = rawValue[valueIndex + 2] & 0xff;
+ int colorValue = rawValue[valueIndex + 3] & 0xff;
+
+ int alignValue = format & 0x03;
+ TextAlignment align = TextAlignment.fromInt(alignValue);
+
+ int sizeValue = (format >> 2) & 0x03;
+ FontSize size = FontSize.fromInt(sizeValue);
+ if (size == null) {
+ // Font size value is not defined. Use default.
+ size = FontSize.NORMAL;
+ }
+
+ boolean bold = (format & 0x10) != 0;
+ boolean italic = (format & 0x20) != 0;
+ boolean underlined = (format & 0x40) != 0;
+ boolean strikeThrough = (format & 0x80) != 0;
+
+ TextColor color = TextColor.fromInt(colorValue);
+
+ TextAttribute attr = new TextAttribute(start, textLength,
+ align, size, bold, italic, underlined,
+ strikeThrough, color);
+ lst.add(attr);
+ }
+
+ return lst;
+
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Retrieves alpha identifier from an Alpha Identifier COMPREHENSION-TLV
+ * object.
+ *
+ * @param ctlv An Alpha Identifier COMPREHENSION-TLV object
+ * @return String corresponding to the alpha identifier
+ * @throws ResultException
+ */
+ static String retrieveAlphaId(ComprehensionTlv ctlv) throws ResultException {
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ int length = ctlv.getLength();
+ if (length != 0) {
+ try {
+ return SimUtils.adnStringFieldToString(rawValue, valueIndex,
+ length);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves text from the Text COMPREHENSION-TLV object, and decodes it
+ * into a Java String.
+ *
+ * @param ctlv A Text COMPREHENSION-TLV object
+ * @return A Java String object decoded from the Text object
+ * @throws ResultException
+ */
+ static String retrieveTextString(ComprehensionTlv ctlv) throws ResultException {
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ byte codingScheme = 0x00;
+ String text = null;
+ int textLen = ctlv.getLength();
+
+ // In case the text length is 0, return a null string.
+ if (textLen == 0) {
+ return text;
+ } else {
+ // one byte is coding scheme
+ textLen -= 1;
+ }
+
+ try {
+ codingScheme = (byte) (rawValue[valueIndex] & 0x0c);
+
+ if (codingScheme == 0x00) { // GSM 7-bit packed
+ text = GsmAlphabet.gsm7BitPackedToString(rawValue,
+ valueIndex + 1, (textLen * 8) / 7);
+ } else if (codingScheme == 0x04) { // GSM 8-bit unpacked
+ text = GsmAlphabet.gsm8BitUnpackedToString(rawValue,
+ valueIndex + 1, textLen);
+ } else if (codingScheme == 0x08) { // UCS2
+ text = new String(rawValue, valueIndex + 1, textLen, "UTF-16");
+ } else {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+
+ return text;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ } catch (UnsupportedEncodingException e) {
+ // This should never happen.
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/test/ModelInterpreter.java b/telephony/java/com/android/internal/telephony/test/ModelInterpreter.java
index 6af5d87..25d2026 100644
--- a/telephony/java/com/android/internal/telephony/test/ModelInterpreter.java
+++ b/telephony/java/com/android/internal/telephony/test/ModelInterpreter.java
@@ -16,17 +16,18 @@
package com.android.internal.telephony.test;
-import com.android.internal.os.HandlerThread;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.IOException;
import java.io.UnsupportedEncodingException;
-
-import android.os.*;
-import android.util.Log;
+import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
-import java.net.InetSocketAddress;
import java.util.List;
// Also in ATChannel.java
@@ -131,7 +132,7 @@ class InterpreterEx extends Exception
}
public class ModelInterpreter
- implements Runnable, HandlerInterface, SimulatedRadioControl
+ implements Runnable, SimulatedRadioControl
{
static final int MAX_CALLS = 6;
@@ -151,7 +152,7 @@ public class ModelInterpreter
SimulatedGsmCallState simulatedCallState;
- HandlerThread handlerThread;
+ HandlerThread mHandlerThread;
int pausedResponseCount;
Object pausedResponseMonitor = new Object();
@@ -186,15 +187,10 @@ public class ModelInterpreter
init()
{
new Thread(this, "ModelInterpreter").start();
-
- handlerThread
- = new HandlerThread(this,
- new Runnable() {
- public void run() {
- simulatedCallState = new SimulatedGsmCallState();
- }
- },
- "ModelInterpreter");
+ mHandlerThread = new HandlerThread("ModelInterpreter");
+ mHandlerThread.start();
+ Looper looper = mHandlerThread.getLooper();
+ simulatedCallState = new SimulatedGsmCallState(looper);
}
//***** Runnable Implementation
@@ -273,14 +269,6 @@ public class ModelInterpreter
}
}
- //***** HandlerInterface Implementation
-
- public void
- handleMessage(Message msg)
- {
-
- }
-
//***** Instance Methods
@@ -695,7 +683,10 @@ public class ModelInterpreter
public void
shutdown()
{
- handlerThread.getHandler().getLooper().quit();
+ Looper looper = mHandlerThread.getLooper();
+ if (looper != null) {
+ looper.quit();
+ }
try {
in.close();
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index 47fac46..33c1679 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -16,27 +16,25 @@
package com.android.internal.telephony.test;
-import com.android.internal.os.HandlerThread;
+
import android.os.AsyncResult;
-import android.os.HandlerInterface;
+import android.os.HandlerThread;
+import android.os.Looper;
import android.os.Message;
-import com.android.internal.telephony.ATParseEx;
+import android.util.Log;
+
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.gsm.BaseCommands;
-import com.android.internal.telephony.gsm.BaseCommands;
import com.android.internal.telephony.gsm.CallFailCause;
import com.android.internal.telephony.gsm.CommandException;
import com.android.internal.telephony.gsm.CommandsInterface;
-import com.android.internal.telephony.gsm.DriverCall;
import com.android.internal.telephony.gsm.PDPContextState;
-import com.android.internal.telephony.gsm.stk.CtlvCommandDetails;
-import com.android.internal.telephony.gsm.stk.ResultCode;
import com.android.internal.telephony.gsm.SuppServiceNotification;
-import android.util.Log;
+
import java.util.ArrayList;
public final class SimulatedCommands extends BaseCommands
- implements CommandsInterface, HandlerInterface, SimulatedRadioControl
+ implements CommandsInterface, SimulatedRadioControl
{
private final static String LOG_TAG = "SIM";
@@ -64,7 +62,7 @@ public final class SimulatedCommands extends BaseCommands
//***** Instance Variables
SimulatedGsmCallState simulatedCallState;
- HandlerThread handlerThread;
+ HandlerThread mHandlerThread;
SimLockState mSimLockedState;
boolean mSimLockEnabled;
int mPinUnlockAttempts;
@@ -88,15 +86,12 @@ public final class SimulatedCommands extends BaseCommands
public
SimulatedCommands() {
super(null); // Don't log statistics
- handlerThread
- = new HandlerThread(this,
- new Runnable() {
- public void run() {
- simulatedCallState = new SimulatedGsmCallState();
- }
- },
- "SimulatedCommands");
-
+ mHandlerThread = new HandlerThread("SimulatedCommands");
+ mHandlerThread.start();
+ Looper looper = mHandlerThread.getLooper();
+
+ simulatedCallState = new SimulatedGsmCallState(looper);
+
setRadioState(RadioState.RADIO_OFF);
mSimLockedState = INITIAL_LOCK_STATE;
mSimLockEnabled = (mSimLockedState != SimLockState.NONE);
@@ -1274,7 +1269,10 @@ public final class SimulatedCommands extends BaseCommands
shutdown()
{
setRadioState(RadioState.RADIO_UNAVAILABLE);
- handlerThread.getHandler().getLooper().quit();
+ Looper looper = mHandlerThread.getLooper();
+ if (looper != null) {
+ looper.quit();
+ }
}
/** hangup all */
@@ -1313,14 +1311,6 @@ public final class SimulatedCommands extends BaseCommands
}
}
- //***** HandlerInterface implementation
-
- public void
- handleMessage(Message msg)
- {
-
- }
-
//***** Private Methods
private void unimplemented(Message result)
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java b/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
index bbc2bba..340d788 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.test;
+import android.os.Looper;
import android.os.Message;
import android.os.Handler;
import android.telephony.PhoneNumberUtils;
@@ -162,6 +163,10 @@ class SimulatedGsmCallState extends Handler
//***** Overridden from Handler
+ public SimulatedGsmCallState(Looper looper) {
+ super(looper);
+ }
+
public void
handleMessage(Message msg)
{
@@ -176,7 +181,8 @@ class SimulatedGsmCallState extends Handler
}
//***** Public Methods
-
+
+
/**
* Start the simulated phone ringing
* true if succeeded, false if failed