1/* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17package com.android.im.imps; 18 19import java.nio.ByteBuffer; 20 21/** 22 * A helper class to split the payload into several segments to meet the size 23 * constraint of the sms. 24 * 25 */ 26public class SmsSplitter { 27 private static final int MAX_SEGMENT_COUNT = 26; 28 29 private ByteBuffer mOutBuffer; 30 private int mMaxSegmentLen; 31 32 private byte[] mData; 33 private int mPreambleEnd; 34 35 private int mCurrentSegment; 36 private int mSegmentCount; 37 38 public SmsSplitter(int maxLen) { 39 mMaxSegmentLen = maxLen; 40 mOutBuffer = ByteBuffer.allocate(maxLen); 41 } 42 43 /** 44 * Split the data into several segments to meet the size constraint. 45 * 46 * @param data 47 * The data to split. MUST be a valid PTS primitive. 48 * @return The count of segments of the result or -1 if the data is too long. 49 */ 50 public int split(byte[] data) { 51 mData = data; 52 mCurrentSegment = 0; 53 calculateSegments(); 54 if (mSegmentCount > MAX_SEGMENT_COUNT) { 55 mSegmentCount = -1; 56 } 57 return mSegmentCount; 58 } 59 60 public boolean hasNext() { 61 return mCurrentSegment < mSegmentCount; 62 } 63 64 /** 65 * Gets the next segment. 66 * 67 * @return The next segment. 68 * @throws IndexOutOfBoundsException 69 */ 70 public byte[] getNext() { 71 if (mCurrentSegment >= mSegmentCount) { 72 throw new IndexOutOfBoundsException(); 73 } 74 byte[] segment; 75 if (mSegmentCount == 1) { 76 segment = mData; 77 } else { 78 mOutBuffer.clear(); 79 // The original preamble 80 mOutBuffer.put(mData, 0, mPreambleEnd); 81 // Two character of DD 82 mOutBuffer.put((byte) ('a' + mCurrentSegment)); 83 mOutBuffer.put((byte) ('a' + mSegmentCount - 1)); 84 // The space after preamble 85 mOutBuffer.put((byte) ' '); 86 87 // The payload 88 int segmentPayload = mMaxSegmentLen - mPreambleEnd - 3; 89 int offset = mPreambleEnd + 1 + segmentPayload * mCurrentSegment; 90 int len = (offset + segmentPayload > mData.length) ? 91 mData.length - offset : segmentPayload; 92 mOutBuffer.put(mData, offset, len); 93 94 mOutBuffer.flip(); 95 segment = new byte[mOutBuffer.limit()]; 96 mOutBuffer.get(segment); 97 } 98 mCurrentSegment++; 99 return segment; 100 } 101 102 private void calculateSegments() { 103 int totalLen = mData.length; 104 if (totalLen < mMaxSegmentLen) { 105 mSegmentCount = 1; 106 } else { 107 searchPreambleEnd(); 108 int newPreambleLen = mPreambleEnd + 2; 109 int segmentPayload = mMaxSegmentLen - newPreambleLen - 1; 110 int totalPayload = totalLen - mPreambleEnd - 1; 111 mSegmentCount = (totalPayload + segmentPayload -1) / segmentPayload; 112 } 113 } 114 115 private void searchPreambleEnd() { 116 byte[] data = mData; 117 int index = 0; 118 while(index < data.length && data[index] != ' ') { 119 index++; 120 } 121 mPreambleEnd = index; 122 } 123}