Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83917db0 authored by Tammo Spalink's avatar Tammo Spalink
Browse files

Initial code for cdma sms encode and decode, in java, with simple tests.

(direct cherry-pick of master 42/42/8)
parent 19bd253e
Loading
Loading
Loading
Loading
+116 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.util;

/**
 * An object that provides bitwise incremental read access to a byte array.
 *
 * This is useful, for example, when accessing a series of fields that
 * may not be aligned on byte boundaries.
 *
 * NOTE -- This class is not threadsafe.
 */
public class BitwiseInputStream {

    // The byte array being read from.
    private byte[] mBuf;

    // The current position offset, in bits, from the msb in byte 0.
    private int mPos;

    // The last valid bit offset.
    private int mEnd;

    /**
     * An exception to report access problems.
     */
    public static class AccessException extends Exception {
        public AccessException(String s) {
            super("BitwiseInputStream access failed: " + s);
        }
    }

    /**
     * Create object from byte array.
     *
     * @param buf a byte array containing data
     */
    public BitwiseInputStream(byte buf[]) {
        mBuf = buf;
        mEnd = buf.length * 8;
        mPos = 0;
    }

    /**
     * Return the number of bit still available for reading.
     */
    public int available() {
        return mEnd - mPos;
    }

    /**
     * Read some data and increment the current position.
     *
     * @param bits the amount of data to read (gte 0, lte 8)
     *
     * @return byte of read data (possibly partially filled, from lsb)
     */
    public byte read(int bits) throws AccessException {
        int index = mPos / 8;
        int offset = 16 - (mPos % 8) - bits;
        if ((bits < 0) || (bits > 8) || ((mPos + bits) > mEnd)) {
            throw new AccessException("illegal read " +
                "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")");
        }
        int data = (mBuf[index] & 0xFF) << 8;
        if (offset < 8) data |= (mBuf[index + 1] & 0xFF);
        data >>>= offset;
        data &= (-1 >>> (32 - bits));
        mPos += bits;
        return (byte)data;
    }

    /**
     * Read data in bulk into a byte array and increment the current position.
     *
     * @param bits the amount of data to read
     *
     * @return newly allocated byte array of read data
     */
    public byte[] readByteArray(int bits) throws AccessException {
        int bytes = (bits / 8) + ((bits % 8) > 0 ? 1 : 0);
        byte[] arr = new byte[bytes];
        for (int i = 0; i < bytes; i++) {
            int increment = Math.min(8, bits - (i * 8));
            arr[i] = (byte)(read(increment) << (8 - increment));
        }
        return arr;
    }

    /**
     * Increment the current position and ignore contained data.
     *
     * @param bits the amount by which to increment the position
     */
    public void skip(int bits) throws AccessException {
        if ((mPos + bits) > mEnd) {
            throw new AccessException("illegal skip " +
                "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")");
        }
        mPos += bits;
    }
}
+126 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.util;

/**
 * An object that rovides bitwise incremental write access to a byte array.
 *
 * This is useful, for example, when writing a series of fields that
 * may not be aligned on byte boundaries.
 *
 * NOTE -- This class is not threadsafe.
 */
public class BitwiseOutputStream {

    // The byte array being written to, which will be grown as needed.
    private byte[] mBuf;

    // The current position offset, in bits, from the msb in byte 0.
    private int mPos;

    // The last bit offset, given the current buf length.
    private int mEnd;

    /**
     * An exception to report access problems.
     */
    public static class AccessException extends Exception {
        public AccessException(String s) {
            super("BitwiseOutputStream access failed: " + s);
        }
    }

    /**
     * Create object from hint at desired size.
     *
     * @param startingLength initial internal byte array length in bytes
     */
    public BitwiseOutputStream(int startingLength) {
        mBuf = new byte[startingLength];
        mEnd = startingLength * 8;
        mPos = 0;
    }

    /**
     * Return byte array containing accumulated data, sized to just fit.
     *
     * @return newly allocated byte array
     */
    public byte[] toByteArray() {
        int len = (mPos / 8) + ((mPos % 8) > 0 ? 1 : 0);
        byte[] newBuf = new byte[len];
        System.arraycopy(mBuf, 0, newBuf, 0, len);
        return newBuf;
    }

    /**
     * Allocate a new internal buffer, if needed.
     *
     * @param bits additional bits to be accommodated
     */
    private void possExpand(int bits) {
        if ((mPos + bits) < mEnd) return;
        byte[] newBuf = new byte[((mPos + bits) * 2) / 8];
        System.arraycopy(mBuf, 0, newBuf, 0, mEnd / 8);
        mBuf = newBuf;
    }

