172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007-2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007-2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.transaction;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20161c9154aa7aafa397332caee40b2776db988bf7Christian Gustafssonimport com.android.mms.MmsConfig;
2113dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huangimport com.android.mms.ui.MessageUtils;
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.DownloadManager;
233239889e9a417617b755d4cde22070843e5c070bTom Taylorimport com.android.mms.util.Recycler;
24f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.MmsException;
25f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.AcknowledgeInd;
26f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduComposer;
27f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduHeaders;
28f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduParser;
29f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduPersister;
30f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.RetrieveConf;
31f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.EncodedStringValue;
32fd644551e8506266aad2b76463b51b44154ed62fTom Taylorimport android.database.sqlite.SqliteWrapper;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentValues;
3572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
38f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms;
39f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms.Inbox;
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.io.IOException;
4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * The RetrieveTransaction is responsible for retrieving multimedia
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * messages (M-Retrieve.conf) from the MMSC server.  It:
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <ul>
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Sends a GET request to the MMSC server.
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Retrieves the binary M-Retrieve.conf data and parses it.
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Persists the retrieve multimedia message.
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Determines whether an acknowledgement is required.
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Creates appropriate M-Acknowledge.ind and sends it to MMSC server.
5472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Notifies the TransactionService about succesful completion.
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * </ul>
5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class RetrieveTransaction extends Transaction implements Runnable {
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String TAG = "RetrieveTransaction";
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean DEBUG = false;
60150c4179995cc0a75f934ef194372f9295957ca2Joe Onorato    private static final boolean LOCAL_LOGV = false;
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final Uri mUri;
633b9acf897f4bdd4d76cbcf10d7bd2728c941c7d5Christian Gustafsson    private final String mContentLocation;
64864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    private boolean mLocked;
65864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor
66864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    static final String[] PROJECTION = new String[] {
67864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor        Mms.CONTENT_LOCATION,
68864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor        Mms.LOCKED
69864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    };
70864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor
71864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    // The indexes of the columns which must be consistent with above PROJECTION.
72864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    static final int COLUMN_CONTENT_LOCATION      = 0;
73864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    static final int COLUMN_LOCKED                = 1;
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public RetrieveTransaction(Context context, int serviceId,
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            TransactionSettings connectionSettings, String uri)
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throws MmsException {
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super(context, serviceId, connectionSettings);
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (uri.startsWith("content://")) {
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mUri = Uri.parse(uri); // The Uri of the M-Notification.ind
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mId = mContentLocation = getContentLocation(context, mUri);
8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (LOCAL_LOGV) {
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Log.v(TAG, "X-Mms-Content-Location: " + mContentLocation);
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throw new IllegalArgumentException(
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    "Initializing from X-Mms-Content-Location is abandoned!");
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Attach the transaction to the instance of RetryScheduler.
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        attach(RetryScheduler.getInstance(context));
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
95864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor    private String getContentLocation(Context context, Uri uri)
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throws MmsException {
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
98864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                            uri, PROJECTION, null, null, null);
99864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor        mLocked = false;
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (cursor != null) {
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            try {
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if ((cursor.getCount() == 1) && cursor.moveToFirst()) {
104864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                    // Get the locked flag from the M-Notification.ind so it can be transferred
105864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                    // to the real message after the download.
106864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                    mLocked = cursor.getInt(COLUMN_LOCKED) == 1;
107864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                    return cursor.getString(COLUMN_CONTENT_LOCATION);
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } finally {
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                cursor.close();
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        throw new MmsException("Cannot get X-Mms-Content-Location from: " + uri);
11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /*
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * (non-Javadoc)
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @see com.android.mms.transaction.Transaction#process()
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void process() {
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        new Thread(this).start();
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void run() {
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Change the downloading state of the M-Notification.ind.
12972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            DownloadManager.getInstance().markState(
13072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mUri, DownloadManager.STATE_DOWNLOADING);
13172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Send GET request to MMSC and retrieve the response data.
13372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            byte[] resp = getPdu(mContentLocation);
13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Parse M-Retrieve.conf
13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            RetrieveConf retrieveConf = (RetrieveConf) new PduParser(resp).parse();
13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (null == retrieveConf) {
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                throw new MmsException("Invalid M-Retrieve.conf PDU.");
13972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
14072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
141512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor            Uri msgUri = null;
14272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (isDuplicateMessage(mContext, retrieveConf)) {
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Mark this transaction as failed to prevent duplicate
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // notification to user.
14572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mTransactionState.setState(TransactionState.FAILED);
14672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mTransactionState.setContentUri(mUri);
14772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Store M-Retrieve.conf into Inbox
14972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                PduPersister persister = PduPersister.getPduPersister(mContext);
150512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor                msgUri = persister.persist(retrieveConf, Inbox.CONTENT_URI);
15172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15269481afff1b27e1d8b31e1450430aeb8bc6a2d07Matthias Thomae                // Use local time instead of PDU time
15369481afff1b27e1d8b31e1450430aeb8bc6a2d07Matthias Thomae                ContentValues values = new ContentValues(1);
15469481afff1b27e1d8b31e1450430aeb8bc6a2d07Matthias Thomae                values.put(Mms.DATE, System.currentTimeMillis() / 1000L);
15569481afff1b27e1d8b31e1450430aeb8bc6a2d07Matthias Thomae                SqliteWrapper.update(mContext, mContext.getContentResolver(),
15669481afff1b27e1d8b31e1450430aeb8bc6a2d07Matthias Thomae                        msgUri, values, null, null);
15769481afff1b27e1d8b31e1450430aeb8bc6a2d07Matthias Thomae
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // The M-Retrieve.conf has been successfully downloaded.
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mTransactionState.setState(TransactionState.SUCCESS);
160512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor                mTransactionState.setContentUri(msgUri);
16172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Remember the location the message was downloaded from.
16272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Since it's not critical, it won't fail the transaction.
163864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                // Copy over the locked flag from the M-Notification.ind in case
164864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                // the user locked the message before activating the download.
165864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                updateContentLocation(mContext, msgUri, mContentLocation, mLocked);
16672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
16772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Delete the corresponding M-Notification.ind.
16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            SqliteWrapper.delete(mContext, mContext.getContentResolver(),
17072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                 mUri, null, null);
17172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
172512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor            if (msgUri != null) {
173512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor                // Have to delete messages over limit *after* the delete above. Otherwise,
174512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor                // it would be counted as part of the total.
175512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor                Recycler.getMmsRecycler().deleteOldMessagesInSameThreadAsMessage(mContext, msgUri);
176512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor            }
177512681a5702e1ba6df0b7298c7737598a4e9aa8eTom Taylor
17872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Send ACK to the Proxy-Relay to indicate we have fetched the
17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // MM successfully.
18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Don't mark the transaction as failed if we failed to send it.
18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            sendAcknowledgeInd(retrieveConf);
182591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project        } catch (Throwable t) {
183591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project            Log.e(TAG, Log.getStackTraceString(t));
18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } finally {
18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (mTransactionState.getState() != TransactionState.SUCCESS) {
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mTransactionState.setState(TransactionState.FAILED);
18772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mTransactionState.setContentUri(mUri);
18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Log.e(TAG, "Retrieval failed.");
18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            notifyObservers();
19172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
19272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
19372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
19472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static boolean isDuplicateMessage(Context context, RetrieveConf rc) {
19572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        byte[] rawMessageId = rc.getMessageId();
19672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (rawMessageId != null) {
19772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String messageId = new String(rawMessageId);
19872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String selection = "(" + Mms.MESSAGE_ID + " = ? AND "
19972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                   + Mms.MESSAGE_TYPE + " = ?)";
20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String[] selectionArgs = new String[] { messageId,
20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    String.valueOf(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) };
20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Cursor cursor = SqliteWrapper.query(
20372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    context, context.getContentResolver(),
20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Mms.CONTENT_URI, new String[] { Mms._ID },
20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    selection, selectionArgs, null);
20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (cursor != null) {
20772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                try {
20872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (cursor.getCount() > 0) {
20972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        // We already received the same message before.
21072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return true;
21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
21272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } finally {
21372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    cursor.close();
21472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
21572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
21672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
21772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return false;
21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22013dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huang    private void sendAcknowledgeInd(RetrieveConf rc) throws MmsException, IOException {
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Send M-Acknowledge.ind to MMSC if required.
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // If the Transaction-ID isn't set in the M-Retrieve.conf, it means
22372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // the MMS proxy-relay doesn't require an ACK.
22472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        byte[] tranId = rc.getTransactionId();
22572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (tranId != null) {
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Create M-Acknowledge.ind
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            AcknowledgeInd acknowledgeInd = new AcknowledgeInd(
22872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    PduHeaders.CURRENT_MMS_VERSION, tranId);
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23013dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huang            // insert the 'from' address per spec
23113dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huang            String lineNumber = MessageUtils.getLocalNumber();
23213dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huang            acknowledgeInd.setFrom(new EncodedStringValue(lineNumber));
23313dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huang
23472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Pack M-Acknowledge.ind and send it
235161c9154aa7aafa397332caee40b2776db988bf7Christian Gustafsson            if(MmsConfig.getNotifyWapMMSC()) {
236161c9154aa7aafa397332caee40b2776db988bf7Christian Gustafsson                sendPdu(new PduComposer(mContext, acknowledgeInd).make(), mContentLocation);
237161c9154aa7aafa397332caee40b2776db988bf7Christian Gustafsson            } else {
238161c9154aa7aafa397332caee40b2776db988bf7Christian Gustafsson                sendPdu(new PduComposer(mContext, acknowledgeInd).make());
239161c9154aa7aafa397332caee40b2776db988bf7Christian Gustafsson            }
24072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
24372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static void updateContentLocation(Context context, Uri uri,
244864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                                              String contentLocation,
245864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor                                              boolean locked) {
246864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor        ContentValues values = new ContentValues(2);
24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        values.put(Mms.CONTENT_LOCATION, contentLocation);
248864d15179e4b6987e9cf97930d1033ffc2faa228Tom Taylor        values.put(Mms.LOCKED, locked);     // preserve the state of the M-Notification.ind lock.
24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SqliteWrapper.update(context, context.getContentResolver(),
25072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                             uri, values, null, null);
25172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
25272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
25372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
25472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public int getType() {
25572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return RETRIEVE_TRANSACTION;
25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
258