diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /telephony/java/android | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'telephony/java/android')
15 files changed, 0 insertions, 5236 deletions
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java deleted file mode 100644 index 464085f..0000000 --- a/telephony/java/android/telephony/CellLocation.java +++ /dev/null @@ -1,73 +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 android.telephony; - -import android.os.Bundle; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.telephony.gsm.GsmCellLocation; -import com.android.internal.telephony.ITelephony; - -/** - * Abstract class that represents the location of the device. Currently the only - * subclass is {@link android.telephony.gsm.GsmCellLocation}. {@more} - */ -public abstract class CellLocation { - - /** - * Request an update of the current location. If the location has changed, - * a broadcast will be sent to everyone registered with {@link - * PhoneStateListener#LISTEN_CELL_LOCATION}. - */ - public static void requestLocationUpdate() { - try { - ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.getService("phone")); - if (phone != null) { - phone.updateServiceLocation(); - } - } catch (RemoteException ex) { - // ignore it - } - } - - /** - * Create a new CellLocation from a intent notifier Bundle - * - * This method is used by PhoneStateIntentReceiver and maybe by - * external applications. - * - * @param bundle Bundle from intent notifier - * @return newly created CellLocation - * - * @hide - */ - public static CellLocation newFromBundle(Bundle bundle) { - return new GsmCellLocation(bundle); - } - - /** - * @hide - */ - public abstract void fillInNotifierBundle(Bundle bundle); - - /** - * Return a new CellLocation object representing an unknown location. - */ - public static CellLocation getEmpty() { - return new GsmCellLocation(); - } -} diff --git a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java deleted file mode 100644 index 8a82966..0000000 --- a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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 deleted file mode 100644 index a7e709e..0000000 --- a/telephony/java/android/telephony/NeighboringCellInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //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 deleted file mode 100644 index 326401a..0000000 --- a/telephony/java/android/telephony/NeighboringCellInfo.java +++ /dev/null @@ -1,123 +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 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/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java deleted file mode 100644 index 0bc6c04..0000000 --- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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; -import android.text.Selection; -import android.text.TextWatcher; -import android.widget.TextView; - -import java.util.Locale; - -/** - * Watches a {@link TextView} and if a phone number is entered will format it using - * {@link PhoneNumberUtils#formatNumber(Editable, int)}. The formatting is based on - * the current system locale when this object is created and future locale changes - * may not take effect on this instance. - */ -public class PhoneNumberFormattingTextWatcher implements TextWatcher { - - static private int sFormatType; - static private Locale sCachedLocale; - private boolean mFormatting; - private boolean mDeletingHyphen; - private int mHyphenStart; - private boolean mDeletingBackward; - - public PhoneNumberFormattingTextWatcher() { - if (sCachedLocale == null || sCachedLocale != Locale.getDefault()) { - sCachedLocale = Locale.getDefault(); - sFormatType = PhoneNumberUtils.getFormatTypeForLocale(sCachedLocale); - } - } - - public synchronized void afterTextChanged(Editable text) { - // Make sure to ignore calls to afterTextChanged caused by the work done below - if (!mFormatting) { - mFormatting = true; - - // If deleting the hyphen, also delete the char before or after that - if (mDeletingHyphen && mHyphenStart > 0) { - if (mDeletingBackward) { - if (mHyphenStart - 1 < text.length()) { - text.delete(mHyphenStart - 1, mHyphenStart); - } - } else if (mHyphenStart < text.length()) { - text.delete(mHyphenStart, mHyphenStart + 1); - } - } - - PhoneNumberUtils.formatNumber(text, sFormatType); - - mFormatting = false; - } - } - - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - // Check if the user is deleting a hyphen - if (!mFormatting) { - // Make sure user is deleting one char, without a selection - final int selStart = Selection.getSelectionStart(s); - final int selEnd = Selection.getSelectionEnd(s); - if (s.length() > 1 // Can delete another character - && count == 1 // Deleting only one character - && after == 0 // Deleting - && s.charAt(start) == '-' // a hyphen - && selStart == selEnd) { // no selection - mDeletingHyphen = true; - mHyphenStart = start; - // Check if the user is deleting forward or backward - if (selStart == start + 1) { - mDeletingBackward = true; - } else { - mDeletingBackward = false; - } - } else { - mDeletingHyphen = false; - } - } - } - - public void onTextChanged(CharSequence s, int start, int before, int count) { - // Does nothing - } -} diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java deleted file mode 100644 index d3942fc..0000000 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ /dev/null @@ -1,1231 +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 android.telephony; - -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.os.SystemProperties; -import android.provider.Contacts; -import android.text.Editable; -import android.text.SpannableStringBuilder; -import android.text.TextUtils; -import android.util.SparseIntArray; - -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Various utilities for dealing with phone number strings. - */ -public class PhoneNumberUtils -{ - /* - * Special characters - * - * (See "What is a phone number?" doc) - * 'p' --- GSM pause character, same as comma - * 'n' --- GSM wild character - * 'w' --- GSM wait character - */ - public static final char PAUSE = ','; - public static final char WAIT = ';'; - public static final char WILD = 'N'; - - /* - * TOA = TON + NPI - * See TS 24.008 section 10.5.4.7 for details. - * These are the only really useful TOA values - */ - public static final int TOA_International = 0x91; - public static final int TOA_Unknown = 0x81; - - /* - * global-phone-number = ["+"] 1*( DIGIT / written-sep ) - * written-sep = ("-"/".") - */ - private static final Pattern GLOBAL_PHONE_NUMBER_PATTERN = - Pattern.compile("[\\+]?[0-9.-]+"); - - /** True if c is ISO-LATIN characters 0-9 */ - public static boolean - isISODigit (char c) { - return c >= '0' && c <= '9'; - } - - /** True if c is ISO-LATIN characters 0-9, *, # */ - public final static boolean - is12Key(char c) { - return (c >= '0' && c <= '9') || c == '*' || c == '#'; - } - - /** True if c is ISO-LATIN characters 0-9, *, # , +, WILD */ - public final static boolean - isDialable(char c) { - return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == WILD; - } - - /** True if c is ISO-LATIN characters 0-9, *, # , + (no WILD) */ - public final static boolean - isReallyDialable(char c) { - return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+'; - } - - /** True if c is ISO-LATIN characters 0-9, *, # , +, WILD, WAIT, PAUSE */ - public final static boolean - isNonSeparator(char c) { - return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' - || c == WILD || c == WAIT || c == PAUSE; - } - - /** This any anything to the right of this char is part of the - * post-dial string (eg this is PAUSE or WAIT) - */ - public final static boolean - isStartsPostDial (char c) { - return c == PAUSE || c == WAIT; - } - - /** Extracts the phone number from an Intent. - * - * @param intent the intent to get the number of - * @param context a context to use for database access - * - * @return the phone number that would be called by the intent, or - * <code>null</code> if the number cannot be found. - */ - public static String getNumberFromIntent(Intent intent, Context context) { - String number = null; - - Uri uri = intent.getData(); - String scheme = uri.getScheme(); - - if (scheme.equals("tel")) { - return uri.getSchemeSpecificPart(); - } - - if (scheme.equals("voicemail")) { - return TelephonyManager.getDefault().getVoiceMailNumber(); - } - - if (context == null) { - return null; - } - - String type = intent.resolveType(context); - - Cursor c = context.getContentResolver().query( - uri, new String[]{ Contacts.People.Phones.NUMBER }, - null, null, null); - if (c != null) { - try { - if (c.moveToFirst()) { - number = c.getString( - c.getColumnIndex(Contacts.People.Phones.NUMBER)); - } - } finally { - c.close(); - } - } - - return number; - } - - /** Extracts the network address portion and canonicalizes - * (filters out separators.) - * Network address portion is everything up to DTMF control digit - * separators (pause or wait), but without non-dialable characters. - * - * Please note that the GSM wild character is allowed in the result. - * This must be resolved before dialing. - * - * Allows + only in the first position in the result string. - * - * Returns null if phoneNumber == null - */ - public static String - extractNetworkPortion(String phoneNumber) { - if (phoneNumber == null) { - return null; - } - - int len = phoneNumber.length(); - StringBuilder ret = new StringBuilder(len); - boolean firstCharAdded = false; - - for (int i = 0; i < len; i++) { - char c = phoneNumber.charAt(i); - if (isDialable(c) && (c != '+' || !firstCharAdded)) { - firstCharAdded = true; - ret.append(c); - } else if (isStartsPostDial (c)) { - break; - } - } - - return ret.toString(); - } - - /** - * Strips separators from a phone number string. - * @param phoneNumber phone number to strip. - * @return phone string stripped of separators. - */ - public static String stripSeparators(String phoneNumber) { - if (phoneNumber == null) { - return null; - } - int len = phoneNumber.length(); - StringBuilder ret = new StringBuilder(len); - - for (int i = 0; i < len; i++) { - char c = phoneNumber.charAt(i); - if (isNonSeparator(c)) { - ret.append(c); - } - } - - return ret.toString(); - } - - /** or -1 if both are negative */ - static private int - minPositive (int a, int b) { - if (a >= 0 && b >= 0) { - return (a < b) ? a : b; - } else if (a >= 0) { /* && b < 0 */ - return a; - } else if (b >= 0) { /* && a < 0 */ - return b; - } else { /* a < 0 && b < 0 */ - return -1; - } - } - - /** index of the last character of the network portion - * (eg anything after is a post-dial string) - */ - static private int - indexOfLastNetworkChar(String a) { - int pIndex, wIndex; - int origLength; - int trimIndex; - - origLength = a.length(); - - pIndex = a.indexOf(PAUSE); - wIndex = a.indexOf(WAIT); - - trimIndex = minPositive(pIndex, wIndex); - - if (trimIndex < 0) { - return origLength - 1; - } else { - return trimIndex - 1; - } - } - - /** - * Extracts the post-dial sequence of DTMF control digits, pauses, and - * waits. Strips separators. This string may be empty, but will not be null - * unless phoneNumber == null. - * - * Returns null if phoneNumber == null - */ - - public static String - extractPostDialPortion(String phoneNumber) { - if (phoneNumber == null) return null; - - int trimIndex; - StringBuilder ret = new StringBuilder(); - - trimIndex = indexOfLastNetworkChar (phoneNumber); - - for (int i = trimIndex + 1, s = phoneNumber.length() - ; i < s; i++ - ) { - char c = phoneNumber.charAt(i); - if (isNonSeparator(c)) { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Compare phone numbers a and b, return true if they're identical - * enough for caller ID purposes. - * - * - Compares from right to left - * - requires MIN_MATCH (5) characters to match - * - handles common trunk prefixes and international prefixes - * (basically, everything except the Russian trunk prefix) - * - * Tolerates nulls - */ - public static boolean - compare(String a, String b) { - int ia, ib; - int matched; - - if (a == null || b == null) return a == b; - - if (a.length() == 0 || b.length() == 0) { - return false; - } - - ia = indexOfLastNetworkChar (a); - ib = indexOfLastNetworkChar (b); - matched = 0; - - while (ia >= 0 && ib >=0) { - char ca, cb; - boolean skipCmp = false; - - ca = a.charAt(ia); - - if (!isDialable(ca)) { - ia--; - skipCmp = true; - } - - cb = b.charAt(ib); - - if (!isDialable(cb)) { - ib--; - skipCmp = true; - } - - if (!skipCmp) { - if (cb != ca && ca != WILD && cb != WILD) { - break; - } - ia--; ib--; matched++; - } - } - - if (matched < MIN_MATCH) { - int aLen = a.length(); - - // if the input strings match, but their lengths < MIN_MATCH, - // treat them as equal. - if (aLen == b.length() && aLen == matched) { - return true; - } - return false; - } - - // At least one string has matched completely; - if (matched >= MIN_MATCH && (ia < 0 || ib < 0)) { - return true; - } - - /* - * Now, what remains must be one of the following for a - * match: - * - * - a '+' on one and a '00' or a '011' on the other - * - a '0' on one and a (+,00)<country code> on the other - * (for this, a '0' and a '00' prefix would have succeeded above) - */ - - if (matchIntlPrefix(a, ia + 1) - && matchIntlPrefix (b, ib +1) - ) { - return true; - } - - if (matchTrunkPrefix(a, ia + 1) - && matchIntlPrefixAndCC(b, ib +1) - ) { - return true; - } - - if (matchTrunkPrefix(b, ib + 1) - && matchIntlPrefixAndCC(a, ia +1) - ) { - return true; - } - - return false; - } - - /** - * Returns the rightmost MIN_MATCH (5) characters in the network portion - * in *reversed* order - * - * This can be used to do a database lookup against the column - * that stores getStrippedReversed() - * - * Returns null if phoneNumber == null - */ - public static String - toCallerIDMinMatch(String phoneNumber) { - String np = extractNetworkPortion(phoneNumber); - return internalGetStrippedReversed(np, MIN_MATCH); - } - - /** - * Returns the network portion reversed. - * This string is intended to go into an index column for a - * database lookup. - * - * Returns null if phoneNumber == null - */ - public static String - getStrippedReversed(String phoneNumber) { - String np = extractNetworkPortion(phoneNumber); - - if (np == null) return null; - - return internalGetStrippedReversed(np, np.length()); - } - - /** - * Returns the last numDigits of the reversed phone number - * Returns null if np == null - */ - private static String - internalGetStrippedReversed(String np, int numDigits) { - if (np == null) return null; - - StringBuilder ret = new StringBuilder(numDigits); - int length = np.length(); - - for (int i = length - 1, s = length - ; i >= 0 && (s - i) <= numDigits ; i-- - ) { - char c = np.charAt(i); - - ret.append(c); - } - - return ret.toString(); - } - - /** - * Basically: makes sure there's a + in front of a - * TOA_International number - * - * Returns null if s == null - */ - public static String - stringFromStringAndTOA(String s, int TOA) { - if (s == null) return null; - - if (TOA == TOA_International && s.length() > 0 && s.charAt(0) != '+') { - return "+" + s; - } - - return s; - } - - /** - * Returns the TOA for the given dial string - * Basically, returns TOA_International if there's a + prefix - */ - - public static int - toaFromString(String s) { - if (s != null && s.length() > 0 && s.charAt(0) == '+') { - return TOA_International; - } - - return TOA_Unknown; - } - - /** - * Phone numbers are stored in "lookup" form in the database - * as reversed strings to allow for caller ID lookup - * - * This method takes a phone number and makes a valid SQL "LIKE" - * string that will match the lookup form - * - */ - /** all of a up to len must be an international prefix or - * separators/non-dialing digits - */ - private static boolean - matchIntlPrefix(String a, int len) { - /* '([^0-9*#+pwn]\+[^0-9*#+pwn] | [^0-9*#+pwn]0(0|11)[^0-9*#+pwn] )$' */ - /* 0 1 2 3 45 */ - - int state = 0; - for (int i = 0 ; i < len ; i++) { - char c = a.charAt(i); - - switch (state) { - case 0: - if (c == '+') state = 1; - else if (c == '0') state = 2; - else if (isNonSeparator(c)) return false; - break; - - case 2: - if (c == '0') state = 3; - else if (c == '1') state = 4; - else if (isNonSeparator(c)) return false; - break; - - case 4: - if (c == '1') state = 5; - else if (isNonSeparator(c)) return false; - break; - - default: - if (isNonSeparator(c)) return false; - break; - - } - } - - return state == 1 || state == 3 || state == 5; - } - - /** - * 3GPP TS 24.008 10.5.4.7 - * 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 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 - * - * @return partial string on invalid decode - * - * FIXME(mkf) support alphanumeric address type - * currently implemented in SMSMessage.getAddress() - */ - public static String - calledPartyBCDToString (byte[] bytes, int offset, int length) { - boolean prependPlus = false; - StringBuilder ret = new StringBuilder(1 + length * 2); - - if (length < 2) { - return ""; - } - - if ((bytes[offset] & 0xff) == TOA_International) { - prependPlus = true; - } - - internalCalledPartyBCDFragmentToString( - ret, bytes, offset + 1, 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(); - } - - private static void - internalCalledPartyBCDFragmentToString( - StringBuilder sb, byte [] bytes, int offset, int length) { - for (int i = offset ; i < length + offset ; i++) { - byte b; - char c; - - c = bcdToChar((byte)(bytes[i] & 0xf)); - - if (c == 0) { - return; - } - sb.append(c); - - // FIXME(mkf) TS 23.040 9.1.2.3 says - // "if a mobile receives 1111 in a position prior to - // the last semi-octet then processing shall commense with - // the next semi-octet and the intervening - // semi-octet shall be ignored" - // How does this jive with 24,008 10.5.4.7 - - b = (byte)((bytes[i] >> 4) & 0xf); - - if (b == 0xf && i + 1 == length + offset) { - //ignore final 0xf - break; - } - - c = bcdToChar(b); - if (c == 0) { - return; - } - - sb.append(c); - } - - } - - /** - * Like calledPartyBCDToString, but field does not start with a - * TOA byte. For example: SIM ADN extension fields - */ - - public static String - calledPartyBCDFragmentToString(byte [] bytes, int offset, int length) { - StringBuilder ret = new StringBuilder(length * 2); - - internalCalledPartyBCDFragmentToString(ret, bytes, offset, length); - - return ret.toString(); - } - - /** returns 0 on invalid value */ - private static char - bcdToChar(byte b) { - if (b < 0xa) { - return (char)('0' + b); - } else switch (b) { - case 0xa: return '*'; - case 0xb: return '#'; - case 0xc: return PAUSE; - case 0xd: return WILD; - - default: return 0; - } - } - - private static int - charToBCD(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c == '*') { - return 0xa; - } else if (c == '#') { - return 0xb; - } else if (c == PAUSE) { - return 0xc; - } else if (c == WILD) { - return 0xd; - } else { - throw new RuntimeException ("invalid char for BCD " + c); - } - } - - /** - * Note: calls extractNetworkPortion(), so do not use for - * SIM EF[ADN] style records - * - * Exceptions thrown if extractNetworkPortion(s).length() == 0 - */ - public static byte[] - networkPortionToCalledPartyBCD(String s) { - return numberToCalledPartyBCD(extractNetworkPortion(s)); - } - - /** - * Return true iff the network portion of <code>address</code> is, - * as far as we can tell on the device, suitable for use as an SMS - * destination address. - */ - public static boolean isWellFormedSmsAddress(String address) { - String networkPortion = - PhoneNumberUtils.extractNetworkPortion(address); - - return (!(networkPortion.equals("+") - || TextUtils.isEmpty(networkPortion))) - && isDialable(networkPortion); - } - - public static boolean isGlobalPhoneNumber(String phoneNumber) { - if (TextUtils.isEmpty(phoneNumber)) { - return false; - } - - Matcher match = GLOBAL_PHONE_NUMBER_PATTERN.matcher(phoneNumber); - return match.matches(); - } - - private static boolean isDialable(String address) { - for (int i = 0, count = address.length(); i < count; i++) { - if (!isDialable(address.charAt(i))) { - return false; - } - } - return true; - } - - /** - * Same as {@link #networkPortionToCalledPartyBCD}, but includes a - * one-byte length prefix. - */ - public static byte[] - networkPortionToCalledPartyBCDWithLength(String s) { - return numberToCalledPartyBCDWithLength(extractNetworkPortion(s)); - } - - /** - * Convert a dialing number to BCD byte array - * - * @param number dialing number string - * if the dialing number starts with '+', set to internationl TOA - * @return BCD byte array - */ - public static byte[] - numberToCalledPartyBCD(String number) { - // The extra byte required for '+' is taken into consideration while calculating - // length of ret. - int size = (hasPlus(number) ? number.length() - 1 : number.length()); - byte[] ret = new byte[(size + 1) / 2 + 1]; - - return numberToCalledPartyBCDHelper(ret, 0, number); - } - - /** - * Same as {@link #numberToCalledPartyBCD}, but includes a - * one-byte length prefix. - */ - private static byte[] - numberToCalledPartyBCDWithLength(String number) { - // The extra byte required for '+' is taken into consideration while calculating - // length of ret. - int size = (hasPlus(number) ? number.length() - 1 : number.length()); - int length = (size + 1) / 2 + 1; - byte[] ret = new byte[length + 1]; - - ret[0] = (byte) (length & 0xff); - 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) { - if (hasPlus(number)) { - number = number.replaceAll("\\+", ""); - ret[offset] = (byte) TOA_International; - } else { - 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] - = (byte) ((charToBCD(number.charAt(curChar++))) - | (charToBCD(number.charAt(curChar++))) << 4); - } - - // The left-over octet for odd-length phone numbers should be - // filled with 0xf. - if (countFullBytes + offset < ret.length - 1) { - ret[ret.length - 1] - = (byte) (charToBCD(number.charAt(curChar)) - | (0xf << 4)); - } - return ret; - } - - /** all of 'a' up to len must match non-US trunk prefix ('0') */ - private static boolean - matchTrunkPrefix(String a, int len) { - boolean found; - - found = false; - - for (int i = 0 ; i < len ; i++) { - char c = a.charAt(i); - - if (c == '0' && !found) { - found = true; - } else if (isNonSeparator(c)) { - return false; - } - } - - return found; - } - - /** all of 'a' up to len must be a (+|00|011)country code) - * We're fast and loose with the country code. Any \d{1,3} matches */ - private static boolean - matchIntlPrefixAndCC(String a, int len) { - /* [^0-9*#+pwn]*(\+|0(0|11)\d\d?\d? [^0-9*#+pwn] $ */ - /* 0 1 2 3 45 6 7 8 */ - - int state = 0; - for (int i = 0 ; i < len ; i++ ) { - char c = a.charAt(i); - - switch (state) { - case 0: - if (c == '+') state = 1; - else if (c == '0') state = 2; - else if (isNonSeparator(c)) return false; - break; - - case 2: - if (c == '0') state = 3; - else if (c == '1') state = 4; - else if (isNonSeparator(c)) return false; - break; - - case 4: - if (c == '1') state = 5; - else if (isNonSeparator(c)) return false; - break; - - case 1: - case 3: - case 5: - if (isISODigit(c)) state = 6; - else if (isNonSeparator(c)) return false; - break; - - case 6: - case 7: - if (isISODigit(c)) state++; - else if (isNonSeparator(c)) return false; - break; - - default: - if (isNonSeparator(c)) return false; - } - } - - return state == 6 || state == 7 || state == 8; - } - - //================ Number formatting ========================= - - /** The current locale is unknown, look for a country code or don't format */ - 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[] { - "US", // United States - "CA", // Canada - "AS", // American Samoa - "AI", // Anguilla - "AG", // Antigua and Barbuda - "BS", // Bahamas - "BB", // Barbados - "BM", // Bermuda - "VG", // British Virgin Islands - "KY", // Cayman Islands - "DM", // Dominica - "DO", // Dominican Republic - "GD", // Grenada - "GU", // Guam - "JM", // Jamaica - "PR", // Puerto Rico - "MS", // Montserrat - "NP", // Northern Mariana Islands - "KN", // Saint Kitts and Nevis - "LC", // Saint Lucia - "VC", // Saint Vincent and the Grenadines - "TT", // Trinidad and Tobago - "TC", // Turks and Caicos Islands - "VI", // U.S. Virgin Islands - }; - - /** - * Breaks the given number down and formats it according to the rules - * for the country the number is from. - * - * @param source the phone number to format - * @return a locally acceptable formatting of the input, or the raw input if - * formatting rules aren't known for the number - */ - public static String formatNumber(String source) { - SpannableStringBuilder text = new SpannableStringBuilder(source); - formatNumber(text, getFormatTypeForLocale(Locale.getDefault())); - return text.toString(); - } - - /** - * Returns the phone number formatting type for the given locale. - * - * @param locale The locale of interest, usually {@link Locale#getDefault()} - * @return the formatting type for the given locale, or FORMAT_UNKNOWN if the formatting - * rules are not known for the given locale - */ - public static int getFormatTypeForLocale(Locale locale) { - String country = locale.getCountry(); - - // Check for the NANP countries - int length = NANP_COUNTRIES.length; - for (int i = 0; i < length; i++) { - if (NANP_COUNTRIES[i].equals(country)) { - return FORMAT_NANP; - } - } - if (locale.equals(Locale.JAPAN)) { - return FORMAT_JAPAN; - } - return FORMAT_UNKNOWN; - } - - /** - * Formats a phone number in-place. Currently only supports NANP formatting. - * - * @param text The number to be formatted, will be modified with the formatting - * @param defaultFormattingType The default formatting rules to apply if the number does - * not begin with +<country_code> - */ - public static void formatNumber(Editable text, int defaultFormattingType) { - int formatType = defaultFormattingType; - - 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; - } - } - - switch (formatType) { - case FORMAT_NANP: - formatNanpNumber(text); - return; - case FORMAT_JAPAN: - formatJapaneseNumber(text); - return; - } - } - - private static final int NANP_STATE_DIGIT = 1; - private static final int NANP_STATE_PLUS = 2; - private static final int NANP_STATE_ONE = 3; - private static final int NANP_STATE_DASH = 4; - - /** - * Formats a phone number in-place using the NANP formatting rules. Numbers will be formatted - * as: - * - * <p><code> - * xxx-xxxx - * xxx-xxx-xxxx - * 1-xxx-xxx-xxxx - * +1-xxx-xxx-xxxx - * </code></p> - * - * @param text the number to be formatted, will be modified with the formatting - */ - public static void formatNanpNumber(Editable text) { - int length = text.length(); - if (length > "+1-nnn-nnn-nnnn".length()) { - // The string is too long to be formatted - 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()) { - if (text.charAt(p) == '-') { - text.delete(p, p + 1); - } else { - p++; - } - } - length = text.length(); - - // When scanning the number we record where dashes need to be added, - // if they're non-0 at the end of the scan the dashes will be added in - // the proper places. - int dashPositions[] = new int[3]; - int numDashes = 0; - - int state = NANP_STATE_DIGIT; - int numDigits = 0; - for (int i = 0; i < length; i++) { - char c = text.charAt(i); - switch (c) { - case '1': - if (numDigits == 0 || state == NANP_STATE_PLUS) { - state = NANP_STATE_ONE; - break; - } - // fall through - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '0': - if (state == NANP_STATE_PLUS) { - // Only NANP number supported for now - text.replace(0, length, saved); - return; - } else if (state == NANP_STATE_ONE) { - // Found either +1 or 1, follow it up with a dash - dashPositions[numDashes++] = i; - } else if (state != NANP_STATE_DASH && (numDigits == 3 || numDigits == 6)) { - // Found a digit that should be after a dash that isn't - dashPositions[numDashes++] = i; - } - state = NANP_STATE_DIGIT; - numDigits++; - break; - - case '-': - state = NANP_STATE_DASH; - break; - - case '+': - if (i == 0) { - // Plus is only allowed as the first character - state = NANP_STATE_PLUS; - break; - } - // Fall through - default: - // Unknown character, bail on formatting - text.replace(0, length, saved); - return; - } - } - - if (numDigits == 7) { - // With 7 digits we want xxx-xxxx, not xxx-xxx-x - numDashes--; - } - - // Actually put the dashes in place - for (int i = 0; i < numDashes; i++) { - int pos = dashPositions[i]; - text.replace(pos + i, pos + i, "-"); - } - - // Remove trailing dashes - int len = text.length(); - while (len > 0) { - if (text.charAt(len - 1) == '-') { - text.delete(len - 1, len); - len--; - } else { - break; - } - } - } - - /** - * 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 - static final int MIN_MATCH = 5; - - /** - * isEmergencyNumber: checks a given number against the list of - * emergency numbers provided by the RIL and SIM card. - * - * @param number the number to look up. - * @return if the number is in the list of emergency numbers - * 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 - // to the list. - number = extractNetworkPortion(number); - - // retrieve the list of emergency numbers - String numbers = SystemProperties.get("ro.ril.ecclist"); - - if (!TextUtils.isEmpty(numbers)) { - // searches through the comma-separated list for a match, - // return true if one is found. - for (String emergencyNum : numbers.split(",")) { - if (emergencyNum.equals(number)) { - return true; - } - } - // no matches found against the list! - return false; - } - - //no ecclist system property, so use our own list. - return (number.equals("112") || number.equals("911")); - } - - /** - * Translates any alphabetic letters (i.e. [A-Za-z]) in the - * specified phone number into the equivalent numeric digits, - * according to the phone keypad letter mapping described in - * ITU E.161 and ISO/IEC 9995-8. - * - * @return the input string, with alpha letters converted to numeric - * digits using the phone keypad letter mapping. For example, - * an input of "1-800-GOOG-411" will return "1-800-4664-411". - */ - public static String convertKeypadLettersToDigits(String input) { - if (input == null) { - return input; - } - int len = input.length(); - if (len == 0) { - return input; - } - - char[] out = input.toCharArray(); - - for (int i = 0; i < len; i++) { - char c = out[i]; - // If this char isn't in KEYPAD_MAP at all, just leave it alone. - out[i] = (char) KEYPAD_MAP.get(c, c); - } - - return new String(out); - } - - /** - * The phone keypad letter mapping (see ITU E.161 or ISO/IEC 9995-8.) - * TODO: This should come from a resource. - */ - private static final SparseIntArray KEYPAD_MAP = new SparseIntArray(); - static { - KEYPAD_MAP.put('a', '2'); KEYPAD_MAP.put('b', '2'); KEYPAD_MAP.put('c', '2'); - KEYPAD_MAP.put('A', '2'); KEYPAD_MAP.put('B', '2'); KEYPAD_MAP.put('C', '2'); - - KEYPAD_MAP.put('d', '3'); KEYPAD_MAP.put('e', '3'); KEYPAD_MAP.put('f', '3'); - KEYPAD_MAP.put('D', '3'); KEYPAD_MAP.put('E', '3'); KEYPAD_MAP.put('F', '3'); - - KEYPAD_MAP.put('g', '4'); KEYPAD_MAP.put('h', '4'); KEYPAD_MAP.put('i', '4'); - KEYPAD_MAP.put('G', '4'); KEYPAD_MAP.put('H', '4'); KEYPAD_MAP.put('I', '4'); - - KEYPAD_MAP.put('j', '5'); KEYPAD_MAP.put('k', '5'); KEYPAD_MAP.put('l', '5'); - KEYPAD_MAP.put('J', '5'); KEYPAD_MAP.put('K', '5'); KEYPAD_MAP.put('L', '5'); - - KEYPAD_MAP.put('m', '6'); KEYPAD_MAP.put('n', '6'); KEYPAD_MAP.put('o', '6'); - KEYPAD_MAP.put('M', '6'); KEYPAD_MAP.put('N', '6'); KEYPAD_MAP.put('O', '6'); - - KEYPAD_MAP.put('p', '7'); KEYPAD_MAP.put('q', '7'); KEYPAD_MAP.put('r', '7'); KEYPAD_MAP.put('s', '7'); - KEYPAD_MAP.put('P', '7'); KEYPAD_MAP.put('Q', '7'); KEYPAD_MAP.put('R', '7'); KEYPAD_MAP.put('S', '7'); - - KEYPAD_MAP.put('t', '8'); KEYPAD_MAP.put('u', '8'); KEYPAD_MAP.put('v', '8'); - KEYPAD_MAP.put('T', '8'); KEYPAD_MAP.put('U', '8'); KEYPAD_MAP.put('V', '8'); - - KEYPAD_MAP.put('w', '9'); KEYPAD_MAP.put('x', '9'); KEYPAD_MAP.put('y', '9'); KEYPAD_MAP.put('z', '9'); - KEYPAD_MAP.put('W', '9'); KEYPAD_MAP.put('X', '9'); KEYPAD_MAP.put('Y', '9'); KEYPAD_MAP.put('Z', '9'); - } -} diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java deleted file mode 100644 index 8a8a675..0000000 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ /dev/null @@ -1,265 +0,0 @@ -package android.telephony; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.telephony.ServiceState; -import android.telephony.CellLocation; -import android.util.Log; - -import com.android.internal.telephony.IPhoneStateListener; - -/** - * A listener class for monitoring changes in specific telephony states - * on the device, including service state, signal strength, message - * waiting indicator (voicemail), and others. - * <p> - * Override the methods for the state that you wish to receive updates for, and - * pass your PhoneStateListener object, along with bitwise-or of the LISTEN_ - * flags to {@link TelephonyManager#listen TelephonyManager.listen()}. - * <p> - * Note that access to some telephony information is - * permission-protected. Your application won't receive updates for protected - * information unless it has the appropriate permissions declared in - * its manifest file. Where permissions apply, they are noted in the - * appropriate LISTEN_ flags. - */ -public class PhoneStateListener { - - /** - * Stop listening for updates. - */ - public static final int LISTEN_NONE = 0; - - /** - * Listen for changes to the network service state (cellular). - * - * @see #onServiceStateChanged - * @see ServiceState - */ - public static final int LISTEN_SERVICE_STATE = 0x00000001; - - /** - * Listen for changes to the network signal strength (cellular). - * <p> - * Example: The status bar uses this to control the signal-strength - * icon. - * - * @see #onSignalStrengthChanged - */ - public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002; - - /** - * Listen for changes to the message-waiting indicator. - * <p> - * Example: The status bar uses this to determine when to display the - * voicemail icon. - * - * @see #onMessageWaitingIndicatorChanged - */ - public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004; - - /** - * Listen for changes to the call-forwarding indicator. - * - * @see #onCallForwardingIndicatorChanged - */ - public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008; - - /** - * Listen for changes to the device's cell location. Note that - * this will result in frequent callbacks to the listener. - * {@more} - * Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION - * ACCESS_COARSE_LOCATION} - * <p> - * If you need regular location updates but want more control over - * the update interval or location precision, you can set up a listener - * through the {@link android.location.LocationManager location manager} - * instead. - * - * @see #onCellLocationChanged - */ - public static final int LISTEN_CELL_LOCATION = 0x00000010; - - /** - * Listen for changes to the device call state. - * - * @see #onCallStateChanged - */ - public static final int LISTEN_CALL_STATE = 0x00000020; - - /** - * Listen for changes to the data connection state (cellular). - * - * @see #onDataConnectionStateChanged - */ - public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040; - - /** - * Listen for changes to the direction of data traffic on the data - * connection (cellular). - * - * Example: The status bar uses this to display the appropriate - * data-traffic icon. - * - * @see #onDataActivity - */ - public static final int LISTEN_DATA_ACTIVITY = 0x00000080; - - public PhoneStateListener() { - } - - /** - * Callback invoked when device service state changes. - * - * @see ServiceState#STATE_EMERGENCY_ONLY - * @see ServiceState#STATE_IN_SERVICE - * @see ServiceState#STATE_OUT_OF_SERVICE - * @see ServiceState#STATE_POWER_OFF - */ - public void onServiceStateChanged(ServiceState serviceState) { - // default implementation empty - } - - /** - * Callback invoked when network signal strength changes. - * - * @see ServiceState#STATE_EMERGENCY_ONLY - * @see ServiceState#STATE_IN_SERVICE - * @see ServiceState#STATE_OUT_OF_SERVICE - * @see ServiceState#STATE_POWER_OFF - */ - public void onSignalStrengthChanged(int asu) { - // default implementation empty - } - - /** - * Callback invoked when the message-waiting indicator changes. - */ - public void onMessageWaitingIndicatorChanged(boolean mwi) { - // default implementation empty - } - - /** - * Callback invoked when the call-forwarding indicator changes. - */ - public void onCallForwardingIndicatorChanged(boolean cfi) { - // default implementation empty - } - - /** - * Callback invoked when device cell location changes. - */ - public void onCellLocationChanged(CellLocation location) { - // default implementation empty - } - - /** - * Callback invoked when device call state changes. - * - * @see TelephonyManager#CALL_STATE_IDLE - * @see TelephonyManager#CALL_STATE_RINGING - * @see TelephonyManager#CALL_STATE_OFFHOOK - */ - public void onCallStateChanged(int state, String incomingNumber) { - // default implementation empty - } - - /** - * Callback invoked when connection state changes. - * - * @see TelephonyManager#DATA_DISCONNECTED - * @see TelephonyManager#DATA_CONNECTING - * @see TelephonyManager#DATA_CONNECTED - * @see TelephonyManager#DATA_SUSPENDED - */ - public void onDataConnectionStateChanged(int state) { - // default implementation empty - } - - /** - * Callback invoked when data activity state changes. - * - * @see TelephonyManager#DATA_ACTIVITY_NONE - * @see TelephonyManager#DATA_ACTIVITY_IN - * @see TelephonyManager#DATA_ACTIVITY_OUT - * @see TelephonyManager#DATA_ACTIVITY_INOUT - */ - public void onDataActivity(int direction) { - // default implementation empty - } - - /** - * The callback methods need to be called on the handler thread where - * this object was created. If the binder did that for us it'd be nice. - */ - IPhoneStateListener callback = new IPhoneStateListener.Stub() { - public void onServiceStateChanged(ServiceState serviceState) { - Message.obtain(mHandler, LISTEN_SERVICE_STATE, 0, 0, serviceState).sendToTarget(); - } - - public void onSignalStrengthChanged(int asu) { - Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTH, asu, 0, null).sendToTarget(); - } - - public void onMessageWaitingIndicatorChanged(boolean mwi) { - Message.obtain(mHandler, LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null) - .sendToTarget(); - } - - public void onCallForwardingIndicatorChanged(boolean cfi) { - Message.obtain(mHandler, LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null) - .sendToTarget(); - } - - public void onCellLocationChanged(Bundle bundle) { - CellLocation location = CellLocation.newFromBundle(bundle); - Message.obtain(mHandler, LISTEN_CELL_LOCATION, 0, 0, location).sendToTarget(); - } - - public void onCallStateChanged(int state, String incomingNumber) { - Message.obtain(mHandler, LISTEN_CALL_STATE, state, 0, incomingNumber).sendToTarget(); - } - - public void onDataConnectionStateChanged(int state) { - Message.obtain(mHandler, LISTEN_DATA_CONNECTION_STATE, state, 0, null).sendToTarget(); - } - - public void onDataActivity(int direction) { - Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget(); - } - }; - - Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - //Log.d("TelephonyRegistry", "what=0x" + Integer.toHexString(msg.what) + " msg=" + msg); - switch (msg.what) { - case LISTEN_SERVICE_STATE: - PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj); - break; - case LISTEN_SIGNAL_STRENGTH: - PhoneStateListener.this.onSignalStrengthChanged(msg.arg1); - break; - case LISTEN_MESSAGE_WAITING_INDICATOR: - PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0); - break; - case LISTEN_CALL_FORWARDING_INDICATOR: - PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0); - break; - case LISTEN_CELL_LOCATION: - PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj); - break; - case LISTEN_CALL_STATE: - PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj); - break; - case LISTEN_DATA_CONNECTION_STATE: - PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1); - break; - case LISTEN_DATA_ACTIVITY: - PhoneStateListener.this.onDataActivity(msg.arg1); - break; - } - } - }; -} diff --git a/telephony/java/android/telephony/ServiceState.aidl b/telephony/java/android/telephony/ServiceState.aidl deleted file mode 100644 index b1cf379..0000000 --- a/telephony/java/android/telephony/ServiceState.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* //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 ServiceState; - diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java deleted file mode 100644 index 2c58051..0000000 --- a/telephony/java/android/telephony/ServiceState.java +++ /dev/null @@ -1,331 +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 android.telephony; - -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import com.android.internal.telephony.Phone; - -/** - * Contains phone state and service related information. - * - * The following phone information is included in returned ServiceState: - * - * <ul> - * <li>Service state: IN_SERVICE, OUT_OF_SERVICE, EMERGENCY_ONLY, POWER_OFF - * <li>Roaming indicator - * <li>Operator name, short name and numeric id - * <li>Network selection mode - * </ul> - */ -public class ServiceState implements Parcelable { - - /** - * Normal operation condition, the phone is registered - * with an operator either in home network or in roaming. - */ - public static final int STATE_IN_SERVICE = 0; - - /** - * Phone is not registered with any operator, the phone - * can be currently searching a new operator to register to, or not - * searching to registration at all, or registration is denied, or radio - * signal is not available. - */ - public static final int STATE_OUT_OF_SERVICE = 1; - - /** - * The phone is registered and locked. Only emergency numbers are allowed. {@more} - */ - public static final int STATE_EMERGENCY_ONLY = 2; - - /** - * Radio of telephony is explictly powered off. - */ - public static final int STATE_POWER_OFF = 3; - - private int mState = STATE_OUT_OF_SERVICE; - private boolean mRoaming; - private String mOperatorAlphaLong; - private String mOperatorAlphaShort; - private String mOperatorNumeric; - private boolean mIsManualNetworkSelection; - - /** - * Create a new ServiceState from a intent notifier Bundle - * - * This method is used by PhoneStateIntentReceiver and maybe by - * external applications. - * - * @param m Bundle from intent notifier - * @return newly created ServiceState - * @hide - */ - public static ServiceState newFromBundle(Bundle m) { - ServiceState ret; - ret = new ServiceState(); - ret.setFromNotifierBundle(m); - return ret; - } - - /** - * Empty constructor - */ - public ServiceState() { - } - - /** - * Copy constructors - * - * @param s Source service state - */ - public ServiceState(ServiceState s) { - copyFrom(s); - } - - protected void copyFrom(ServiceState s) { - mState = s.mState; - mRoaming = s.mRoaming; - mOperatorAlphaLong = s.mOperatorAlphaLong; - mOperatorAlphaShort = s.mOperatorAlphaShort; - mOperatorNumeric = s.mOperatorNumeric; - mIsManualNetworkSelection = s.mIsManualNetworkSelection; - } - - /** - * Construct a ServiceState object from the given parcel. - */ - public ServiceState(Parcel in) { - mState = in.readInt(); - mRoaming = in.readInt() != 0; - mOperatorAlphaLong = in.readString(); - mOperatorAlphaShort = in.readString(); - mOperatorNumeric = in.readString(); - mIsManualNetworkSelection = in.readInt() != 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeInt(mState); - out.writeInt(mRoaming ? 1 : 0); - out.writeString(mOperatorAlphaLong); - out.writeString(mOperatorAlphaShort); - out.writeString(mOperatorNumeric); - out.writeInt(mIsManualNetworkSelection ? 1 : 0); - } - - public int describeContents() { - return 0; - } - - public static final Parcelable.Creator<ServiceState> CREATOR = new Parcelable.Creator() { - public ServiceState createFromParcel(Parcel in) { - return new ServiceState(in); - } - - public ServiceState[] newArray(int size) { - return new ServiceState[size]; - } - }; - - /** - * Get current servcie state of phone - * - * @see #STATE_IN_SERVICE - * @see #STATE_OUT_OF_SERVICE - * @see #STATE_EMERGENCY_ONLY - * @see #STATE_POWER_OFF - */ - public int getState() { - return mState; - } - - /** - * Get current roaming indicator of phone - * (note: not just decoding from TS 27.007 7.2) - * - * @return true if TS 27.007 7.2 roaming is true - * and ONS is different from SPN - * - */ - public boolean getRoaming() { - return mRoaming; - } - - /** - * Get current registered operator name in long alphanumeric format - * - * In GSM/UMTS, long format can be upto 16 characters long - * - * @return long name of operator, null if unregistered or unknown - */ - public String getOperatorAlphaLong() { - return mOperatorAlphaLong; - } - - /** - * Get current registered operator name in short lphanumeric format - * - * In GSM/UMST, short format can be upto 8 characters long - * - * @return short name of operator, null if unregistered or unknown - */ - public String getOperatorAlphaShort() { - return mOperatorAlphaShort; - } - - /** - * Get current registered operator numeric id - * - * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit - * network code - * - * The country code can be decoded using MccTable.countryCodeForMcc() - * - * @return numeric format of operator, null if unregistered or unknown - */ - public String getOperatorNumeric() { - return mOperatorNumeric; - } - - /** - * Get current network selection mode - * - * @return true if manual mode, false if automatic mode - */ - public boolean getIsManualSelection() { - return mIsManualNetworkSelection; - } - - @Override - public int hashCode() { - return (mState * 0x1234) - + (mRoaming ? 1 : 0) - + (mIsManualNetworkSelection ? 1 : 0) - + ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode()) - + ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode()) - + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode()); - } - - @Override - public boolean equals (Object o) { - ServiceState s; - - try { - s = (ServiceState) o; - } catch (ClassCastException ex) { - return false; - } - - if (o == null) { - return false; - } - - return mState == s.mState - && mRoaming == s.mRoaming - && mIsManualNetworkSelection == s.mIsManualNetworkSelection - && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong) - && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort) - && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric); - } - - @Override - public String toString() { - return mState + " " + (mRoaming ? "roaming" : "home") - + " " + mOperatorAlphaLong - + " " + mOperatorAlphaShort - + " " + mOperatorNumeric - + " " + (mIsManualNetworkSelection ? "(manual)" : ""); - } - - public void setStateOutOfService() { - mState = STATE_OUT_OF_SERVICE; - mRoaming = false; - mOperatorAlphaLong = null; - mOperatorAlphaShort = null; - mOperatorNumeric = null; - mIsManualNetworkSelection = false; - } - - public void setStateOff() { - mState = STATE_POWER_OFF; - mRoaming = false; - mOperatorAlphaLong = null; - mOperatorAlphaShort = null; - mOperatorNumeric = null; - mIsManualNetworkSelection = false; - } - - public void setState(int state) { - mState = state; - } - - public void setRoaming(boolean roaming) { - mRoaming = roaming; - } - - public void setOperatorName(String longName, String shortName, String numeric) { - mOperatorAlphaLong = longName; - mOperatorAlphaShort = shortName; - mOperatorNumeric = numeric; - } - - public void setIsManualSelection(boolean isManual) { - mIsManualNetworkSelection = isManual; - } - - /** - * Test whether two objects hold the same data values or both are null - * - * @param a first obj - * @param b second obj - * @return true if two objects equal or both are null - */ - private static boolean equalsHandlesNulls (Object a, Object b) { - return (a == null) ? (b == null) : a.equals (b); - } - - /** - * Set ServiceState based on intent notifier map - * - * @param m intent notifier map - * @hide - */ - private void setFromNotifierBundle(Bundle m) { - mState = m.getInt("state"); - mRoaming = m.getBoolean("roaming"); - mOperatorAlphaLong = m.getString("operator-alpha-long"); - mOperatorAlphaShort = m.getString("operator-alpha-short"); - mOperatorNumeric = m.getString("operator-numeric"); - mIsManualNetworkSelection = m.getBoolean("manual"); - } - - /** - * Set intent notifier Bundle based on service state - * - * @param m intent notifier Bundle - * @hide - */ - public void fillInNotifierBundle(Bundle m) { - m.putInt("state", mState); - m.putBoolean("roaming", Boolean.valueOf(mRoaming)); - m.putString("operator-alpha-long", mOperatorAlphaLong); - m.putString("operator-alpha-short", mOperatorAlphaShort); - m.putString("operator-numeric", mOperatorNumeric); - m.putBoolean("manual", Boolean.valueOf(mIsManualNetworkSelection)); - } -} diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java deleted file mode 100644 index c5b1b73..0000000 --- a/telephony/java/android/telephony/TelephonyManager.java +++ /dev/null @@ -1,689 +0,0 @@ -/* - * 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 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.os.Bundle; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemProperties; - - -/** - * Provides access to information about the telephony services on - * the device. Applications can use the methods in this class to - * determine telephony services and states, as well as to access some - * types of subscriber information. Applications can also register - * a listener to receive notification of telephony state changes. - * <p> - * You do not instantiate this class directly; instead, you retrieve - * a reference to an instance through - * {@link android.content.Context#getSystemService - * Context.getSystemService(Context.TELEPHONY_SERVICE)}. - * <p> - * Note that acess to some telephony information is - * permission-protected. Your application cannot access the protected - * information unless it has the appropriate permissions declared in - * its manifest file. Where permissions apply, they are noted in the - * the methods through which you access the protected information. - */ -public class TelephonyManager { - private static final String TAG = "TelephonyManager"; - - private Context mContext; - private ITelephonyRegistry mRegistry; - - /** @hide */ - public TelephonyManager(Context context) { - mContext = context; - mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - } - - /** @hide */ - private TelephonyManager() { - } - - private static TelephonyManager sInstance = new TelephonyManager(); - - /** @hide */ - public static TelephonyManager getDefault() { - 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 - // - // - - /** - * Returns the software version number for the device, for example, - * the IMEI/SV for GSM phones. - * - * <p>Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getDeviceSoftwareVersion() { - try { - return getSubscriberInfo().getDeviceSvn(); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Returns the unique device ID, for example,the IMEI for GSM - * phones. - * - * <p>Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getDeviceId() { - try { - return getSubscriberInfo().getDeviceId(); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Returns the current location of the device. - * - * <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION - * ACCESS_COARSE_LOCATION}. - */ - public CellLocation getCellLocation() { - try { - Bundle bundle = getITelephony().getCellLocation(); - return CellLocation.newFromBundle(bundle); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Enables location update notifications. {@link PhoneStateListener#onCellLocationChanged - * PhoneStateListener.onCellLocationChanged} will be called on location updates. - * - * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES - * CONTROL_LOCATION_UPDATES} - * - * @hide - */ - public void enableLocationUpdates() { - try { - getITelephony().enableLocationUpdates(); - } catch (RemoteException ex) { - } - } - - /** - * Disables location update notifications. {@link PhoneStateListener#onCellLocationChanged - * PhoneStateListener.onCellLocationChanged} will be called on location updates. - * - * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES - * CONTROL_LOCATION_UPDATES} - * - * @hide - */ - public void disableLocationUpdates() { - try { - getITelephony().disableLocationUpdates(); - } catch (RemoteException ex) { - } - } - - /** - * 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 { - return getITelephony().getNeighboringCellInfo(); - } catch (RemoteException ex) { - } - return null; - - } - - /** - * No phone module - */ - public static final int PHONE_TYPE_NONE = 0; - - /** - * GSM phone - */ - public static final int PHONE_TYPE_GSM = 1; - - /** - * Returns a constant indicating the device phone type. - * - * @see #PHONE_TYPE_NONE - * @see #PHONE_TYPE_GSM - */ - public int getPhoneType() { - // in the future, we should really check this - return PHONE_TYPE_GSM; - } - - // - // - // Current Network - // - // - - /** - * Returns the alphabetic name of current registered operator. - * <p> - * Availability: Only when user is registered to a network - */ - public String getNetworkOperatorName() { - return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA); - } - - /** - * Returns the numeric name (MCC+MNC) of current registered operator. - * <p> - * Availability: Only when user is registered to a network - */ - public String getNetworkOperator() { - return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC); - } - - /** - * Returns true if the device is considered roaming on the current - * network, for GSM purposes. - * <p> - * Availability: Only when user registered to a network - */ - public boolean isNetworkRoaming() { - return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING)); - } - - /** - * Returns the ISO country code equivilent of the current registered - * operator's MCC (Mobile Country Code). - * <p> - * Availability: Only when user is registered to a network - */ - public String getNetworkCountryIso() { - return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY); - } - - /** Network type is unknown */ - public static final int NETWORK_TYPE_UNKNOWN = 0; - /** Current network is GPRS */ - public static final int NETWORK_TYPE_GPRS = 1; - /** Current network is EDGE */ - public static final int NETWORK_TYPE_EDGE = 2; - /** Current network is UMTS */ - public static final int NETWORK_TYPE_UMTS = 3; - - /** - * 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 - * @see #NETWORK_TYPE_EDGE - * @see #NETWORK_TYPE_UMTS - */ - public int getNetworkType() { - String prop = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE); - if ("GPRS".equals(prop)) { - return NETWORK_TYPE_GPRS; - } - else if ("EDGE".equals(prop)) { - return NETWORK_TYPE_EDGE; - } - else if ("UMTS".equals(prop)) { - return NETWORK_TYPE_UMTS; - } - else { - return NETWORK_TYPE_UNKNOWN; - } - } - - /** - * 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 - // - // - - /** SIM card state: Unknown. Signifies that the SIM is in transition - * between states. For example, when the user inputs the SIM pin - * under PIN_REQUIRED state, a query for sim status returns - * this state before turning to SIM_STATE_READY. */ - public static final int SIM_STATE_UNKNOWN = 0; - /** SIM card state: no SIM card is available in the device */ - public static final int SIM_STATE_ABSENT = 1; - /** SIM card state: Locked: requires the user's SIM PIN to unlock */ - public static final int SIM_STATE_PIN_REQUIRED = 2; - /** SIM card state: Locked: requires the user's SIM PUK to unlock */ - public static final int SIM_STATE_PUK_REQUIRED = 3; - /** SIM card state: Locked: requries a network PIN to unlock */ - public static final int SIM_STATE_NETWORK_LOCKED = 4; - /** SIM card state: Ready */ - public static final int SIM_STATE_READY = 5; - - /** - * Returns a constant indicating the state of the - * device SIM card. - * - * @see #SIM_STATE_UNKNOWN - * @see #SIM_STATE_ABSENT - * @see #SIM_STATE_PIN_REQUIRED - * @see #SIM_STATE_PUK_REQUIRED - * @see #SIM_STATE_NETWORK_LOCKED - * @see #SIM_STATE_READY - */ - public int getSimState() { - String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE); - if ("ABSENT".equals(prop)) { - return SIM_STATE_ABSENT; - } - else if ("PIN_REQUIRED".equals(prop)) { - return SIM_STATE_PIN_REQUIRED; - } - else if ("PUK_REQUIRED".equals(prop)) { - return SIM_STATE_PUK_REQUIRED; - } - else if ("NETWORK_LOCKED".equals(prop)) { - return SIM_STATE_NETWORK_LOCKED; - } - else if ("READY".equals(prop)) { - return SIM_STATE_READY; - } - else { - return SIM_STATE_UNKNOWN; - } - } - - /** - * Returns the MCC+MNC (mobile country code + mobile network code) of the - * provider of the SIM. 5 or 6 decimal digits. - * <p> - * Availability: SIM state must be {@link #SIM_STATE_READY} - * - * @see #getSimState - */ - public String getSimOperator() { - return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC); - } - - /** - * Returns the Service Provider Name (SPN). - * <p> - * Availability: SIM state must be {@link #SIM_STATE_READY} - * - * @see #getSimState - */ - public String getSimOperatorName() { - return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA); - } - - /** - * Returns the ISO country code equivalent for the SIM provider's country code. - */ - public String getSimCountryIso() { - return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ISO_COUNTRY); - } - - /** - * Returns the serial number of the SIM, if applicable. - * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getSimSerialNumber() { - try { - return getSubscriberInfo().getSimSerialNumber(); - } catch (RemoteException ex) { - } - return null; - } - - // - // - // Subscriber Info - // - // - - /** - * Returns the unique subscriber ID, for example, the IMSI for a GSM phone. - * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getSubscriberId() { - try { - return getSubscriberInfo().getSubscriberId(); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Returns the phone number string for line 1, for example, the MSISDN - * for a GSM phone. - * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getLine1Number() { - try { - return getSubscriberInfo().getLine1Number(); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Returns the alphabetic identifier associated with the line 1 number. - * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - * @hide - * nobody seems to call this. - */ - public String getLine1AlphaTag() { - try { - return getSubscriberInfo().getLine1AlphaTag(); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Returns the voice mail number. - * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getVoiceMailNumber() { - try { - return getSubscriberInfo().getVoiceMailNumber(); - } catch (RemoteException ex) { - } - return null; - } - - /** - * Retrieves the alphabetic identifier associated with the voice - * mail number. - * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - */ - public String getVoiceMailAlphaTag() { - try { - return getSubscriberInfo().getVoiceMailAlphaTag(); - } catch (RemoteException ex) { - } - return null; - } - - private IPhoneSubInfo getSubscriberInfo() { - // get it each time because that process crashes a lot - return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo")); - } - - - /** Device call state: No activity. */ - public static final int CALL_STATE_IDLE = 0; - /** Device call state: Ringing. A new call arrived and is - * ringing or waiting. In the latter case, another call is - * already active. */ - public static final int CALL_STATE_RINGING = 1; - /** Device call state: Off-hook. At least one call exists - * that is dialing, active, or on hold, and no calls are ringing - * or waiting. */ - public static final int CALL_STATE_OFFHOOK = 2; - - /** - * Returns a constant indicating the call state (cellular) on the device. - */ - public int getCallState() { - try { - return getITelephony().getCallState(); - } catch (RemoteException ex) { - // the phone process is restarting. - return CALL_STATE_IDLE; - } - } - - /** Data connection activity: No traffic. */ - public static final int DATA_ACTIVITY_NONE = 0x00000000; - /** Data connection activity: Currently receiving IP PPP traffic. */ - public static final int DATA_ACTIVITY_IN = 0x00000001; - /** Data connection activity: Currently sending IP PPP traffic. */ - public static final int DATA_ACTIVITY_OUT = 0x00000002; - /** Data connection activity: Currently both sending and receiving - * IP PPP traffic. */ - public static final int DATA_ACTIVITY_INOUT = DATA_ACTIVITY_IN | DATA_ACTIVITY_OUT; - - /** - * Returns a constant indicating the type of activity on a data connection - * (cellular). - * - * @see #DATA_ACTIVITY_NONE - * @see #DATA_ACTIVITY_IN - * @see #DATA_ACTIVITY_OUT - * @see #DATA_ACTIVITY_INOUT - */ - public int getDataActivity() { - try { - return getITelephony().getDataActivity(); - } catch (RemoteException ex) { - // the phone process is restarting. - return DATA_ACTIVITY_NONE; - } - } - - /** Data connection state: Disconnected. IP traffic not available. */ - public static final int DATA_DISCONNECTED = 0; - /** Data connection state: Currently setting up a data connection. */ - public static final int DATA_CONNECTING = 1; - /** Data connection state: Connected. IP traffic should be available. */ - public static final int DATA_CONNECTED = 2; - /** Data connection state: Suspended. The connection is up, but IP - * traffic is temporarily unavailable. For example, in a 2G network, - * data activity may be suspended when a voice call arrives. */ - public static final int DATA_SUSPENDED = 3; - - /** - * Returns a constant indicating the current data connection state - * (cellular). - * - * @see #DATA_DISCONNECTED - * @see #DATA_CONNECTING - * @see #DATA_CONNECTED - * @see #DATA_SUSPENDED - */ - public int getDataState() { - try { - return getITelephony().getDataState(); - } catch (RemoteException ex) { - // the phone process is restarting. - return DATA_DISCONNECTED; - } - } - - private ITelephony getITelephony() { - return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); - } - - // - // - // PhoneStateListener - // - // - - /** - * Registers a listener object to receive notification of changes - * in specified telephony states. - * <p> - * To register a listener, pass a {@link PhoneStateListener} - * and specify at least one telephony state of interest in - * the events argument. - * - * At registration, and when a specified telephony state - * changes, the telephony manager invokes the appropriate - * callback method on the listener object and passes the - * current (udpated) values. - * <p> - * To unregister a listener, pass the listener object and set the - * events argument to - * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0). - * - * @param listener The {@link PhoneStateListener} object to register - * (or unregister) - * @param events The telephony state(s) of interest to the listener, - * as a bitwise-OR combination of {@link PhoneStateListener} - * LISTEN_ flags. - */ - public void listen(PhoneStateListener listener, int events) { - String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>"; - try { - Boolean notifyNow = (getITelephony() != null); - mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow); - } catch (RemoteException ex) { - // system process dead - } - } -} diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java deleted file mode 100644 index fb9b73a..0000000 --- a/telephony/java/android/telephony/gsm/GsmCellLocation.java +++ /dev/null @@ -1,126 +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 android.telephony.gsm; - -import android.os.Bundle; -import com.android.internal.telephony.Phone; -import android.telephony.CellLocation; - -/** - * Represents the cell location on a GSM phone. - */ -public class GsmCellLocation extends CellLocation -{ - private int mLac; - private int mCid; - - /** - * Empty constructor. Initializes the LAC and CID to -1. - */ - public GsmCellLocation() { - mLac = -1; - mCid = -1; - } - - /** - * Initialize the object from a bundle. - */ - public GsmCellLocation(Bundle bundle) { - mLac = bundle.getInt("lac"); - mCid = bundle.getInt("cid"); - } - - /** - * @return gsm location area code, -1 if unknown, 0xffff max legal value - */ - public int getLac() { - return mLac; - } - - /** - * @return gsm cell id, -1 if unknown, 0xffff max legal value - */ - public int getCid() { - return mCid; - } - - /** - * Invalidate this object. The location area code and the cell id are set to -1. - */ - public void setStateInvalid() { - mLac = -1; - mCid = -1; - } - - /** - * Set the location area code and the cell id. - */ - public void setLacAndCid(int lac, int cid) { - mLac = lac; - mCid = cid; - } - - @Override - public int hashCode() { - return mLac ^ mCid; - } - - @Override - public boolean equals(Object o) { - GsmCellLocation s; - - try { - s = (GsmCellLocation)o; - } catch (ClassCastException ex) { - return false; - } - - if (o == null) { - return false; - } - - return equalsHandlesNulls(mLac, s.mLac) && equalsHandlesNulls(mCid, s.mCid); - } - - @Override - public String toString() { - return "["+ mLac + "," + mCid + "]"; - } - - /** - * Test whether two objects hold the same data values or both are null - * - * @param a first obj - * @param b second obj - * @return true if two objects equal or both are null - */ - private static boolean equalsHandlesNulls(Object a, Object b) { - return (a == null) ? (b == null) : a.equals (b); - } - - /** - * Set intent notifier Bundle based on service state - * - * @param m intent notifier Bundle - */ - public void fillInNotifierBundle(Bundle m) { - m.putInt("lac", mLac); - m.putInt("cid", mCid); - } -} - - diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java deleted file mode 100644 index c63b530..0000000 --- a/telephony/java/android/telephony/gsm/SmsManager.java +++ /dev/null @@ -1,432 +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 android.telephony.gsm; - -import android.app.PendingIntent; -import android.os.RemoteException; -import android.os.IServiceManager; -import android.os.ServiceManager; -import android.os.ServiceManagerNative; -import android.text.TextUtils; - -import com.android.internal.telephony.gsm.EncodeException; -import com.android.internal.telephony.gsm.GsmAlphabet; -import com.android.internal.telephony.gsm.ISms; -import com.android.internal.telephony.gsm.SimConstants; -import com.android.internal.telephony.gsm.SmsRawData; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Manages SMS operations such as sending data, text, and pdu SMS messages. - * Get this object by calling the static method SmsManager.getDefault(). - */ -public final class SmsManager { - private static SmsManager sInstance; - - /** - * Send a text based SMS. - * - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param text the body of the message to send - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is sucessfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK<code> for success, - * or one of these errors: - * <code>RESULT_ERROR_GENERIC_FAILURE</code> - * <code>RESULT_ERROR_RADIO_OFF</code> - * <code>RESULT_ERROR_NULL_PDU</code>. - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applicaitons, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * - * @throws IllegalArgumentException if destinationAddress or text are empty - */ - public void sendTextMessage( - String destinationAddress, String scAddress, String text, - PendingIntent sentIntent, PendingIntent deliveryIntent) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - - if (TextUtils.isEmpty(text)) { - throw new IllegalArgumentException("Invalid message body"); - } - - SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu( - scAddress, destinationAddress, text, (deliveryIntent != null)); - sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent); - } - - /** - * Divide a text message into several messages, none bigger than - * the maximum SMS message size. - * - * @param text the original message. Must not be null. - * @return an <code>ArrayList</code> of strings that, in order, - * comprise the original message - */ - public ArrayList<String> divideMessage(String text) { - int size = text.length(); - int[] params = SmsMessage.calculateLength(text, false); - /* SmsMessage.calculateLength returns an int[4] with: - * int[0] being the number of SMS's required, - * int[1] the number of code units used, - * int[2] is the number of code units remaining until the next message. - * int[3] is the encoding type that should be used for the message. - */ - int messageCount = params[0]; - int encodingType = params[3]; - ArrayList<String> result = new ArrayList<String>(messageCount); - - int start = 0; - int limit; - - if (messageCount > 1) { - 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; - } - - try { - while (start < size) { - int end = GsmAlphabet.findLimitIndex(text, start, limit, encodingType); - result.add(text.substring(start, end)); - start = end; - } - } catch (EncodeException e) { - // ignore it. - } - return result; - } - - /** - * Send a multi-part text based SMS. The callee should have already - * divided the message into correctly sized parts by calling - * <code>divideMessage</code>. - * - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param parts an <code>ArrayList</code> of strings that, in order, - * comprise the original message - * @param sentIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been sent. - * The result code will be <code>Activity.RESULT_OK<code> for success, - * or one of these errors: - * <code>RESULT_ERROR_GENERIC_FAILURE</code> - * <code>RESULT_ERROR_RADIO_OFF</code> - * <code>RESULT_ERROR_NULL_PDU</code>. - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applicaitons, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been delivered - * to the recipient. The raw pdu of the status report is in the - * extended data ("pdu"). - */ - public void sendMultipartTextMessage( - String destinationAddress, String scAddress, ArrayList<String> parts, - ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - if (parts == null || parts.size() < 1) { - throw new IllegalArgumentException("Invalid message body"); - } - - if (parts.size() > 1) { - try { - ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (simISms != null) { - simISms.sendMultipartText(destinationAddress, scAddress, parts, - sentIntents, deliveryIntents); - } - } catch (RemoteException ex) { - // ignore it - } - } else { - PendingIntent sentIntent = null; - PendingIntent deliveryIntent = null; - if (sentIntents != null && sentIntents.size() > 0) { - sentIntent = sentIntents.get(0); - } - if (deliveryIntents != null && deliveryIntents.size() > 0) { - deliveryIntent = deliveryIntents.get(0); - } - sendTextMessage(destinationAddress, scAddress, parts.get(0), - sentIntent, deliveryIntent); - } - } - - /** - * Send a data based SMS to a specific application port. - * - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param destinationPort the port to deliver the message to - * @param data the body of the message to send - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is sucessfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK<code> for success, - * or one of these errors: - * <code>RESULT_ERROR_GENERIC_FAILURE</code> - * <code>RESULT_ERROR_RADIO_OFF</code> - * <code>RESULT_ERROR_NULL_PDU</code>. - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applicaitons, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * - * @throws IllegalArgumentException if destinationAddress or data are empty - */ - public void sendDataMessage( - String destinationAddress, String scAddress, short destinationPort, - byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - - if (data == null || data.length == 0) { - throw new IllegalArgumentException("Invalid message data"); - } - - SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress, - destinationPort, data, (deliveryIntent != null)); - sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent); - } - - /** - * Send a raw SMS PDU. - * - * @param smsc the SMSC to send the message through, or NULL for the - * default SMSC - * @param pdu the raw PDU to send - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is sucessfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK<code> for success, - * or one of these errors: - * <code>RESULT_ERROR_GENERIC_FAILURE</code> - * <code>RESULT_ERROR_RADIO_OFF</code> - * <code>RESULT_ERROR_NULL_PDU</code>. - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applicaitons, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * - */ - private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent, - PendingIntent deliveryIntent) { - try { - ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (simISms != null) { - simISms.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent); - } - } catch (RemoteException ex) { - // ignore it - } - } - - /** - * Get the default instance of the SmsManager - * - * @return the default instance of the SmsManager - */ - public static SmsManager getDefault() { - if (sInstance == null) { - sInstance = new SmsManager(); - } - return sInstance; - } - - private SmsManager() { - // nothing to see here - } - - /** - * Copy a raw SMS PDU to the SIM. - * - * @param smsc the SMSC for this message, or NULL for the default SMSC - * @param pdu the raw PDU to store - * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD, - * STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT) - * @return true for success - * - * {@hide} - */ - public boolean copyMessageToSim(byte[] smsc, byte[] pdu, int status) { - boolean success = false; - - try { - ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (simISms != null) { - success = simISms.copyMessageToSimEf(status, pdu, smsc); - } - } catch (RemoteException ex) { - // ignore it - } - - return success; - } - - /** - * Delete the specified message from the SIM. - * - * @param messageIndex is the record index of the message on SIM - * @return true for success - * - * {@hide} - */ - public boolean - deleteMessageFromSim(int messageIndex) { - boolean success = false; - byte[] pdu = new byte[SimConstants.SMS_RECORD_LENGTH-1]; - Arrays.fill(pdu, (byte)0xff); - - try { - ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (simISms != null) { - success = simISms.updateMessageOnSimEf(messageIndex, - STATUS_ON_SIM_FREE, pdu); - } - } catch (RemoteException ex) { - // ignore it - } - - return success; - } - - /** - * Update the specified message on the SIM. - * - * @param messageIndex record index of message to update - * @param newStatus new message status (STATUS_ON_SIM_READ, - * STATUS_ON_SIM_UNREAD, STATUS_ON_SIM_SENT, - * STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE) - * @param pdu the raw PDU to store - * @return true for success - * - * {@hide} - */ - public boolean updateMessageOnSim(int messageIndex, int newStatus, - byte[] pdu) { - boolean success = false; - - try { - ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (simISms != null) { - success = simISms.updateMessageOnSimEf(messageIndex, newStatus, pdu); - } - } catch (RemoteException ex) { - // ignore it - } - - return success; - } - - - /** - * Retrieves all messages currently stored on SIM. - * - * @return <code>ArrayList</code> of <code>SmsMessage</code> objects - * - * {@hide} - */ - public ArrayList<SmsMessage> getAllMessagesFromSim() { - List<SmsRawData> records = null; - - try { - ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (simISms != null) { - records = simISms.getAllMessagesFromSimEf(); - } - } catch (RemoteException ex) { - // ignore it - } - - return createMessageListFromRawRecords(records); - } - - /** - * Create a list of <code>SmsMessage</code>s from a list of RawSmsData - * records returned by <code>getAllMessagesFromSim()</code> - * - * @param records SMS EF records, returned by - * <code>getAllMessagesFromSim</code> - * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. - */ - private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) { - ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); - if (records != null) { - int count = records.size(); - for (int i = 0; i < count; i++) { - SmsRawData data = (SmsRawData)records.get(i); - // List contains all records, including "free" records (null) - if (data != null) { - SmsMessage sms = - SmsMessage.createFromEfRecord(i+1, data.getBytes()); - messages.add(sms); - } - } - } - return messages; - } - - /** Free space (TS 51.011 10.5.3). */ - static public final int STATUS_ON_SIM_FREE = 0; - - /** Received and read (TS 51.011 10.5.3). */ - static public final int STATUS_ON_SIM_READ = 1; - - /** Received and unread (TS 51.011 10.5.3). */ - static public final int STATUS_ON_SIM_UNREAD = 3; - - /** Stored and sent (TS 51.011 10.5.3). */ - static public final int STATUS_ON_SIM_SENT = 5; - - /** Stored and unsent (TS 51.011 10.5.3). */ - static public final int STATUS_ON_SIM_UNSENT = 7; - - - // SMS send failure result codes - - /** Generic failure cause */ - static public final int RESULT_ERROR_GENERIC_FAILURE = 1; - /** Failed because radio was explicitly turned off */ - static public final int RESULT_ERROR_RADIO_OFF = 2; - /** Failed because no pdu provided */ - static public final int RESULT_ERROR_NULL_PDU = 3; - /** Failed because service is currently unavailable */ - static public final int RESULT_ERROR_NO_SERVICE = 4; -} diff --git a/telephony/java/android/telephony/gsm/SmsMessage.java b/telephony/java/android/telephony/gsm/SmsMessage.java deleted file mode 100644 index f79b0a0..0000000 --- a/telephony/java/android/telephony/gsm/SmsMessage.java +++ /dev/null @@ -1,1598 +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 android.telephony.gsm; - -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; -import com.android.internal.telephony.gsm.SmsHeader; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -class SmsAddress { - // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118 - static final int TON_UNKNOWN = 0; - - static final int TON_INTERNATIONAL = 1; - - static final int TON_NATIONAL = 2; - - static final int TON_NETWORK = 3; - - static final int TON_SUBSCRIBER = 4; - - static final int TON_ALPHANUMERIC = 5; - - static final int TON_APPREVIATED = 6; - - static final int OFFSET_ADDRESS_LENGTH = 0; - - static final int OFFSET_TOA = 1; - - static final int OFFSET_ADDRESS_VALUE = 2; - - int ton; - - String address; - - byte[] origBytes; - - /** - * New SmsAddress from TS 23.040 9.1.2.5 Address Field - * - * @param offset the offset of the Address-Length byte - * @param length the length in bytes rounded up, e.g. "2 + - * (addressLength + 1) / 2" - */ - - SmsAddress(byte[] data, int offset, int length) { - origBytes = new byte[length]; - System.arraycopy(data, offset, origBytes, 0, length); - - // addressLength is the count of semi-octets, not bytes - int addressLength = origBytes[OFFSET_ADDRESS_LENGTH] & 0xff; - - int toa = origBytes[OFFSET_TOA] & 0xff; - ton = 0x7 & (toa >> 4); - - // TOA must have its high bit set - if ((toa & 0x80) != 0x80) { - throw new RuntimeException("Invalid TOA - high bit must be set"); - } - - if (isAlphanumeric()) { - // An alphanumeric address - int countSeptets = addressLength * 4 / 7; - - address = GsmAlphabet.gsm7BitPackedToString(origBytes, - OFFSET_ADDRESS_VALUE, countSeptets); - } else { - // TS 23.040 9.1.2.5 says - // that "the MS shall interpret reserved values as 'Unknown' - // but shall store them exactly as received" - - byte lastByte = origBytes[length - 1]; - - if ((addressLength & 1) == 1) { - // Make sure the final unused BCD digit is 0xf - origBytes[length - 1] |= 0xf0; - } - address = PhoneNumberUtils.calledPartyBCDToString(origBytes, - OFFSET_TOA, length - OFFSET_TOA); - - // And restore origBytes - origBytes[length - 1] = lastByte; - } - } - - public String getAddressString() { - return address; - } - - /** - * Returns true if this is an alphanumeric addres - */ - public boolean isAlphanumeric() { - return ton == TON_ALPHANUMERIC; - } - - public boolean isNetworkSpecific() { - return ton == TON_NETWORK; - } - - /** - * Returns true of this is a valid CPHS voice message waiting indicator - * address - */ - public boolean isCphsVoiceMessageIndicatorAddress() { - // CPHS-style MWI message - // See CPHS 4.7 B.4.2.1 - // - // Basically: - // - // - Originating address should be 4 bytes long and alphanumeric - // - Decode will result with two chars: - // - Char 1 - // 76543210 - // ^ set/clear indicator (0 = clear) - // ^^^ type of indicator (000 = voice) - // ^^^^ must be equal to 0001 - // - Char 2: - // 76543210 - // ^ line number (0 = line 1) - // ^^^^^^^ set to 0 - // - // Remember, since the alpha address is stored in 7-bit compact form, - // the "line number" is really the top bit of the first address value - // byte - - return (origBytes[OFFSET_ADDRESS_LENGTH] & 0xff) == 4 - && isAlphanumeric() && (origBytes[OFFSET_TOA] & 0x0f) == 0; - } - - /** - * Returns true if this is a valid CPHS voice message waiting indicator - * address indicating a "set" of "indicator 1" of type "voice message - * waiting" - */ - public boolean isCphsVoiceMessageSet() { - // 0x11 means "set" "voice message waiting" "indicator 1" - return isCphsVoiceMessageIndicatorAddress() - && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x11; - - } - - /** - * Returns true if this is a valid CPHS voice message waiting indicator - * address indicationg a "clear" of "indicator 1" of type "voice message - * waiting" - */ - public boolean isCphsVoiceMessageClear() { - // 0x10 means "clear" "voice message waiting" "indicator 1" - return isCphsVoiceMessageIndicatorAddress() - && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x10; - - } - - public boolean couldBeEmailGateway() { - // Some carriers seems to send email gateway messages in this form: - // from: an UNKNOWN TON, 3 or 4 digits long, beginning with a 5 - // PID: 0x00, Data coding scheme 0x03 - // So we just attempt to treat any message from an address length <= 4 - // as an email gateway - - return address.length() <= 4; - } - -} - -/** - * A Short Message Service message. - * - */ -public class SmsMessage { - static final String LOG_TAG = "GSM"; - - /** - * SMS Class enumeration. - * See TS 23.038. - * - */ - public enum MessageClass { - UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3; - } - - /** Unknown encoding scheme (see TS 23.038) */ - public static final int ENCODING_UNKNOWN = 0; - /** 7-bit encoding scheme (see TS 23.038) */ - public static final int ENCODING_7BIT = 1; - /** 8-bit encoding scheme (see TS 23.038) */ - public static final int ENCODING_8BIT = 2; - /** 16-bit encoding scheme (see TS 23.038) */ - public static final int ENCODING_16BIT = 3; - - /** The maximum number of payload bytes per message */ - public static final int MAX_USER_DATA_BYTES = 140; - - /** - * The maximum number of payload bytes per message if a user data header - * is present. This assumes the header only contains the - * CONCATENATED_8_BIT_REFERENCE element. - * - * @hide pending API Council approval to extend the public API - */ - 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; - - /** - * The maximum number of payload septets per message if a user data header - * is present. This assumes the header only contains the - * CONCATENATED_8_BIT_REFERENCE element. - */ - public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153; - - /** The address of the SMSC. May be null */ - String scAddress; - - /** The address of the sender */ - SmsAddress originatingAddress; - - /** The message body as a string. May be null if the message isn't text */ - String messageBody; - - String pseudoSubject; - - /** Non-null this is an email gateway message */ - String emailFrom; - - /** Non-null if this is an email gateway message */ - String emailBody; - - boolean isEmail; - - long scTimeMillis; - - /** The raw PDU of the message */ - byte[] mPdu; - - /** The raw bytes for the user data section of the message */ - byte[] userData; - - SmsHeader userDataHeader; - - /** - * TP-Message-Type-Indicator - * 9.2.3 - */ - int mti; - - /** TP-Protocol-Identifier (TP-PID) */ - int protocolIdentifier; - - // TP-Data-Coding-Scheme - // see TS 23.038 - int dataCodingScheme; - - // TP-Reply-Path - // e.g. 23.040 9.2.2.1 - boolean replyPathPresent = false; - - // "Message Marked for Automatic Deletion Group" - // 23.038 Section 4 - boolean automaticDeletion; - - // "Message Waiting Indication Group" - // 23.038 Section 4 - private boolean isMwi; - - private boolean mwiSense; - - private boolean mwiDontStore; - - MessageClass messageClass; - - /** - * Indicates status for messages stored on the SIM. - */ - int statusOnSim = -1; - - /** - * Record index of message in the EF. - */ - int indexOnSim = -1; - - /** TP-Message-Reference - Message Reference of sent message. @hide */ - public int messageRef; - - /** True if Status Report is for SMS-SUBMIT; false for SMS-COMMAND. */ - boolean forSubmit; - - /** The address of the receiver. */ - SmsAddress recipientAddress; - - /** Time when SMS-SUBMIT was delivered from SC to MSE. */ - long dischargeTimeMillis; - - /** - * TP-Status - status of a previously submitted SMS. - * This field applies to SMS-STATUS-REPORT messages. 0 indicates success; - * see TS 23.040, 9.2.3.15 for description of other possible values. - */ - int status; - - /** - * TP-Status - status of a previously submitted SMS. - * This field is true iff the message is a SMS-STATUS-REPORT message. - */ - 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; - - public String toString() { - return "SubmitPdu: encodedScAddress = " - + Arrays.toString(encodedScAddress) - + ", encodedMessage = " - + Arrays.toString(encodedMessage); - } - } - - /** - * Create an SmsMessage from a raw PDU. - */ - public static SmsMessage createFromPdu(byte[] pdu) { - try { - SmsMessage msg = new SmsMessage(); - msg.parsePdu(pdu); - return msg; - } catch (RuntimeException ex) { - Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex); - return null; - } - } - - /** - * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the - * +CMT unsolicited response (PDU mode, of course) - * +CMT: [<alpha>],<length><CR><LF><pdu> - * - * Only public for debugging - * - * {@hide} - */ - /* package */ public static SmsMessage newFromCMT(String[] lines) { - try { - SmsMessage msg = new SmsMessage(); - msg.parsePdu(SimUtils.hexStringToBytes(lines[1])); - return msg; - } catch (RuntimeException ex) { - Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex); - return null; - } - } - - /* pacakge */ static SmsMessage newFromCMTI(String line) { - // the thinking here is not to read the message immediately - // FTA test case - Log.e(LOG_TAG, "newFromCMTI: not yet supported"); - return null; - } - - /** @hide */ - /* package */ public static SmsMessage newFromCDS(String line) { - try { - SmsMessage msg = new SmsMessage(); - msg.parsePdu(SimUtils.hexStringToBytes(line)); - return msg; - } catch (RuntimeException ex) { - Log.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex); - return null; - } - } - - /** - * Create an SmsMessage from an SMS EF record. - * - * @param index Index of SMS record. This should be index in ArrayList - * returned by SmsManager.getAllMessagesFromSim + 1. - * @param data Record data. - * @return An SmsMessage representing the record. - * - * @hide - */ - public static SmsMessage createFromEfRecord(int index, byte[] data) { - try { - SmsMessage msg = new SmsMessage(); - - msg.indexOnSim = index; - - // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT, - // or STORED_UNSENT - // See TS 51.011 10.5.3 - if ((data[0] & 1) == 0) { - Log.w(LOG_TAG, - "SMS parsing failed: Trying to parse a free record"); - return null; - } else { - msg.statusOnSim = data[0] & 0x07; - } - - int size = data.length - 1; - - // Note: Data may include trailing FF's. That's OK; message - // should still parse correctly. - byte[] pdu = new byte[size]; - System.arraycopy(data, 1, pdu, 0, size); - msg.parsePdu(pdu); - return msg; - } catch (RuntimeException ex) { - Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex); - return null; - } - } - - /** - * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the - * length in bytes (not hex chars) less the SMSC header - */ - public static int getTPLayerLengthForPDU(String pdu) { - int len = pdu.length() / 2; - int smscLen = 0; - - smscLen = Integer.parseInt(pdu.substring(0, 2), 16); - - return len - smscLen - 1; - } - - /** - * Calculates the number of SMS's required to encode the message body and - * the number of characters remaining until the next message, given the - * current encoding. - * - * @param messageBody the message to encode - * @param use7bitOnly if true, characters that are not part of the GSM - * alphabet are counted as a single space char. If false, a - * messageBody containing non-GSM alphabet characters is calculated - * for 16-bit encoding. - * @return an int[4] with int[0] being the number of SMS's required, int[1] - * the number of code units used, and int[2] is the number of code - * units remaining until the next message. int[3] is the encoding - * type that should be used for the message. - */ - public static int[] calculateLength(String messageBody, boolean use7bitOnly) { - int ret[] = new int[4]; - - try { - // Try GSM alphabet - int septets = GsmAlphabet.countGsmSeptets(messageBody, !use7bitOnly); - ret[1] = septets; - if (septets > MAX_USER_DATA_SEPTETS) { - ret[0] = (septets / MAX_USER_DATA_SEPTETS_WITH_HEADER) + 1; - 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 UCS-2 - int octets = messageBody.length() * 2; - 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] = (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)/2; - } - ret[3] = ENCODING_16BIT; - } - - return ret; - } - - - /** - * Get an SMS-SUBMIT PDU for a destination address and a message - * - * @param scAddress Service Centre address. Null means use default. - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - * @hide - */ - public static SubmitPdu getSubmitPdu(String scAddress, - String destinationAddress, String message, - boolean statusReportRequested, byte[] header) { - - // Perform null parameter checks. - if (message == null || destinationAddress == null) { - return null; - } - - SubmitPdu ret = new SubmitPdu(); - // MTI = SMS-SUBMIT, UDHI = header != null - byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00)); - ByteArrayOutputStream bo = getSubmitPduHead( - scAddress, destinationAddress, mtiByte, - statusReportRequested, ret); - - try { - // First, try encoding it with the GSM alphabet - - // User Data (and length) - byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header); - - if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) { - // Message too long - return null; - } - - // TP-Data-Coding-Scheme - // Default encoding, uncompressed - bo.write(0x00); - - // (no TP-Validity-Period) - - bo.write(userData, 0, userData.length); - } catch (EncodeException ex) { - byte[] userData, textPart; - // Encoding to the 7-bit alphabet failed. Let's see if we can - // send it as a UCS-2 encoded message - - try { - textPart = message.getBytes("utf-16be"); - } catch (UnsupportedEncodingException uex) { - Log.e(LOG_TAG, - "Implausible UnsupportedEncodingException ", - uex); - return null; - } - - if (header != null) { - userData = new byte[header.length + textPart.length]; - - System.arraycopy(header, 0, userData, 0, header.length); - System.arraycopy(textPart, 0, userData, header.length, textPart.length); - } else { - userData = textPart; - } - - if (userData.length > MAX_USER_DATA_BYTES) { - // Message too long - return null; - } - - // TP-Data-Coding-Scheme - // Class 3, UCS-2 encoding, uncompressed - bo.write(0x0b); - - // (no TP-Validity-Period) - - // TP-UDL - bo.write(userData.length); - - bo.write(userData, 0, userData.length); - } - - ret.encodedMessage = bo.toByteArray(); - return ret; - } - - - /** - * Get an SMS-SUBMIT PDU for a destination address and a message - * - * @param scAddress Service Centre address. Null means use default. - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - */ - public static SubmitPdu getSubmitPdu(String scAddress, - String destinationAddress, String message, - boolean statusReportRequested) { - - return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null); - } - - /** - * Get an SMS-SUBMIT PDU for a data message to a destination address & port - * - * @param scAddress Service Centre address. null == use default - * @param destinationAddress the address of the destination for the message - * @param destinationPort the port to deliver the message to at the - * destination - * @param data the dat for the message - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - */ - public static SubmitPdu getSubmitPdu(String scAddress, - String destinationAddress, short destinationPort, byte[] data, - boolean statusReportRequested) { - if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) { - Log.e(LOG_TAG, "SMS data message may only contain " - + (MAX_USER_DATA_BYTES - 7) + " bytes"); - return null; - } - - SubmitPdu ret = new SubmitPdu(); - ByteArrayOutputStream bo = getSubmitPduHead( - scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT, - // TP-UDHI = true - statusReportRequested, ret); - - // TP-Data-Coding-Scheme - // No class, 8 bit data - bo.write(0x04); - - // (no TP-Validity-Period) - - // User data size - bo.write(data.length + 7); - - // User data header size - bo.write(0x06); // header is 6 octets - - // User data header, indicating the destination port - bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port - // addressing - // header - bo.write(0x04); // each port is 2 octets - bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port - bo.write(destinationPort & 0xFF); // LSB of destination port - bo.write(0x00); // MSB of originating port - bo.write(0x00); // LSB of originating port - - // User data - bo.write(data, 0, data.length); - - ret.encodedMessage = bo.toByteArray(); - return ret; - } - - /** - * Create the beginning of a SUBMIT PDU. This is the part of the - * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu}, - * one of which takes a byte array and the other of which takes a - * <code>String</code>. - * - * @param scAddress Service Centre address. null == use default - * @param destinationAddress the address of the destination for the message - * @param mtiByte - * @param ret <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message - */ - private static ByteArrayOutputStream getSubmitPduHead( - String scAddress, String destinationAddress, byte mtiByte, - boolean statusReportRequested, SubmitPdu ret) { - ByteArrayOutputStream bo = new ByteArrayOutputStream( - MAX_USER_DATA_BYTES + 40); - - // SMSC address with length octet, or 0 - if (scAddress == null) { - ret.encodedScAddress = null; - } else { - ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength( - scAddress); - } - - // TP-Message-Type-Indicator (and friends) - if (statusReportRequested) { - // Set TP-Status-Report-Request bit. - mtiByte |= 0x20; - if (Config.LOGD) Log.d(LOG_TAG, "SMS status report requested"); - } - bo.write(mtiByte); - - // space for TP-Message-Reference - bo.write(0); - - byte[] daBytes; - - daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress); - - // destination address length in BCD digits, ignoring TON byte and pad - // TODO Should be better. - bo.write((daBytes.length - 1) * 2 - - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0)); - - // destination address - bo.write(daBytes, 0, daBytes.length); - - // TP-Protocol-Identifier - bo.write(0); - return bo; - } - - static class PduParser { - byte pdu[]; - - int cur; - - SmsHeader userDataHeader; - - byte[] userData; - - int mUserDataSeptetPadding; - - int mUserDataSize; - - PduParser(String s) { - this(SimUtils.hexStringToBytes(s)); - } - - PduParser(byte[] pdu) { - this.pdu = pdu; - cur = 0; - mUserDataSeptetPadding = 0; - } - - /** - * Parse and return the SC address prepended to SMS messages coming via - * the TS 27.005 / AT interface. Returns null on invalid address - */ - String getSCAddress() { - int len; - String ret; - - // length of SC Address - len = getByte(); - - if (len == 0) { - // no SC address - ret = null; - } else { - // SC address - try { - ret = PhoneNumberUtils - .calledPartyBCDToString(pdu, cur, len); - } catch (RuntimeException tr) { - Log.d(LOG_TAG, "invalid SC address: ", tr); - ret = null; - } - } - - cur += len; - - return ret; - } - - /** - * returns non-sign-extended byte value - */ - int getByte() { - return pdu[cur++] & 0xff; - } - - /** - * Any address except the SC address (eg, originating address) See TS - * 23.040 9.1.2.5 - */ - SmsAddress getAddress() { - SmsAddress ret; - - // "The Address-Length field is an integer representation of - // the number field, i.e. excludes any semi octet containing only - // fill bits." - // The TOA field is not included as part of this - int addressLength = pdu[cur] & 0xff; - int lengthBytes = 2 + (addressLength + 1) / 2; - - ret = new SmsAddress(pdu, cur, lengthBytes); - - cur += lengthBytes; - - return ret; - } - - /** - * Parses an SC timestamp and returns a currentTimeMillis()-style - * timestamp - */ - - long getSCTimestampMillis() { - // TP-Service-Centre-Time-Stamp - int year = SimUtils.bcdByteToInt(pdu[cur++]); - int month = SimUtils.bcdByteToInt(pdu[cur++]); - int day = SimUtils.bcdByteToInt(pdu[cur++]); - int hour = SimUtils.bcdByteToInt(pdu[cur++]); - int minute = SimUtils.bcdByteToInt(pdu[cur++]); - int second = SimUtils.bcdByteToInt(pdu[cur++]); - - // For the timezone, the most significant bit of the - // least signficant nibble is the sign byte - // (meaning the max range of this field is 79 quarter-hours, - // which is more than enough) - - byte tzByte = pdu[cur++]; - - // Mask out sign bit. - int timezoneOffset = SimUtils - .bcdByteToInt((byte) (tzByte & (~0x08))); - - timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset - : -timezoneOffset; - - Time time = new Time(Time.TIMEZONE_UTC); - - // It's 2006. Should I really support years < 2000? - time.year = year >= 90 ? year + 1900 : year + 2000; - time.month = month - 1; - time.monthDay = day; - time.hour = hour; - time.minute = minute; - time.second = second; - - // Timezone offset is in quarter hours. - return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000); - } - - /** - * Pulls the user data out of the PDU, and separates the payload from - * the header if there is one. - * - * @param hasUserDataHeader true if there is a user data header - * @param dataInSeptets true if the data payload is in septets instead - * of octets - * @return the number of septets or octets in the user data payload - */ - int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets) - { - int offset = cur; - int userDataLength = pdu[offset++] & 0xff; - int headerSeptets = 0; - - if (hasUserDataHeader) { - int userDataHeaderLength = pdu[offset++] & 0xff; - - byte[] udh = new byte[userDataHeaderLength]; - System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength); - userDataHeader = SmsHeader.parse(udh); - offset += userDataHeaderLength; - - int headerBits = (userDataHeaderLength + 1) * 8; - headerSeptets = headerBits / 7; - headerSeptets += (headerBits % 7) > 0 ? 1 : 0; - mUserDataSeptetPadding = (headerSeptets * 7) - headerBits; - } - - /* - * Here we just create the user data length to be the remainder of - * the pdu minus the user data hearder. This is because the count - * could mean the number of uncompressed sepets if the userdata is - * encoded in 7-bit. - */ - userData = new byte[pdu.length - offset]; - System.arraycopy(pdu, offset, userData, 0, userData.length); - cur = offset; - - if (dataInSeptets) { - // Return the number of septets - 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; - } - } - - /** - * Returns the user data payload, not including the headers - * - * @return the user data payload, not including the headers - */ - byte[] getUserData() { - return userData; - } - - /** - * Returns the number of padding bits at the begining of the user data - * array before the start of the septets. - * - * @return the number of padding bits at the begining of the user data - * array before the start of the septets - */ - int getUserDataSeptetPadding() { - return mUserDataSeptetPadding; - } - - /** - * Returns an object representing the user data headers - * - * @return an object representing the user data headers - * - * {@hide} - */ - SmsHeader getUserDataHeader() { - return userDataHeader; - } - -/* - XXX Not sure what this one is supposed to be doing, and no one is using - it. - String getUserDataGSM8bit() { - // System.out.println("remainder of pud:" + - // HexDump.dumpHexString(pdu, cur, pdu.length - cur)); - int count = pdu[cur++] & 0xff; - int size = pdu[cur++]; - - // skip over header for now - cur += size; - - if (pdu[cur - 1] == 0x01) { - int tid = pdu[cur++] & 0xff; - int type = pdu[cur++] & 0xff; - - size = pdu[cur++] & 0xff; - - int i = cur; - - while (pdu[i++] != '\0') { - } - - int length = i - cur; - String mimeType = new String(pdu, cur, length); - - cur += length; - - if (false) { - System.out.println("tid = 0x" + HexDump.toHexString(tid)); - System.out.println("type = 0x" + HexDump.toHexString(type)); - System.out.println("header size = " + size); - System.out.println("mimeType = " + mimeType); - System.out.println("remainder of header:" + - HexDump.dumpHexString(pdu, cur, (size - mimeType.length()))); - } - - cur += size - mimeType.length(); - - // System.out.println("data count = " + count + " cur = " + cur - // + " :" + HexDump.dumpHexString(pdu, cur, pdu.length - cur)); - - MMSMessage msg = MMSMessage.parseEncoding(mContext, pdu, cur, - pdu.length - cur); - } else { - System.out.println(new String(pdu, cur, pdu.length - cur - 1)); - } - - return SimUtils.bytesToHexString(pdu); - } -*/ - - /** - * Interprets the user data payload as pack GSM 7bit characters, and - * decodes them into a String. - * - * @param septetCount the number of septets in the user data payload - * @return a String with the decoded characters - */ - String getUserDataGSM7Bit(int septetCount) { - String ret; - - ret = GsmAlphabet.gsm7BitPackedToString(pdu, cur, septetCount, - mUserDataSeptetPadding); - - cur += (septetCount * 7) / 8; - - return ret; - } - - /** - * Interprets the user data payload as UCS2 characters, and - * decodes them into a String. - * - * @param byteCount the number of bytes in the user data payload - * @return a String with the decoded characters - */ - String getUserDataUCS2(int byteCount) { - String ret; - - try { - ret = new String(pdu, cur, byteCount, "utf-16"); - } catch (UnsupportedEncodingException ex) { - ret = ""; - Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex); - } - - cur += byteCount; - return ret; - } - - boolean moreDataPresent() { - return (pdu.length > cur); - } - } - - /** - * Returns the address of the SMS service center that relayed this message - * or null if there is none. - */ - public String getServiceCenterAddress() { - return scAddress; - } - - /** - * Returns the originating address (sender) of this SMS message in String - * form or null if unavailable - */ - public String getOriginatingAddress() { - if (originatingAddress == null) { - return null; - } - - return originatingAddress.getAddressString(); - } - - /** - * Returns the originating address, or email from address if this message - * was from an email gateway. Returns null if originating address - * unavailable. - */ - public String getDisplayOriginatingAddress() { - if (isEmail) { - return emailFrom; - } else { - return getOriginatingAddress(); - } - } - - /** - * Returns the message body as a String, if it exists and is text based. - * @return message body is there is one, otherwise null - */ - public String getMessageBody() { - return messageBody; - } - - /** - * Returns the class of this message. - */ - public MessageClass getMessageClass() { - return messageClass; - } - - /** - * Returns the message body, or email message body if this message was from - * an email gateway. Returns null if message body unavailable. - */ - public String getDisplayMessageBody() { - if (isEmail) { - return emailBody; - } else { - return getMessageBody(); - } - } - - /** - * Unofficial convention of a subject line enclosed in parens empty string - * if not present - */ - public String getPseudoSubject() { - return pseudoSubject == null ? "" : pseudoSubject; - } - - /** - * Returns the service centre timestamp in currentTimeMillis() format - */ - public long getTimestampMillis() { - return scTimeMillis; - } - - /** - * Returns true if message is an email. - * - * @return true if this message came through an email gateway and email - * sender / subject / parsed body are available - */ - public boolean isEmail() { - return isEmail; - } - - /** - * @return if isEmail() is true, body of the email sent through the gateway. - * null otherwise - */ - public String getEmailBody() { - return emailBody; - } - - /** - * @return if isEmail() is true, email from address of email sent through - * the gateway. null otherwise - */ - public String getEmailFrom() { - return emailFrom; - } - - /** - * Get protocol identifier. - */ - public int getProtocolIdentifier() { - return protocolIdentifier; - } - - /** - * See TS 23.040 9.2.3.9 returns true if this is a "replace short message" - * SMS - */ - public boolean isReplace() { - return (protocolIdentifier & 0xc0) == 0x40 - && (protocolIdentifier & 0x3f) > 0 - && (protocolIdentifier & 0x3f) < 8; - } - - /** - * Returns true for CPHS MWI toggle message. - * - * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section - * B.4.2 - */ - public boolean isCphsMwiMessage() { - return originatingAddress.isCphsVoiceMessageClear() - || originatingAddress.isCphsVoiceMessageSet(); - } - - /** - * returns true if this message is a CPHS voicemail / message waiting - * indicator (MWI) clear message - */ - public boolean isMWIClearMessage() { - if (isMwi && (mwiSense == false)) { - return true; - } - - return originatingAddress != null - && originatingAddress.isCphsVoiceMessageClear(); - } - - /** - * returns true if this message is a CPHS voicemail / message waiting - * indicator (MWI) set message - */ - public boolean isMWISetMessage() { - if (isMwi && (mwiSense == true)) { - return true; - } - - return originatingAddress != null - && originatingAddress.isCphsVoiceMessageSet(); - } - - /** - * returns true if this message is a "Message Waiting Indication Group: - * Discard Message" notification and should not be stored. - */ - public boolean isMwiDontStore() { - if (isMwi && mwiDontStore) { - return true; - } - - if (isCphsMwiMessage()) { - // See CPHS 4.2 Section B.4.2.1 - // If the user data is a single space char, do not store - // the message. Otherwise, store and display as usual - if (" ".equals(getMessageBody())) { - ; - } - return true; - } - - return false; - } - - /** - * returns the user data section minus the user data header if one was - * present. - */ - public byte[] getUserData() { - return userData; - } - - /** - * Returns an object representing the user data header - * - * @return an object representing the user data header - * - * {@hide} - */ - public SmsHeader getUserDataHeader() { - return userDataHeader; - } - - /** - * Returns the raw PDU for the message. - * - * @return the raw PDU for the message. - */ - public byte[] getPdu() { - return mPdu; - } - - /** - * Returns the status of the message on the SIM (read, unread, sent, unsent). - * - * @return the status of the message on the SIM. These are: - * SmsManager.STATUS_ON_SIM_FREE - * SmsManager.STATUS_ON_SIM_READ - * SmsManager.STATUS_ON_SIM_UNREAD - * SmsManager.STATUS_ON_SIM_SEND - * SmsManager.STATUS_ON_SIM_UNSENT - */ - public int getStatusOnSim() { - return statusOnSim; - } - - /** - * Returns the record index of the message on the SIM (1-based index). - * @return the record index of the message on the SIM, or -1 if this - * SmsMessage was not created from a SIM SMS EF record. - */ - public int getIndexOnSim() { - return indexOnSim; - } - - /** - * For an SMS-STATUS-REPORT message, this returns the status field from - * the status report. This field indicates the status of a previousely - * submitted SMS, if requested. See TS 23.040, 9.2.3.15 TP-Status for a - * description of values. - * - * @return 0 indicates the previously sent message was received. - * See TS 23.040, 9.9.2.3.15 for a description of other possible - * values. - */ - public int getStatus() { - return status; - } - - /** - * Return true iff the message is a SMS-STATUS-REPORT message. - */ - public boolean isStatusReportMessage() { - return isStatusReportMessage; - } - - /** - * Returns true iff the <code>TP-Reply-Path</code> bit is set in - * this message. - */ - public boolean isReplyPathPresent() { - return replyPathPresent; - } - - /** - * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] - * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format: - * ME/TA converts each octet of TP data unit into two IRA character long - * hexad number (e.g. octet with integer value 42 is presented to TE as two - * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast, - * something else... - */ - private void parsePdu(byte[] pdu) { - mPdu = pdu; - // Log.d(LOG_TAG, "raw sms mesage:"); - // Log.d(LOG_TAG, s); - - PduParser p = new PduParser(pdu); - - scAddress = p.getSCAddress(); - - if (scAddress != null) { - if (Config.LOGD) Log.d(LOG_TAG, "SMS SC address: " + scAddress); - } - - // TODO(mkf) support reply path, user data header indicator - - // TP-Message-Type-Indicator - // 9.2.3 - int firstByte = p.getByte(); - - mti = firstByte & 0x3; - switch (mti) { - // TP-Message-Type-Indicator - // 9.2.3 - case 0: - parseSmsDeliver(p, firstByte); - break; - case 2: - parseSmsStatusReport(p, firstByte); - break; - default: - // TODO(mkf) the rest of these - throw new RuntimeException("Unsupported message type"); - } - } - - /** - * Parses a SMS-STATUS-REPORT message. - * - * @param p A PduParser, cued past the first byte. - * @param firstByte The first byte of the PDU, which contains MTI, etc. - */ - private void parseSmsStatusReport(PduParser p, int firstByte) { - isStatusReportMessage = true; - - // TP-Status-Report-Qualifier bit == 0 for SUBMIT - forSubmit = (firstByte & 0x20) == 0x00; - // TP-Message-Reference - messageRef = p.getByte(); - // TP-Recipient-Address - recipientAddress = p.getAddress(); - // TP-Service-Centre-Time-Stamp - scTimeMillis = p.getSCTimestampMillis(); - // TP-Discharge-Time - dischargeTimeMillis = p.getSCTimestampMillis(); - // TP-Status - status = p.getByte(); - - // The following are optional fields that may or may not be present. - if (p.moreDataPresent()) { - // TP-Parameter-Indicator - int extraParams = p.getByte(); - int moreExtraParams = extraParams; - while ((moreExtraParams & 0x80) != 0) { - // We only know how to parse a few extra parameters, all - // indicated in the first TP-PI octet, so skip over any - // additional TP-PI octets. - moreExtraParams = p.getByte(); - } - // TP-Protocol-Identifier - if ((extraParams & 0x01) != 0) { - protocolIdentifier = p.getByte(); - } - // TP-Data-Coding-Scheme - if ((extraParams & 0x02) != 0) { - dataCodingScheme = p.getByte(); - } - // TP-User-Data-Length (implies existence of TP-User-Data) - if ((extraParams & 0x04) != 0) { - boolean hasUserDataHeader = (firstByte & 0x40) == 0x40; - parseUserData(p, hasUserDataHeader); - } - } - } - - private void parseSmsDeliver(PduParser p, int firstByte) { - replyPathPresent = (firstByte & 0x80) == 0x80; - - originatingAddress = p.getAddress(); - - if (originatingAddress != null) { - if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: " - + originatingAddress.address); - } - - // TP-Protocol-Identifier (TP-PID) - // TS 23.040 9.2.3.9 - protocolIdentifier = p.getByte(); - - // TP-Data-Coding-Scheme - // see TS 23.038 - dataCodingScheme = p.getByte(); - - if (Config.LOGV) { - Log.v(LOG_TAG, "SMS TP-PID:" + protocolIdentifier - + " data coding scheme: " + dataCodingScheme); - } - - scTimeMillis = p.getSCTimestampMillis(); - - if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis); - - boolean hasUserDataHeader = (firstByte & 0x40) == 0x40; - - parseUserData(p, hasUserDataHeader); - } - - /** - * Parses the User Data of an SMS. - * - * @param p The current PduParser. - * @param hasUserDataHeader Indicates whether a header is present in the - * User Data. - */ - private void parseUserData(PduParser p, boolean hasUserDataHeader) { - boolean hasMessageClass = false; - boolean userDataCompressed = false; - - int encodingType = ENCODING_UNKNOWN; - - // Look up the data encoding scheme - if ((dataCodingScheme & 0x80) == 0) { - // Bits 7..4 == 0xxx - automaticDeletion = (0 != (dataCodingScheme & 0x40)); - userDataCompressed = (0 != (dataCodingScheme & 0x20)); - hasMessageClass = (0 != (dataCodingScheme & 0x10)); - - if (userDataCompressed) { - Log.w(LOG_TAG, "4 - Unsupported SMS data coding scheme " - + "(compression) " + (dataCodingScheme & 0xff)); - } else { - switch ((dataCodingScheme >> 2) & 0x3) { - case 0: // GSM 7 bit default alphabet - encodingType = ENCODING_7BIT; - break; - - case 2: // UCS 2 (16bit) - encodingType = ENCODING_16BIT; - break; - - case 1: // 8 bit data - case 3: // reserved - Log.w(LOG_TAG, "1 - Unsupported SMS data coding scheme " - + (dataCodingScheme & 0xff)); - encodingType = ENCODING_8BIT; - break; - } - } - } else if ((dataCodingScheme & 0xf0) == 0xf0) { - automaticDeletion = false; - hasMessageClass = true; - userDataCompressed = false; - - if (0 == (dataCodingScheme & 0x04)) { - // GSM 7 bit default alphabet - encodingType = ENCODING_7BIT; - } else { - // 8 bit data - encodingType = ENCODING_8BIT; - } - } else if ((dataCodingScheme & 0xF0) == 0xC0 - || (dataCodingScheme & 0xF0) == 0xD0 - || (dataCodingScheme & 0xF0) == 0xE0) { - // 3GPP TS 23.038 V7.0.0 (2006-03) section 4 - - // 0xC0 == 7 bit, don't store - // 0xD0 == 7 bit, store - // 0xE0 == UCS-2, store - - if ((dataCodingScheme & 0xF0) == 0xE0) { - encodingType = ENCODING_16BIT; - } else { - encodingType = ENCODING_7BIT; - } - - userDataCompressed = false; - boolean active = ((dataCodingScheme & 0x08) == 0x08); - - // bit 0x04 reserved - - if ((dataCodingScheme & 0x03) == 0x00) { - isMwi = true; - mwiSense = active; - mwiDontStore = ((dataCodingScheme & 0xF0) == 0xC0); - } else { - isMwi = false; - - Log.w(LOG_TAG, "MWI for fax, email, or other " - + (dataCodingScheme & 0xff)); - } - } else { - Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme " - + (dataCodingScheme & 0xff)); - } - - // set both the user data and the user data header. - int count = p.constructUserData(hasUserDataHeader, - encodingType == ENCODING_7BIT); - this.userData = p.getUserData(); - this.userDataHeader = p.getUserDataHeader(); - - switch (encodingType) { - case ENCODING_UNKNOWN: - case ENCODING_8BIT: - messageBody = null; - break; - - case ENCODING_7BIT: - messageBody = p.getUserDataGSM7Bit(count); - break; - - case ENCODING_16BIT: - messageBody = p.getUserDataUCS2(count); - break; - } - - if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'"); - - if (messageBody != null) { - parseMessageBody(); - } - - if (!hasMessageClass) { - messageClass = MessageClass.UNKNOWN; - } else { - switch (dataCodingScheme & 0x3) { - case 0: - messageClass = MessageClass.CLASS_0; - break; - case 1: - messageClass = MessageClass.CLASS_1; - break; - case 2: - messageClass = MessageClass.CLASS_2; - break; - case 3: - messageClass = MessageClass.CLASS_3; - break; - } - } - } - - private void parseMessageBody() { - if (originatingAddress.couldBeEmailGateway()) { - extractEmailAddressFromMessageBody(); - } - } - - /** - * Try to parse this message as an email gateway message -> Neither - * of the standard ways are currently supported: There are two ways - * specified in TS 23.040 Section 3.8 (not supported via this mechanism) - - * SMS message "may have its TP-PID set for internet electronic mail - MT - * SMS format: [<from-address><space>]<message> - "Depending on the - * nature of the gateway, the destination/origination address is either - * derived from the content of the SMS TP-OA or TP-DA field, or the - * TP-OA/TP-DA field contains a generic gateway address and the to/from - * address is added at the beginning as shown above." - multiple addreses - * separated by commas, no spaces - subject field delimited by '()' or '##' - * and '#' Section 9.2.3.24.11 - */ - private void extractEmailAddressFromMessageBody() { - - /* - * a little guesswork here. I haven't found doc for this. - * the format could be either - * - * 1. [x@y][ ]/[subject][ ]/[body] - * -or- - * 2. [x@y][ ]/[body] - */ - int slash = 0, slash2 = 0, atSymbol = 0; - - try { - slash = messageBody.indexOf(" /"); - if (slash == -1) { - return; - } - - atSymbol = messageBody.indexOf('@'); - if (atSymbol == -1 || atSymbol > slash) { - return; - } - - emailFrom = messageBody.substring(0, slash); - - slash2 = messageBody.indexOf(" /", slash + 2); - - if (slash2 == -1) { - pseudoSubject = null; - emailBody = messageBody.substring(slash + 2); - } else { - pseudoSubject = messageBody.substring(slash + 2, slash2); - emailBody = messageBody.substring(slash2 + 2); - } - - isEmail = true; - } catch (Exception ex) { - Log.w(LOG_TAG, - "extractEmailAddressFromMessageBody: exception slash=" - + slash + ", atSymbol=" + atSymbol + ", slash2=" - + slash2, ex); - } - } - -} diff --git a/telephony/java/android/telephony/gsm/package.html b/telephony/java/android/telephony/gsm/package.html deleted file mode 100644 index 9860417..0000000 --- a/telephony/java/android/telephony/gsm/package.html +++ /dev/null @@ -1,6 +0,0 @@ -<HTML> -<BODY> -Provides APIs for utilizing GSM-specific telephony features, such as -text/data/PDU SMS messages. -</BODY> -</HTML>
\ No newline at end of file diff --git a/telephony/java/android/telephony/package.html b/telephony/java/android/telephony/package.html deleted file mode 100644 index aee4a6f..0000000 --- a/telephony/java/android/telephony/package.html +++ /dev/null @@ -1,7 +0,0 @@ -<HTML> -<BODY> -Provides APIs for monitoring the basic phone information, such as -the network type and connection state, plus utilities -for manipulating phone number strings. -</BODY> -</HTML>
\ No newline at end of file |