記不清是android 4.0之後還是4.1之後,浏覽信息時,彩信幻燈片不再隨著信息內容一並顯示,而是在信息內容顯示後,開啟後台線程,異步加載彩信幻燈片,加載完畢之後再顯示附件。為什麼要這麼設計那?主要是為了解決彩信顯示緩慢的問題。在原先的設計中,彩信想要顯示,首先要做准備工作,准備工作包括從數據庫中加載信息的內容,收件人,發送時間,主題,類型,狀態報告等基礎內容,其中還包括了一項費時的操作,那就是加載彩信幻燈片附件。只有上述工作全部完成之後彩信才會顯示在界面上,用戶才可以進行浏覽。這種設計非常容易卡機,有時還會引起ANR(應用程序無相應),尤其當我們的運營商要求彩信幻燈片支持20頁(默認10頁),這個問題就更加嚴重,長時間不顯示信息,嚴重影響性能。其實從功能設計上來說,用戶首先希望看到的是彩信收件人,彩信主題,發送時間,發送狀態報告等基礎信息,然後才會選擇查看幻燈片等多媒體附件。我們完全可以將幻燈片的加載滯後。androd目前給出了這樣的一個設計。
首先根據當前回話,查詢數據庫,加載信息條目。每一個信息條目,每一條信息條目,用視圖MessageListItem來顯示,信息內容數據包裝在MessageItem中。
MessageListAdapter.java
[java]
public View newView(Context context, Cursor cursor, ViewGroup parent) {
int boxType = getItemViewType(cursor);
View view = mInflater.inflate((boxType == INCOMING_ITEM_TYPE_SMS ||
boxType == INCOMING_ITEM_TYPE_MMS) ?
R.layout.message_list_item_recv : R.layout.message_list_item_send,
parent, false);
if (boxType == INCOMING_ITEM_TYPE_MMS || boxType == OUTGOING_ITEM_TYPE_MMS) {
// We've got an mms item, pre-inflate the mms portion of the view
view.findViewById(R.id.mms_layout_view_stub).setVisibility(View.VISIBLE);
}
return view;
}
這個view就是MessageLIstItem。然後MessagelistAdapter會調用bindView方法,完成視圖的加載,在加載中,主要是調用MessageItem的bind方法。我們現在主要關心的是MessageItem對彩信內容數據的加載,以及著重注意異步加載幻燈片附件的邏輯處理。
[java]
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (<strong>view instanceof MessageListItem</strong>) {
String type = cursor.getString(mColumnsMap.mColumnMsgType);
long msgId = cursor.getLong(mColumnsMap.mColumnMsgId);
<strong>MessageItem msgItem = getCachedMessageItem(type, msgId, cursor);</strong>
if (msgItem != null) {
MessageListItem mli = (MessageListItem) view;
int position = cursor.getPosition();
mli.bind(msgItem, position == cursor.getCount() - 1, position);
mli.setMsgListItemHandler(mMsgListItemHandler);
}
}
}
根據信息的type以及msgId,通過getCachedMessageItem方法,得到一個MessageItem。
[java]
public MessageItem getCachedMessageItem(String type, long msgId, Cursor c) {
MessageItem item = mMessageItemCache.get(getKey(type, msgId));
if (item == null && c != null && isCursorValid(c)) {
try {
<strong>item = new MessageItem(mContext, type, c, mColumnsMap, mHighlight, mFullTimestamp, mSentTimestamp);</strong>
mMessageItemCache.put(getKey(item.mType, item.mMsgId), item);
} catch (MmsException e) {
Log.e(TAG, "getCachedMessageItem: ", e);
}
}
return item;
}
在MessageItem中會對cursor中的數據進行加載。
MessgeItem.java
[java]
MessageItem(Context context, String type, final Cursor cursor,
final ColumnsMap columnsMap, Pattern highlight, boolean fullTimestamp, boolean sentTimestamp) throws MmsException {
mContext = context;
mMsgId = cursor.getLong(columnsMap.mColumnMsgId);
mHighlight = highlight;
mType = type;
mCursor = cursor;
mColumnsMap = columnsMap;
mFullTimestamp = fullTimestamp;
mSentTimestamp = sentTimestamp;
if ("sms".equals(type)) {
mReadReport = false; // No read reports in sms
long status = cursor.getLong(columnsMap.mColumnSmsStatus);
if (status == Sms.STATUS_NONE) {
// No delivery report requested
mDeliveryStatus = DeliveryStatus.NONE;
} else if (status >= Sms.STATUS_FAILED) {
// Failure
mDeliveryStatus = DeliveryStatus.FAILED;
} else if (status >= Sms.STATUS_PENDING) {
// Pending
mDeliveryStatus = DeliveryStatus.PENDING;
} else {
// Success
mDeliveryStatus = DeliveryStatus.RECEIVED;
}
mMessageUri = ContentUris.withAppendedId(Sms.CONTENT_URI, mMsgId);
// Set contact and message body
mBoxId = cursor.getInt(columnsMap.mColumnSmsType);
mAddress = cursor.getString(columnsMap.mColumnSmsAddress);
if (Sms.isOutgoingFolder(mBoxId)) {
String meString = context.getString(
R.string.messagelist_sender_self);
mContact = meString;
} else {
// For incoming messages, the ADDRESS field contains the sender.
mContact = Contact.get(mAddress, false).getName();
}
mBody = cursor.getString(columnsMap.mColumnSmsBody);
// Unless the message is currently in the progress of being sent, it gets a time stamp.
if (!isOutgoingMessage()) {
// Set "received" or "sent" time stamp
long date = cursor.getLong(columnsMap.mColumnSmsDate);
if (mSentTimestamp && (mBoxId == Sms.MESSAGE_TYPE_INBOX)) {
date = cursor.getLong(columnsMap.mColumnSmsDateSent);
}
mTimestamp = MessageUtils.formatTimeStampString(context, date, mFullTimestamp);
}
mLocked = cursor.getInt(columnsMap.mColumnSmsLocked) != 0;
mErrorCode = cursor.getInt(columnsMap.mColumnSmsErrorCode);
} else if ("mms".equals(type)) {
mMessageUri = ContentUris.withAppendedId(Mms.CONTENT_URI, mMsgId);
mBoxId = cursor.getInt(columnsMap.mColumnMmsMessageBox);
mMessageType = cursor.getInt(columnsMap.mColumnMmsMessageType);
mErrorType = cursor.getInt(columnsMap.mColumnMmsErrorType);
String subject = cursor.getString(columnsMap.mColumnMmsSubject);
if (!TextUtils.isEmpty(subject)) {
EncodedStringValue v = new EncodedStringValue(
cursor.getInt(columnsMap.mColumnMmsSubjectCharset),
PduPersister.getBytes(subject));
mSubject = v.getString();
}
mLocked = cursor.getInt(columnsMap.mColumnMmsLocked) != 0;
mSlideshow = null;
mAttachmentType = ATTACHMENT_TYPE_NOT_LOADED;
mDeliveryStatus = DeliveryStatus.NONE;
mReadReport = false;
mBody = null;
mMessageSize = 0;
mTextContentType = null;
mTimestamp = null;
mMmsStatus = cursor.getInt(columnsMap.mColumnMmsStatus);
// Start an async load of the pdu. If the pdu is already loaded, the callback
// will get called immediately
boolean loadSlideshow = mMessageType != PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
<strong>mItemLoadedFuture = MmsApp.getApplication().getPduLoaderManager()//異步加載幻燈片的邏輯
.getPdu(mMessageUri, loadSlideshow,
new PduLoadedMessageItemCallback());</strong>
} else {
throw new MmsException("Unknown type of the message: " + type);
}
}
在構造中,會根據信息的類別,加載短信和彩信的數據。數據包括信息的MessageUri,信息的 messageType,信息的主題,信息的boxId,信息的狀態等。這些屬於基礎信息,這些信息是要首先展示給用戶的。我們的目的是最後幾行加黑的代碼,他們就是我們彩信幻燈片後台加載的邏輯代碼。
MmsApp.java
[java]
public PduLoaderManager getPduLoaderManager() {
return mPduLoaderManager;
}
PduLoadedManager.java
[java]
public class PduLoaderManager extends BackgroundLoaderManager {.....}
[java]
public PduLoaderManager(final Context context) {
super(context);
mSlideshowCache = new SimpleCache<Uri, SlideshowModel>(8, 16, 0.75f, true);
mPduCache = PduCache.getInstance();
mPduPersister = PduPersister.getPduPersister(context);
mContext = context;
}
方法繼承子BackgroundLoadManager。
BackgroundLoadManager.java
[java]
BackgroundLoaderManager(Context context) {
mPendingTaskUris = new HashSet<Uri>();<strong>//等待加載幻燈片任務集合,內容為彩信uri的集合</strong>
mCallbacks = new HashMap<Uri, Set<ItemLoadedCallback>>();<strong>//彩信uri為key,value是callback的集合,callback是在幻燈片附件加載任務完成後回調的方法對象。</strong>
final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
final int poolSize = MAX_THREADS;
mExecutor = new ThreadPoolExecutor(<strong>//開啟一個線程池,在新線程中處理幻燈片的加載等工作。</strong>
poolSize, poolSize, 5, TimeUnit.SECONDS, queue,
new BackgroundLoaderThreadFactory(getTag()));
mCallbackHandler = new Handler();
}
在上面的MessageItem類中,會調用PduLoadedManager類的getPdu方法。
[java]
public ItemLoadedFuture getPdu(Uri uri, boolean requestSlideshow,
final ItemLoadedCallback<PduLoaded> callback) {
if (uri == null) {
throw new NullPointerException();
}
PduCacheEntry cacheEntry = null;
synchronized(mPduCache) {
if (!mPduCache.isUpdating(uri)) {
cacheEntry = mPduCache.get(uri);//第一次會走到這裡,cacheEntry為null。
}
}
final SlideshowModel slideshow = (requestSlideshow && !DEBUG_DISABLE_CACHE) ?//requestSlideshow為true,但mSlideshowCache.get(uri)為null。
mSlideshowCache.get(uri) : null;
final boolean slideshowExists = (!requestSlideshow || slideshow != null);//判斷slideshowModel是否存在,slideshowModel是幻燈片的實體。
final boolean pduExists = (cacheEntry != null && cacheEntry.getPdu() != null);//pdu是否存在。pdu是幻燈片信息的封裝,基類是GenericPdu。
final boolean taskExists = mPendingTaskUris.contains(uri);//判斷是否存在線程
final boolean newTaskRequired = (!pduExists || !slideshowExists) && !taskExists;//是否需要新開啟線程
final boolean callbackRequired = (callback != null);//是否存在回調對象
if (pduExists && slideshowExists) {//如果pdu存在,並且slideshowModel也存在,那麼不用開啟線程加載了,直接返回。
if (callbackRequired) {
PduLoaded pduLoaded = new PduLoaded(cacheEntry.getPdu(), slideshow);
callback.onItemLoaded(pduLoaded, null);
}
return new NullItemLoadedFuture();
}
if (callbackRequired) {//如果存在回調對象,那麼將uri為key,value為callbacks的集合,加入到mCallbacks中。
addCallback(uri, callback);
}
if (newTaskRequired) {//是否需要開啟新的線程,如果需要,那麼構建一個PduTask,並且放到線程池中,執行它。
mPendingTaskUris.add(uri);
Runnable task = new PduTask(uri, requestSlideshow);
mExecutor.execute(task);
}
return new ItemLoadedFuture() {
public void cancel() {
cancelCallback(callback);
}
public boolean isDone() {
return false;
}
};
}
PduTask.java
[java]
public class PduTask implements Runnable {
private final Uri mUri;
private final boolean mRequestSlideshow;
public PduTask(Uri uri, boolean requestSlideshow) {
if (uri == null) {
throw new NullPointerException();
}
mUri = uri;
mRequestSlideshow = requestSlideshow;
}
/** {@inheritDoc} */
public void run() {
if (DEBUG_DISABLE_PDUS) {
return;
}
if (DEBUG_LONG_WAIT) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
}
GenericPdu pdu = null;//所有彩信pdu的基類,子類中有我們熟悉的SendReq(發送的彩信所包裝的pdu),RetrieveConf等
SlideshowModel slideshow = null;
Throwable exception = null;
try {
pdu = mPduPersister.load(mUri);//<strong>特別關鍵的一個函數,在介紹完流程後,會介紹一下這個類的,處理的數據很多,但框架很清晰</strong>
if (pdu != null && mRequestSlideshow) {
slideshow = SlideshowModel.createFromPduBody(mContext,//從pdu中解析出SlideshowModel。從SlideshowModel能夠得到pdu,那麼反過來也一樣能夠得到。
((MultimediaMessagePdu)pdu).getBody());
}
} catch (final MmsException e) {
Log.e(TAG, "MmsException loading uri: " + mUri, e);
exception = e;
}
final GenericPdu resultPdu = pdu;
final SlideshowModel resultSlideshow = slideshow;
final Throwable resultException = exception;
mCallbackHandler.post(new Runnable() {
public void run() {
final Set<ItemLoadedCallback> callbacks = mCallbacks.get(mUri);//我們在上面將回調對象的集合加入到了mCallbacks中,現在我們根據uri將回調對象集合取出來
if (callbacks != null) {
// Make a copy so that the callback can unregister itself
for (final ItemLoadedCallback<PduLoaded> callback : asList(callbacks)) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Invoking pdu callback " + callback);
}
PduLoaded pduLoaded = new PduLoaded(resultPdu, resultSlideshow);//遍歷集合,然後執行回調函數的onItemLoaded。
callback.onItemLoaded(pduLoaded, resultException);
}
}
// Add the slideshow to the soft cache if the load succeeded
if (resultSlideshow != null) {
mSlideshowCache.put(mUri, resultSlideshow);//將得到的slideshowModel作為value,uri作為key加入到mSlideshowCache中,下次就不需要開啟線程加載就可以得到SlideshowModel
}
mCallbacks.remove(mUri);//回調函數執行完畢,那麼從mCallbacks中移除
mPendingTaskUris.remove(mUri);//同樣移除操作
if (Log.isLoggable(LogTag.PDU_CACHE, Log.DEBUG)) {
Log.d(TAG, "Pdu task for " + mUri + "exiting; " + mPendingTaskUris.size()
+ " remain");
}
}
});
}
}
這個執行完畢,那麼我們回到MessageItem看看回調函數。
[java]
public class PduLoadedMessageItemCallback implements ItemLoadedCallback {
public void onItemLoaded(Object result, Throwable exception) {
if (exception != null) {
Log.e(TAG, "PduLoadedMessageItemCallback PDU couldn't be loaded: ", exception);
return;
}
PduLoaderManager.PduLoaded pduLoaded = (PduLoaderManager.PduLoaded)result;//回調的結果
long timestamp = 0L;
if (PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND == mMessageType) {//根據當前信息的類型,將pdu將強轉成相應的pdu封裝類。<strong>這裡我有一點疑惑(MessageItem中的mMessageType是會改變的,而我們的加載是異步加載,也就說加載前mMessageType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND,如果我們加載完,mMessageType會不會變成另外一個值,比如PduHeaders.MESSAGE_TYPE_SEND_REQ等,那麼我們強轉會不會產生異常?就目前所知,在接收彩信時,MessageItem類型會發生改變,這種情況應該是會出現的)</strong>
mDeliveryStatus = DeliveryStatus.NONE;
NotificationInd notifInd = (NotificationInd)pduLoaded.mPdu;//強轉類型為NotificationInd,接收彩信時,為下載彩信內容
interpretFrom(notifInd.getFrom(), mMessageUri);
// Borrow the mBody to hold the URL of the message.
mBody = new String(notifInd.getContentLocation());
mMessageSize = (int) notifInd.getMessageSize();
timestamp = notifInd.getExpiry() * 1000L;
} else {
if (mCursor.isClosed()) {
return;
}
MultimediaMessagePdu msg = (MultimediaMessagePdu)pduLoaded.mPdu;//MultimediaMessagePdu是發送和接收彩信的pdu類型的基類型。
mSlideshow = pduLoaded.mSlideshow;
mAttachmentType = MessageUtils.getAttachmentType(mSlideshow);
if (mMessageType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) {//接收彩信的類型,再往下就是繼續初始化一些彩信數據
if (msg == null) {
interpretFrom(null, mMessageUri);
} else {
RetrieveConf retrieveConf = (RetrieveConf) msg;
interpretFrom(retrieveConf.getFrom(), mMessageUri);
timestamp = retrieveConf.getDate() * 1000L;
}
} else {
// Use constant string for outgoing messages
mContact = mAddress =
mContext.getString(R.string.messagelist_sender_self);
timestamp = msg == null ? 0 : ((SendReq) msg).getDate() * 1000L;
}
SlideModel slide = mSlideshow == null ? null : mSlideshow.get(0);
if ((slide != null) && slide.hasText()) {
TextModel tm = slide.getText();
mBody = tm.getText();
mTextContentType = tm.getContentType();
}
mMessageSize = mSlideshow == null ? 0 : mSlideshow.getTotalMessageSize();
String report = mCursor.getString(mColumnsMap.mColumnMmsDeliveryReport);
if ((report == null) || !mAddress.equals(mContext.getString(
R.string.messagelist_sender_self))) {
mDeliveryStatus = DeliveryStatus.NONE;
} else {
int reportInt;
try {
reportInt = Integer.parseInt(report);
if (reportInt == PduHeaders.VALUE_YES) {
mDeliveryStatus = DeliveryStatus.RECEIVED;
} else {
mDeliveryStatus = DeliveryStatus.NONE;
}
} catch (NumberFormatException nfe) {
Log.e(TAG, "Value for delivery report was invalid.");
mDeliveryStatus = DeliveryStatus.NONE;
}
}
report = mCursor.getString(mColumnsMap.mColumnMmsReadReport);
if ((report == null) || !mAddress.equals(mContext.getString(
R.string.messagelist_sender_self))) {
mReadReport = false;
} else {
int reportInt;
try {
reportInt = Integer.parseInt(report);
mReadReport = (reportInt == PduHeaders.VALUE_YES);
} catch (NumberFormatException nfe) {
Log.e(TAG, "Value for read report was invalid.");
mReadReport = false;
}
}
}
if (!isOutgoingMessage()) {
if (PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND == mMessageType) {
mTimestamp = mContext.getString(R.string.expire_on,
MessageUtils.formatTimeStampString(mContext, timestamp, mFullTimestamp));
} else {
mTimestamp = MessageUtils.formatTimeStampString(mContext, timestamp, mFullTimestamp);
}
}
if (mPduLoadedCallback != null) {
mPduLoadedCallback.onPduLoaded(MessageItem.this);
}
}
}
異步加載完幻燈片,那麼就可以在彩信中顯示了。我們主要看幻燈片附件的異步加載,剩下的邏輯以後在分析。
我們最後來看一下
[java]
pdu = mPduPersister.load(mUri);
PduPersister.java
這個類在framework層
[java]
public GenericPdu load(Uri uri) throws MmsException {
GenericPdu pdu = null;
PduCacheEntry cacheEntry = null;
int msgBox = 0;
long threadId = -1;
try {
synchronized(PDU_CACHE_INSTANCE) {
if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
if (LOCAL_LOGV) {
Log.v(TAG, "load: " + uri + " blocked by isUpdating()");
}
try {
PDU_CACHE_INSTANCE.wait();
} catch (InterruptedException e) {
Log.e(TAG, "load: ", e);
}
cacheEntry = PDU_CACHE_INSTANCE.get(uri);
if (cacheEntry != null) {
return cacheEntry.getPdu();
}
}
// Tell the cache to indicate to other callers that this item
// is currently being updated.
PDU_CACHE_INSTANCE.setUpdating(uri, true);
}
<strong> Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri,//加載彩信數據庫中的內容
PDU_PROJECTION, null, null, null);</strong>
PduHeaders headers = new PduHeaders();
Set<Entry<Integer, Integer>> set;
long msgId = ContentUris.parseId(uri);
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();<strong>//解析數據庫中的內容到PduHeaders中。</strong>
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);
<strong>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)) {//構建pduBody
PduPart[] parts = loadParts(msgId);//這部分相信大家可以看懂,同樣是加載數據庫
if (parts != null) {
int partsNum = parts.length;
for (int i = 0; i < partsNum; i++) {
body.addPart(parts[i]);
}
}
}</strong>
switch (msgType) {<strong>//根據msgType,構建GeniricPdu的實例子類型</strong>
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));
}
} finally {
synchronized(PDU_CACHE_INSTANCE) {
if (pdu != null) {
assert(PDU_CACHE_INSTANCE.get(uri) == null);
// Update the cache entry with the real info
cacheEntry = new PduCacheEntry(pdu, msgBox, threadId);
PDU_CACHE_INSTANCE.put(uri, cacheEntry);
}
PDU_CACHE_INSTANCE.setUpdating(uri, false);
PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead
}
}
return pdu;
}