    /**
     * Write some data and increment the current position.
     *
     * @param bits the amount of data to write (gte 0, lte 8)
     * @param data to write, will be masked to expose only bits param from lsb
     */
    public void write(int bits, int data) throws AccessException {
        if ((bits < 0) || (bits > 8)) {
            throw new AccessException("illegal write (" + bits + " bits)");
        }
        possExpand(bits);
        data &= (-1 >>> (32 - bits));
        int index = mPos / 8;
        int offset = 16 - (mPos % 8) - bits;
        data <<= offset;
        mPos += bits;
        mBuf[index] |= (data >>> 8);
        if (offset < 8) mBuf[index + 1] |= (data & 0xFF);
    }

    /**
     * Write data in bulk from a byte array and increment the current position.
     *
     * @param bits the amount of data to write
     * @param arr the byte array containing data to be written
     */
    public void writeByteArray(int bits, byte[] arr) throws AccessException {
        for (int i = 0; i < arr.length; i++) {
            int increment = Math.min(8, bits - (i * 8));
            if (increment > 0) {
                write(increment, (byte)(arr[i] >>> (8 - increment)));
            }
        }
    }

    /**
     * Increment the current position, implicitly writing zeros.
     *
     * @param bits the amount by which to increment the position
     */
    public void skip(int bits) {
        possExpand(bits);
        mPos += bits;
    }
}
+0 −14
Original line number Diff line number Diff line
@@ -20,20 +20,7 @@ import android.util.Log;
import com.android.internal.telephony.SmsHeader;
import java.util.Arrays;

import static android.telephony.SmsMessage.ENCODING_7BIT;
import static android.telephony.SmsMessage.ENCODING_16BIT;
import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
import static android.telephony.SmsMessage.MessageClass;
import static com.android.internal.telephony.SmsAddress.TON_ABBREVIATED;
import static com.android.internal.telephony.SmsAddress.TON_ALPHANUMERIC;
import static com.android.internal.telephony.SmsAddress.TON_INTERNATIONAL;
import static com.android.internal.telephony.SmsAddress.TON_NATIONAL;
import static com.android.internal.telephony.SmsAddress.TON_NETWORK;
import static com.android.internal.telephony.SmsAddress.TON_SUBSCRIBER;
import static com.android.internal.telephony.SmsAddress.TON_UNKNOWN;

