| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.telephony.gsm; |
| |
| import android.telephony.PhoneNumberUtils; |
| |
| import com.android.internal.telephony.GsmAlphabet; |
| import com.android.internal.telephony.SmsAddress; |
| |
| public class GsmSmsAddress extends SmsAddress { |
| |
| static final int OFFSET_ADDRESS_LENGTH = 0; |
| |
| static final int OFFSET_TOA = 1; |
| |
| static final int OFFSET_ADDRESS_VALUE = 2; |
| |
| /** |
| * New GsmSmsAddress 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" |
| */ |
| |
| public GsmSmsAddress(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 address |
| */ |
| 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 indicating 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; |
| |
| } |
| } |