PduPersisterpublic class PduPersister extends Object This class is the high-level manager of PDU storage. |
Fields Summary |
---|
private static final String | TAG | private static final boolean | DEBUG | private static final boolean | LOCAL_LOGV | private static final long | DUMMY_THREAD_ID | public static final String | TEMPORARY_DRM_OBJECT_URIThe uri of temporary drm objects. | public static final int | PROC_STATUS_TRANSIENT_FAILUREIndicate that we transiently failed to process a MM. | public static final int | PROC_STATUS_PERMANENTLY_FAILUREIndicate that we permanently failed to process a MM. | public static final int | PROC_STATUS_COMPLETEDIndicate that we have successfully processed a MM. | private static PduPersister | sPersister | private static final com.google.android.mms.util.PduCache | PDU_CACHE_INSTANCE | private static final int[] | ADDRESS_FIELDS | private static final String[] | PDU_PROJECTION | private static final int | PDU_COLUMN_ID | private static final int | PDU_COLUMN_MESSAGE_BOX | private static final int | PDU_COLUMN_THREAD_ID | private static final int | PDU_COLUMN_RETRIEVE_TEXT | private static final int | PDU_COLUMN_SUBJECT | private static final int | PDU_COLUMN_CONTENT_LOCATION | private static final int | PDU_COLUMN_CONTENT_TYPE | private static final int | PDU_COLUMN_MESSAGE_CLASS | private static final int | PDU_COLUMN_MESSAGE_ID | private static final int | PDU_COLUMN_RESPONSE_TEXT | private static final int | PDU_COLUMN_TRANSACTION_ID | private static final int | PDU_COLUMN_CONTENT_CLASS | private static final int | PDU_COLUMN_DELIVERY_REPORT | private static final int | PDU_COLUMN_MESSAGE_TYPE | private static final int | PDU_COLUMN_MMS_VERSION | private static final int | PDU_COLUMN_PRIORITY | private static final int | PDU_COLUMN_READ_REPORT | private static final int | PDU_COLUMN_READ_STATUS | private static final int | PDU_COLUMN_REPORT_ALLOWED | private static final int | PDU_COLUMN_RETRIEVE_STATUS | private static final int | PDU_COLUMN_STATUS | private static final int | PDU_COLUMN_DATE | private static final int | PDU_COLUMN_DELIVERY_TIME | private static final int | PDU_COLUMN_EXPIRY | private static final int | PDU_COLUMN_MESSAGE_SIZE | private static final int | PDU_COLUMN_SUBJECT_CHARSET | private static final int | PDU_COLUMN_RETRIEVE_TEXT_CHARSET | private static final String[] | PART_PROJECTION | private static final int | PART_COLUMN_ID | private static final int | PART_COLUMN_CHARSET | private static final int | PART_COLUMN_CONTENT_DISPOSITION | private static final int | PART_COLUMN_CONTENT_ID | private static final int | PART_COLUMN_CONTENT_LOCATION | private static final int | PART_COLUMN_CONTENT_TYPE | private static final int | PART_COLUMN_FILENAME | private static final int | PART_COLUMN_NAME | private static final HashMap | MESSAGE_BOX_MAP | private static final HashMap | CHARSET_COLUMN_INDEX_MAP | private static final HashMap | ENCODED_STRING_COLUMN_INDEX_MAP | private static final HashMap | TEXT_STRING_COLUMN_INDEX_MAP | private static final HashMap | OCTET_COLUMN_INDEX_MAP | private static final HashMap | LONG_COLUMN_INDEX_MAP | private static final HashMap | CHARSET_COLUMN_NAME_MAP | private static final HashMap | ENCODED_STRING_COLUMN_NAME_MAP | private static final HashMap | TEXT_STRING_COLUMN_NAME_MAP | private static final HashMap | OCTET_COLUMN_NAME_MAP | private static final HashMap | LONG_COLUMN_NAME_MAP | private final android.content.Context | mContext | private final android.content.ContentResolver | mContentResolver |
Constructors Summary |
---|
private PduPersister(android.content.Context context)
mContext = context;
mContentResolver = context.getContentResolver();
|
Methods Summary |
---|
private byte[] | getByteArrayFromPartColumn(android.database.Cursor c, int columnIndex)
if (!c.isNull(columnIndex)) {
return getBytes(c.getString(columnIndex));
}
return null;
| public static byte[] | getBytes(java.lang.String data)Unpack a given String into a byte[].
try {
return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
} catch (UnsupportedEncodingException e) {
// Impossible to reach here!
Log.e(TAG, "ISO_8859_1 must be supported!", e);
return new byte[0];
}
| private java.lang.Integer | getIntegerFromPartColumn(android.database.Cursor c, int columnIndex)
if (!c.isNull(columnIndex)) {
return c.getInt(columnIndex);
}
return null;
| public static com.google.android.mms.pdu.PduPersister | getPduPersister(android.content.Context context)Get(or create if not exist) an instance of PduPersister
if ((sPersister == null) || !context.equals(sPersister.mContext)) {
sPersister = new PduPersister(context);
}
return sPersister;
| public android.database.Cursor | getPendingMessages(long dueTime)Find all messages to be sent or downloaded before certain time.
Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon();
uriBuilder.appendQueryParameter("protocol", "mms");
String selection = PendingMessages.ERROR_TYPE + " < ?"
+ " AND " + PendingMessages.DUE_TIME + " <= ?";
String[] selectionArgs = new String[] {
String.valueOf(MmsSms.ERR_TYPE_GENERIC_PERMANENT),
String.valueOf(dueTime)
};
return SqliteWrapper.query(mContext, mContentResolver,
uriBuilder.build(), null, selection, selectionArgs,
PendingMessages.DUE_TIME);
| public GenericPdu | load(android.net.Uri uri)Load a PDU from storage by given Uri.
PduCacheEntry cacheEntry = PDU_CACHE_INSTANCE.get(uri);
if (cacheEntry != null) {
return cacheEntry.getPdu();
}
Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri,
PDU_PROJECTION, null, null, null);
PduHeaders headers = new PduHeaders();
Set<Entry<Integer, Integer>> set;
long msgId = ContentUris.parseId(uri);
int msgBox;
long threadId;
try {
if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) {
throw new MmsException("Bad uri: " + uri);
}
msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX);
threadId = c.getLong(PDU_COLUMN_THREAD_ID);
set = ENCODED_STRING_COLUMN_INDEX_MAP.entrySet();
for (Entry<Integer, Integer> e : set) {
setEncodedStringValueToHeaders(
c, e.getValue(), headers, e.getKey());
}
set = TEXT_STRING_COLUMN_INDEX_MAP.entrySet();
for (Entry<Integer, Integer> e : set) {
setTextStringToHeaders(
c, e.getValue(), headers, e.getKey());
}
set = OCTET_COLUMN_INDEX_MAP.entrySet();
for (Entry<Integer, Integer> e : set) {
setOctetToHeaders(
c, e.getValue(), headers, e.getKey());
}
set = LONG_COLUMN_INDEX_MAP.entrySet();
for (Entry<Integer, Integer> e : set) {
setLongToHeaders(
c, e.getValue(), headers, e.getKey());
}
} finally {
if (c != null) {
c.close();
}
}
// Check whether 'msgId' has been assigned a valid value.
if (msgId == -1L) {
throw new MmsException("Error! ID of the message: -1.");
}
// Load address information of the MM.
loadAddress(msgId, headers);
int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
PduBody body = new PduBody();
// For PDU which type is M_retrieve.conf or Send.req, we should
// load multiparts and put them into the body of the PDU.
if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
|| (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
PduPart[] parts = loadParts(msgId);
if (parts != null) {
int partsNum = parts.length;
for (int i = 0; i < partsNum; i++) {
body.addPart(parts[i]);
}
}
}
GenericPdu pdu = null;
switch (msgType) {
case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
pdu = new NotificationInd(headers);
break;
case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
pdu = new DeliveryInd(headers);
break;
case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
pdu = new ReadOrigInd(headers);
break;
case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
pdu = new RetrieveConf(headers, body);
break;
case PduHeaders.MESSAGE_TYPE_SEND_REQ:
pdu = new SendReq(headers, body);
break;
case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
pdu = new AcknowledgeInd(headers);
break;
case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
pdu = new NotifyRespInd(headers);
break;
case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
pdu = new ReadRecInd(headers);
break;
case PduHeaders.MESSAGE_TYPE_SEND_CONF:
case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
throw new MmsException(
"Unsupported PDU type: " + Integer.toHexString(msgType));
default:
throw new MmsException(
"Unrecognized PDU type: " + Integer.toHexString(msgType));
}
cacheEntry = new PduCacheEntry(pdu, msgBox, threadId);
PDU_CACHE_INSTANCE.put(uri, cacheEntry);
return pdu;
| private void | loadAddress(long msgId, PduHeaders headers)
Cursor c = SqliteWrapper.query(mContext, mContentResolver,
Uri.parse("content://mms/" + msgId + "/addr"),
new String[] { Addr.ADDRESS, Addr.CHARSET, Addr.TYPE },
null, null, null);
if (c != null) {
try {
while (c.moveToNext()) {
String addr = c.getString(0);
if (!TextUtils.isEmpty(addr)) {
int addrType = c.getInt(2);
switch (addrType) {
case PduHeaders.FROM:
headers.setEncodedStringValue(
new EncodedStringValue(c.getInt(1), getBytes(addr)),
addrType);
break;
case PduHeaders.TO:
case PduHeaders.CC:
case PduHeaders.BCC:
headers.appendEncodedStringValue(
new EncodedStringValue(c.getInt(1), getBytes(addr)),
addrType);
break;
default:
Log.e(TAG, "Unknown address type: " + addrType);
break;
}
}
}
} finally {
c.close();
}
}
| private PduPart[] | loadParts(long msgId)
Cursor c = SqliteWrapper.query(mContext, mContentResolver,
Uri.parse("content://mms/" + msgId + "/part"),
PART_PROJECTION, null, null, null);
PduPart[] parts = null;
try {
if ((c == null) || (c.getCount() == 0)) {
if (LOCAL_LOGV) {
Log.v(TAG, "loadParts(" + msgId + "): no part to load.");
}
return null;
}
int partCount = c.getCount();
int partIdx = 0;
parts = new PduPart[partCount];
while (c.moveToNext()) {
PduPart part = new PduPart();
Integer charset = getIntegerFromPartColumn(
c, PART_COLUMN_CHARSET);
if (charset != null) {
part.setCharset(charset);
}
byte[] contentDisposition = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_DISPOSITION);
if (contentDisposition != null) {
part.setContentDisposition(contentDisposition);
}
byte[] contentId = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_ID);
if (contentId != null) {
part.setContentId(contentId);
}
byte[] contentLocation = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_LOCATION);
if (contentLocation != null) {
part.setContentLocation(contentLocation);
}
byte[] contentType = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_TYPE);
if (contentType != null) {
part.setContentType(contentType);
} else {
throw new MmsException("Content-Type must be set.");
}
byte[] fileName = getByteArrayFromPartColumn(
c, PART_COLUMN_FILENAME);
if (fileName != null) {
part.setFilename(fileName);
}
byte[] name = getByteArrayFromPartColumn(
c, PART_COLUMN_NAME);
if (name != null) {
part.setName(name);
}
// Construct a Uri for this part.
long partId = c.getLong(PART_COLUMN_ID);
Uri partURI = Uri.parse("content://mms/part/" + partId);
part.setDataUri(partURI);
// For images/audio/video, we won't keep their data in Part
// because their renderer accept Uri as source.
String type = toIsoString(contentType);
if (!ContentType.isImageType(type)
&& !ContentType.isAudioType(type)
&& !ContentType.isVideoType(type)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = mContentResolver.openInputStream(partURI);
byte[] buffer = new byte[256];
int len = is.read(buffer);
while (len >= 0) {
baos.write(buffer, 0, len);
len = is.read(buffer);
}
} catch (IOException e) {
Log.e(TAG, "Failed to load part data", e);
c.close();
throw new MmsException(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close stream", e);
} // Ignore
}
}
part.setData(baos.toByteArray());
}
parts[partIdx++] = part;
}
} finally {
if (c != null) {
c.close();
}
}
return parts;
| public android.net.Uri | move(android.net.Uri from, android.net.Uri to)Move a PDU object from one location to another.
// Check whether the 'msgId' has been assigned a valid value.
long msgId = ContentUris.parseId(from);
if (msgId == -1L) {
throw new MmsException("Error! ID of the message: -1.");
}
// Get corresponding int value of destination box.
Integer msgBox = MESSAGE_BOX_MAP.get(to);
if (msgBox == null) {
throw new MmsException(
"Bad destination, must be one of "
+ "content://mms/inbox, content://mms/sent, "
+ "content://mms/drafts, content://mms/outbox, "
+ "content://mms/temp.");
}
ContentValues values = new ContentValues(1);
values.put(Mms.MESSAGE_BOX, msgBox);
SqliteWrapper.update(mContext, mContentResolver, from, values, null, null);
return ContentUris.withAppendedId(to, msgId);
| public android.net.Uri | persist(GenericPdu pdu, android.net.Uri uri)Persist a PDU object to specific location in the storage.
if (uri == null) {
throw new MmsException("Uri may not be null.");
}
Integer msgBox = MESSAGE_BOX_MAP.get(uri);
if (msgBox == null) {
throw new MmsException(
"Bad destination, must be one of "
+ "content://mms/inbox, content://mms/sent, "
+ "content://mms/drafts, content://mms/outbox, "
+ "content://mms/temp.");
}
PduHeaders header = pdu.getPduHeaders();
PduBody body = null;
ContentValues values = new ContentValues();
Set<Entry<Integer, String>> set;
set = ENCODED_STRING_COLUMN_NAME_MAP.entrySet();
for (Entry<Integer, String> e : set) {
int field = e.getKey();
EncodedStringValue encodedString = header.getEncodedStringValue(field);
if (encodedString != null) {
String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field);
values.put(e.getValue(), toIsoString(encodedString.getTextString()));
values.put(charsetColumn, encodedString.getCharacterSet());
}
}
set = TEXT_STRING_COLUMN_NAME_MAP.entrySet();
for (Entry<Integer, String> e : set){
byte[] text = header.getTextString(e.getKey());
if (text != null) {
values.put(e.getValue(), toIsoString(text));
}
}
set = OCTET_COLUMN_NAME_MAP.entrySet();
for (Entry<Integer, String> e : set){
int b = header.getOctet(e.getKey());
if (b != 0) {
values.put(e.getValue(), b);
}
}
set = LONG_COLUMN_NAME_MAP.entrySet();
for (Entry<Integer, String> e : set){
long l = header.getLongInteger(e.getKey());
if (l != -1L) {
values.put(e.getValue(), l);
}
}
HashMap<Integer, EncodedStringValue[]> addressMap =
new HashMap<Integer, EncodedStringValue[]>(ADDRESS_FIELDS.length);
// Save address information.
for (int addrType : ADDRESS_FIELDS) {
EncodedStringValue[] array = null;
if (addrType == PduHeaders.FROM) {
EncodedStringValue v = header.getEncodedStringValue(addrType);
if (v != null) {
array = new EncodedStringValue[1];
array[0] = v;
}
} else {
array = header.getEncodedStringValues(addrType);
}
addressMap.put(addrType, array);
}
HashSet<String> recipients = new HashSet<String>();
long threadId = DUMMY_THREAD_ID;
int msgType = pdu.getMessageType();
// Here we only allocate thread ID for M-Notification.ind,
// M-Retrieve.conf and M-Send.req.
// Some of other PDU types may be allocated a thread ID outside
// this scope.
if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND)
|| (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
|| (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
EncodedStringValue[] array = null;
switch (msgType) {
case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
array = addressMap.get(PduHeaders.FROM);
break;
case PduHeaders.MESSAGE_TYPE_SEND_REQ:
array = addressMap.get(PduHeaders.TO);
break;
}
if (array != null) {
for (EncodedStringValue v : array) {
if (v != null) {
recipients.add(v.getString());
}
}
}
threadId = Threads.getOrCreateThreadId(mContext, recipients);
}
values.put(Mms.THREAD_ID, threadId);
// Save parts first to avoid inconsistent message is loaded
// while saving the parts.
long dummyId = System.currentTimeMillis(); // Dummy ID of the msg.
// Get body if the PDU is a RetrieveConf or SendReq.
if (pdu instanceof MultimediaMessagePdu) {
body = ((MultimediaMessagePdu) pdu).getBody();
// Start saving parts if necessary.
if (body != null) {
int partsNum = body.getPartsNum();
for (int i = 0; i < partsNum; i++) {
PduPart part = body.getPart(i);
persistPart(part, dummyId);
}
}
}
Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
if (res == null) {
throw new MmsException("persist() failed: return null.");
}
// Get the real ID of the PDU and update all parts which were
// saved with the dummy ID.
long msgId = ContentUris.parseId(res);
values = new ContentValues(1);
values.put(Part.MSG_ID, msgId);
SqliteWrapper.update(mContext, mContentResolver,
Uri.parse("content://mms/" + dummyId + "/part"),
values, null, null);
// We should return the longest URI of the persisted PDU, for
// example, if input URI is "content://mms/inbox" and the _ID of
// persisted PDU is '8', we should return "content://mms/inbox/8"
// instead of "content://mms/8".
// FIXME: Should the MmsProvider be responsible for this???
res = Uri.parse(uri + "/" + msgId);
// Save address information.
for (int addrType : ADDRESS_FIELDS) {
EncodedStringValue[] array = addressMap.get(addrType);
if (array != null) {
persistAddress(msgId, addrType, array);
}
}
return res;
| private void | persistAddress(long msgId, int type, EncodedStringValue[] array)
ContentValues values = new ContentValues(3);
for (EncodedStringValue addr : array) {
values.clear(); // Clear all values first.
values.put(Addr.ADDRESS, toIsoString(addr.getTextString()));
values.put(Addr.CHARSET, addr.getCharacterSet());
values.put(Addr.TYPE, type);
Uri uri = Uri.parse("content://mms/" + msgId + "/addr");
SqliteWrapper.insert(mContext, mContentResolver, uri, values);
}
| private void | persistData(PduPart part, android.net.Uri uri, java.lang.String contentType)Save data of the part into storage. The source data may be given
by a byte[] or a Uri. If it's a byte[], directly save it
into storage, otherwise load source data from the dataUri and then
save it. If the data is an image, we may scale down it according
to user preference.
OutputStream os = null;
InputStream is = null;
try {
os = mContentResolver.openOutputStream(uri);
byte[] data = part.getData();
if (data == null) {
Uri dataUri = part.getDataUri();
if ((dataUri == null) || (dataUri == uri)) {
Log.w(TAG, "Can't find data for this part.");
return;
}
is = mContentResolver.openInputStream(dataUri);
if (LOCAL_LOGV) {
Log.v(TAG, "Saving data to: " + uri);
}
byte[] buffer = new byte[256];
for (int len = 0; (len = is.read(buffer)) != -1; ) {
os.write(buffer, 0, len);
}
} else {
if (LOCAL_LOGV) {
Log.v(TAG, "Saving data to: " + uri);
}
os.write(data);
}
} catch (FileNotFoundException e) {
Log.e(TAG, "Failed to open Input/Output stream.", e);
throw new MmsException(e);
} catch (IOException e) {
Log.e(TAG, "Failed to read/write data.", e);
throw new MmsException(e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
Log.e(TAG, "IOException while closing: " + os, e);
} // Ignore
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
Log.e(TAG, "IOException while closing: " + is, e);
} // Ignore
}
}
| public android.net.Uri | persistPart(PduPart part, long msgId)
Uri uri = Uri.parse("content://mms/" + msgId + "/part");
ContentValues values = new ContentValues(8);
int charset = part.getCharset();
if (charset != 0 ) {
values.put(Part.CHARSET, charset);
}
String contentType = null;
if (part.getContentType() != null) {
contentType = toIsoString(part.getContentType());
values.put(Part.CONTENT_TYPE, contentType);
// To ensure the SMIL part is always the first part.
if (ContentType.APP_SMIL.equals(contentType)) {
values.put(Part.SEQ, -1);
}
} else {
throw new MmsException("MIME type of the part must be set.");
}
if (part.getFilename() != null) {
String fileName = new String(part.getFilename());
values.put(Part.FILENAME, fileName);
}
if (part.getName() != null) {
String name = new String(part.getName());
values.put(Part.NAME, name);
}
Object value = null;
if (part.getContentDisposition() != null) {
value = toIsoString(part.getContentDisposition());
values.put(Part.CONTENT_DISPOSITION, (String) value);
}
if (part.getContentId() != null) {
value = toIsoString(part.getContentId());
values.put(Part.CONTENT_ID, (String) value);
}
if (part.getContentLocation() != null) {
value = toIsoString(part.getContentLocation());
values.put(Part.CONTENT_LOCATION, (String) value);
}
Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
if (res == null) {
throw new MmsException("Failed to persist part, return null.");
}
persistData(part, res, contentType);
// After successfully store the data, we should update
// the dataUri of the part.
part.setDataUri(res);
return res;
| public void | release()Remove all objects in the temporary path.
Uri uri = Uri.parse(TEMPORARY_DRM_OBJECT_URI);
SqliteWrapper.delete(mContext, mContentResolver, uri, null, null);
| private void | setEncodedStringValueToHeaders(android.database.Cursor c, int columnIndex, PduHeaders headers, int mapColumn)
String s = c.getString(columnIndex);
if ((s != null) && (s.length() > 0)) {
int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn);
int charset = c.getInt(charsetColumnIndex);
EncodedStringValue value = new EncodedStringValue(
charset, getBytes(s));
headers.setEncodedStringValue(value, mapColumn);
}
| private void | setLongToHeaders(android.database.Cursor c, int columnIndex, PduHeaders headers, int mapColumn)
if (!c.isNull(columnIndex)) {
long l = c.getLong(columnIndex);
headers.setLongInteger(l, mapColumn);
}
| private void | setOctetToHeaders(android.database.Cursor c, int columnIndex, PduHeaders headers, int mapColumn)
if (!c.isNull(columnIndex)) {
int b = c.getInt(columnIndex);
headers.setOctet(b, mapColumn);
}
| private void | setTextStringToHeaders(android.database.Cursor c, int columnIndex, PduHeaders headers, int mapColumn)
String s = c.getString(columnIndex);
if (s != null) {
headers.setTextString(getBytes(s), mapColumn);
}
| public static java.lang.String | toIsoString(byte[] bytes)Wrap a byte[] into a String.
try {
return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1);
} catch (UnsupportedEncodingException e) {
// Impossible to reach here!
Log.e(TAG, "ISO_8859_1 must be supported!", e);
return "";
}
| private void | updateAddress(long msgId, int type, EncodedStringValue[] array)
// Delete old address information and then insert new ones.
SqliteWrapper.delete(mContext, mContentResolver,
Uri.parse("content://mms/" + msgId + "/addr"),
Addr.TYPE + "=" + type, null);
persistAddress(msgId, type, array);
| public void | updateHeaders(android.net.Uri uri, SendReq sendReq)Update headers of a SendReq.
PDU_CACHE_INSTANCE.purge(uri);
ContentValues values = new ContentValues(9);
byte[] contentType = sendReq.getContentType();
if (contentType != null) {
values.put(Mms.CONTENT_TYPE, toIsoString(contentType));
}
long date = sendReq.getDate();
if (date != -1) {
values.put(Mms.DATE, date);
}
int deliveryReport = sendReq.getDeliveryReport();
if (deliveryReport != 0) {
values.put(Mms.DELIVERY_REPORT, deliveryReport);
}
long expiry = sendReq.getExpiry();
if (expiry != -1) {
values.put(Mms.EXPIRY, expiry);
}
byte[] msgClass = sendReq.getMessageClass();
if (msgClass != null) {
values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass));
}
int priority = sendReq.getPriority();
if (priority != 0) {
values.put(Mms.PRIORITY, priority);
}
int readReport = sendReq.getReadReport();
if (readReport != 0) {
values.put(Mms.READ_REPORT, readReport);
}
byte[] transId = sendReq.getTransactionId();
if (transId != null) {
values.put(Mms.TRANSACTION_ID, toIsoString(transId));
}
EncodedStringValue subject = sendReq.getSubject();
if (subject != null) {
values.put(Mms.SUBJECT, toIsoString(subject.getTextString()));
values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet());
}
PduHeaders headers = sendReq.getPduHeaders();
HashSet<String> recipients = new HashSet<String>();
for (int addrType : ADDRESS_FIELDS) {
EncodedStringValue[] array = null;
if (addrType == PduHeaders.FROM) {
EncodedStringValue v = headers.getEncodedStringValue(addrType);
if (v != null) {
array = new EncodedStringValue[1];
array[0] = v;
}
} else {
array = headers.getEncodedStringValues(addrType);
}
if (array != null) {
long msgId = ContentUris.parseId(uri);
updateAddress(msgId, addrType, array);
if (addrType == PduHeaders.TO) {
for (EncodedStringValue v : array) {
if (v != null) {
recipients.add(v.getString());
}
}
}
}
}
long threadId = Threads.getOrCreateThreadId(mContext, recipients);
values.put(Mms.THREAD_ID, threadId);
SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
| private void | updatePart(android.net.Uri uri, PduPart part)
ContentValues values = new ContentValues(7);
int charset = part.getCharset();
if (charset != 0 ) {
values.put(Part.CHARSET, charset);
}
String contentType = null;
if (part.getContentType() != null) {
contentType = toIsoString(part.getContentType());
values.put(Part.CONTENT_TYPE, contentType);
} else {
throw new MmsException("MIME type of the part must be set.");
}
if (part.getFilename() != null) {
String fileName = new String(part.getFilename());
values.put(Part.FILENAME, fileName);
}
if (part.getName() != null) {
String name = new String(part.getName());
values.put(Part.NAME, name);
}
Object value = null;
if (part.getContentDisposition() != null) {
value = toIsoString(part.getContentDisposition());
values.put(Part.CONTENT_DISPOSITION, (String) value);
}
if (part.getContentId() != null) {
value = toIsoString(part.getContentId());
values.put(Part.CONTENT_ID, (String) value);
}
if (part.getContentLocation() != null) {
value = toIsoString(part.getContentLocation());
values.put(Part.CONTENT_LOCATION, (String) value);
}
SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
// Only update the data when:
// 1. New binary data supplied or
// 2. The Uri of the part is different from the current one.
if ((part.getData() != null)
|| (uri != part.getDataUri())) {
persistData(part, uri, contentType);
}
| public void | updateParts(android.net.Uri uri, PduBody body)Update all parts of a PDU.
PduCacheEntry cacheEntry = PDU_CACHE_INSTANCE.get(uri);
if (cacheEntry != null) {
((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body);
}
ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>();
HashMap<Uri, PduPart> toBeUpdated = new HashMap<Uri, PduPart>();
int partsNum = body.getPartsNum();
StringBuilder filter = new StringBuilder().append('(");
for (int i = 0; i < partsNum; i++) {
PduPart part = body.getPart(i);
Uri partUri = part.getDataUri();
if ((partUri == null) || !partUri.getAuthority().startsWith("mms")) {
toBeCreated.add(part);
} else {
toBeUpdated.put(partUri, part);
// Don't use 'i > 0' to determine whether we should append
// 'AND' since 'i = 0' may be skipped in another branch.
if (filter.length() > 1) {
filter.append(" AND ");
}
filter.append(Part._ID);
filter.append("!=");
DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment());
}
}
filter.append(')");
long msgId = ContentUris.parseId(uri);
// Remove the parts which doesn't exist anymore.
SqliteWrapper.delete(mContext, mContentResolver,
Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"),
filter.length() > 2 ? filter.toString() : null, null);
// Create new parts which didn't exist before.
for (PduPart part : toBeCreated) {
persistPart(part, msgId);
}
// Update the modified parts.
for (Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
updatePart(e.getKey(), e.getValue());
}
|
|