/**
 * Base class declaring the specific methods and members for SmsMessage.
@@ -385,4 +372,3 @@ public abstract class SmsMessageBase {
    }

}
+22 −40
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.cdma.sms.BearerData;
import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
import com.android.internal.telephony.cdma.sms.SmsDataCoding;
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
import com.android.internal.telephony.cdma.sms.UserData;

@@ -50,23 +49,6 @@ import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
import static android.telephony.SmsMessage.MessageClass;
import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_NONE;
import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_TEMPORARY;
import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_PERMANENT;
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_DELIVER;
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_SUBMIT;
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_CANCELLATION;
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_DELIVERY_ACK;
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_USER_ACK;
import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_READ_ACK;
import static com.android.internal.telephony.cdma.sms.CdmaSmsAddress.SMS_ADDRESS_MAX;
import static com.android.internal.telephony.cdma.sms.CdmaSmsAddress.SMS_SUBADDRESS_MAX;
import static com.android.internal.telephony.cdma.sms.SmsEnvelope.SMS_BEARER_DATA_MAX;
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_7BIT_ASCII;
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_IA5;
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_OCTET;
import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_UNICODE_16;

/**
 * A Short Message Service message.
@@ -186,7 +168,7 @@ public class SmsMessage extends SmsMessageBase {

        // ignore subaddress
        p.readInt(); //p_cur->sSubAddress.subaddressType
        p.readByte(); //p_cur->sSubAddress.odd
        p.readInt(); //p_cur->sSubAddress.odd
        count = p.readByte(); //p_cur->sSubAddress.number_of_digits
        //p_cur->sSubAddress.digits[digitCount] :
        for (int index=0; index < count; index++) {
@@ -309,15 +291,15 @@ public class SmsMessage extends SmsMessageBase {
            int septetCount = GsmAlphabet.countGsmSeptets(message, true);
            // User Data (and length)

            uData.userData = message.getBytes();
            uData.payload = message.getBytes();

            if (uData.userData.length > MAX_USER_DATA_SEPTETS) {
            if (uData.payload.length > MAX_USER_DATA_SEPTETS) {
                // Message too long
                return null;
            }

            // desired TP-Data-Coding-Scheme
            uData.userDataEncoding = UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
            uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;

            // paddingBits not needed for UD_ENCODING_GSM_7BIT_ALPHABET

@@ -341,15 +323,15 @@ public class SmsMessage extends SmsMessageBase {
                return null;
            }

            uData.userData = textPart;
            uData.payload = textPart;

            if (uData.userData.length > MAX_USER_DATA_BYTES) {
            if (uData.payload.length > MAX_USER_DATA_BYTES) {
                // Message too long
                return null;
            }

            // TP-Data-Coding-Scheme
            uData.userDataEncoding = UserData.UD_ENCODING_UNICODE_16;
            uData.msgEncoding = UserData.ENCODING_UNICODE_16;

            // sms header
            if(headerData != null) {
@@ -425,8 +407,8 @@ public class SmsMessage extends SmsMessageBase {

        // TP-Data-Coding-Scheme
        // No class, 8 bit data
        uData.userDataEncoding = UserData.UD_ENCODING_OCTET;
        uData.userData = data;
        uData.msgEncoding = UserData.ENCODING_OCTET;
        uData.payload = data;

        byte[] msgData = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
                true, true);
@@ -619,21 +601,21 @@ public class SmsMessage extends SmsMessageBase {
     * Parses a SMS message from its BearerData stream. (mobile-terminated only)
     */
    protected void parseSms() {
        mBearerData = SmsDataCoding.decodeCdmaSms(mEnvelope.bearerData);
        messageRef = mBearerData.messageID;
        mBearerData = BearerData.decode(mEnvelope.bearerData);
        messageRef = mBearerData.messageId;

        // TP-Message-Type-Indicator
        // (See 3GPP2 C.S0015-B, v2, 4.5.1)
        int messageType = mBearerData.messageType;

        switch (messageType) {
        case MESSAGE_TYPE_USER_ACK:
        case MESSAGE_TYPE_READ_ACK:
        case MESSAGE_TYPE_DELIVER:
        case BearerData.MESSAGE_TYPE_USER_ACK:
        case BearerData.MESSAGE_TYPE_READ_ACK:
        case BearerData.MESSAGE_TYPE_DELIVER:
            // Deliver (mobile-terminated only)
            parseSmsDeliver();
            break;
        case MESSAGE_TYPE_DELIVERY_ACK:
        case BearerData.MESSAGE_TYPE_DELIVERY_ACK:
            parseSmsDeliveryAck();
            break;

@@ -699,22 +681,22 @@ public class SmsMessage extends SmsMessageBase {
            return;
        }

        encodingType = uData.userDataEncoding;
        encodingType = uData.msgEncoding;

        // insert DCS-decoding here when type is supported by ril-library

        userData = uData.userData;
        userData = uData.payload;
        userDataHeader = uData.userDataHeader;

        switch (encodingType) {
        case UD_ENCODING_GSM_7BIT_ALPHABET:
        case UD_ENCODING_UNICODE_16:
        case UserData.ENCODING_GSM_7BIT_ALPHABET:
        case UserData.ENCODING_UNICODE_16:
            // user data was already decoded by wmsts-library
            messageBody = new String(userData);
            break;

        // data and unsupported encodings:
        case UD_ENCODING_OCTET:
        case UserData.ENCODING_OCTET:
        default:
            messageBody = null;
            break;
@@ -771,7 +753,7 @@ public class SmsMessage extends SmsMessageBase {
        if (useNewId) {
            setNextMessageId();
        }
        mBearerData.messageID = nextMessageId;
        mBearerData.messageId = nextMessageId;

        // Set the reply options (See C.S0015-B, v2.0, 4.5.11)
        if(statusReportRequested) {
@@ -795,7 +777,7 @@ public class SmsMessage extends SmsMessageBase {
        // ** encode BearerData **
        byte[] encodedBearerData = null;
        try {
            encodedBearerData = SmsDataCoding.encodeCdmaSms(mBearerData);
            encodedBearerData = BearerData.encode(mBearerData);
        } catch (Exception e) {
            Log.e(LOG_TAG, "doGetSubmitPdu: EncodeCdmaSMS function in JNI interface failed: "
                    + e.getMessage());
+482 −5

File changed.

Preview size limit exceeded, changes collapsed.

Loading