19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007-2008 Esmertec AG.
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007-2008 The Android Open Source Project
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorpackage com.google.android.mms.pdu;
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.ContentType;
21a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.InvalidHeaderValueException;
22a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.MmsException;
23ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport com.google.android.mms.util.DownloadDrmHelper;
24ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport com.google.android.mms.util.DrmConvertSession;
25a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.util.PduCache;
26a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.util.PduCacheEntry;
27a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.util.SqliteWrapper;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentUris;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentValues;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DatabaseUtils;
35ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport android.database.sqlite.SQLiteException;
36ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport android.drm.DrmManagerClient;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
38ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport android.os.FileUtils;
39ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport android.provider.MediaStore;
40a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony;
41a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony.Mms;
42a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony.MmsSms;
43a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony.Threads;
44a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony.Mms.Addr;
45a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony.Mms.Part;
46a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport android.provider.Telephony.MmsSms.PendingMessages;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.ByteArrayOutputStream;
51ca184870ca6db8cda264a466582f19e71f7233cdTom Taylorimport java.io.File;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map.Entry;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
64a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylorimport com.google.android.mms.pdu.EncodedStringValue;
65f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class is the high-level manager of PDU storage.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class PduPersister {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "PduPersister";
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DEBUG = false;
7243a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato    private static final boolean LOCAL_LOGV = false;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long DUMMY_THREAD_ID = Long.MAX_VALUE;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The uri of temporary drm objects.
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String TEMPORARY_DRM_OBJECT_URI =
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "content://mms/" + Long.MAX_VALUE + "/part";
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicate that we transiently failed to process a MM.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PROC_STATUS_TRANSIENT_FAILURE   = 1;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicate that we permanently failed to process a MM.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PROC_STATUS_PERMANENTLY_FAILURE = 2;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicate that we have successfully processed a MM.
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PROC_STATUS_COMPLETED           = 3;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static PduPersister sPersister;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final PduCache PDU_CACHE_INSTANCE;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] ADDRESS_FIELDS = new int[] {
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders.BCC,
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders.CC,
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders.FROM,
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders.TO
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String[] PDU_PROJECTION = new String[] {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms._ID,
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.MESSAGE_BOX,
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.THREAD_ID,
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.RETRIEVE_TEXT,
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.SUBJECT,
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.CONTENT_LOCATION,
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.CONTENT_TYPE,
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.MESSAGE_CLASS,
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.MESSAGE_ID,
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.RESPONSE_TEXT,
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.TRANSACTION_ID,
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.CONTENT_CLASS,
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.DELIVERY_REPORT,
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.MESSAGE_TYPE,
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.MMS_VERSION,
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.PRIORITY,
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.READ_REPORT,
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.READ_STATUS,
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.REPORT_ALLOWED,
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.RETRIEVE_STATUS,
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.STATUS,
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.DATE,
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.DELIVERY_TIME,
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.EXPIRY,
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.MESSAGE_SIZE,
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.SUBJECT_CHARSET,
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Mms.RETRIEVE_TEXT_CHARSET,
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_ID                    = 0;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_MESSAGE_BOX           = 1;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_THREAD_ID             = 2;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_RETRIEVE_TEXT         = 3;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_SUBJECT               = 4;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_CONTENT_LOCATION      = 5;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_CONTENT_TYPE          = 6;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_MESSAGE_CLASS         = 7;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_MESSAGE_ID            = 8;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_RESPONSE_TEXT         = 9;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_TRANSACTION_ID        = 10;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_CONTENT_CLASS         = 11;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_DELIVERY_REPORT       = 12;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_MESSAGE_TYPE          = 13;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_MMS_VERSION           = 14;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_PRIORITY              = 15;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_READ_REPORT           = 16;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_READ_STATUS           = 17;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_REPORT_ALLOWED        = 18;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_RETRIEVE_STATUS       = 19;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_STATUS                = 20;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_DATE                  = 21;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_DELIVERY_TIME         = 22;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_EXPIRY                = 23;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_MESSAGE_SIZE          = 24;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_SUBJECT_CHARSET       = 25;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PDU_COLUMN_RETRIEVE_TEXT_CHARSET = 26;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String[] PART_PROJECTION = new String[] {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part._ID,
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.CHARSET,
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.CONTENT_DISPOSITION,
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.CONTENT_ID,
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.CONTENT_LOCATION,
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.CONTENT_TYPE,
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.FILENAME,
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Part.NAME,
171f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner        Part.TEXT
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_ID                  = 0;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_CHARSET             = 1;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_CONTENT_DISPOSITION = 2;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_CONTENT_ID          = 3;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_CONTENT_LOCATION    = 4;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_CONTENT_TYPE        = 5;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_FILENAME            = 6;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int PART_COLUMN_NAME                = 7;
182f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner    private static final int PART_COLUMN_TEXT                = 8;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Uri, Integer> MESSAGE_BOX_MAP;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // These map are used for convenience in persist() and load().
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, Integer> CHARSET_COLUMN_INDEX_MAP;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, Integer> ENCODED_STRING_COLUMN_INDEX_MAP;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, Integer> TEXT_STRING_COLUMN_INDEX_MAP;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, Integer> OCTET_COLUMN_INDEX_MAP;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, Integer> LONG_COLUMN_INDEX_MAP;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, String> CHARSET_COLUMN_NAME_MAP;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, String> ENCODED_STRING_COLUMN_NAME_MAP;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, String> TEXT_STRING_COLUMN_NAME_MAP;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, String> OCTET_COLUMN_NAME_MAP;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<Integer, String> LONG_COLUMN_NAME_MAP;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MESSAGE_BOX_MAP = new HashMap<Uri, Integer>();
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MESSAGE_BOX_MAP.put(Mms.Inbox.CONTENT_URI,  Mms.MESSAGE_BOX_INBOX);
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MESSAGE_BOX_MAP.put(Mms.Sent.CONTENT_URI,   Mms.MESSAGE_BOX_SENT);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MESSAGE_BOX_MAP.put(Mms.Draft.CONTENT_URI,  Mms.MESSAGE_BOX_DRAFTS);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MESSAGE_BOX_MAP.put(Mms.Outbox.CONTENT_URI, Mms.MESSAGE_BOX_OUTBOX);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CHARSET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT_CHARSET);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT_CHARSET);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CHARSET_COLUMN_NAME_MAP = new HashMap<Integer, String>();
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CHARSET_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT_CHARSET);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CHARSET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT_CHARSET);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Encoded string field code -> column index/name map.
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ENCODED_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ENCODED_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>();
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Text string field code -> column index/name map.
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_LOCATION, PDU_COLUMN_CONTENT_LOCATION);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_TYPE, PDU_COLUMN_CONTENT_TYPE);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_CLASS, PDU_COLUMN_MESSAGE_CLASS);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_ID, PDU_COLUMN_MESSAGE_ID);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RESPONSE_TEXT, PDU_COLUMN_RESPONSE_TEXT);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.TRANSACTION_ID, PDU_COLUMN_TRANSACTION_ID);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>();
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_LOCATION, Mms.CONTENT_LOCATION);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_TYPE, Mms.CONTENT_TYPE);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_CLASS, Mms.MESSAGE_CLASS);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_ID, Mms.MESSAGE_ID);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.RESPONSE_TEXT, Mms.RESPONSE_TEXT);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.TRANSACTION_ID, Mms.TRANSACTION_ID);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Octet field code -> column index/name map.
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_CLASS, PDU_COLUMN_CONTENT_CLASS);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_REPORT, PDU_COLUMN_DELIVERY_REPORT);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_TYPE, PDU_COLUMN_MESSAGE_TYPE);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MMS_VERSION, PDU_COLUMN_MMS_VERSION);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.PRIORITY, PDU_COLUMN_PRIORITY);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_REPORT, PDU_COLUMN_READ_REPORT);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_STATUS, PDU_COLUMN_READ_STATUS);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.REPORT_ALLOWED, PDU_COLUMN_REPORT_ALLOWED);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_STATUS, PDU_COLUMN_RETRIEVE_STATUS);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.STATUS, PDU_COLUMN_STATUS);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP = new HashMap<Integer, String>();
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_CLASS, Mms.CONTENT_CLASS);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_REPORT, Mms.DELIVERY_REPORT);
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_TYPE, Mms.MESSAGE_TYPE);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.MMS_VERSION, Mms.MMS_VERSION);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.PRIORITY, Mms.PRIORITY);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_REPORT, Mms.READ_REPORT);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_STATUS, Mms.READ_STATUS);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.REPORT_ALLOWED, Mms.REPORT_ALLOWED);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_STATUS, Mms.RETRIEVE_STATUS);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OCTET_COLUMN_NAME_MAP.put(PduHeaders.STATUS, Mms.STATUS);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Long field code -> column index/name map.
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_INDEX_MAP.put(PduHeaders.DATE, PDU_COLUMN_DATE);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_TIME, PDU_COLUMN_DELIVERY_TIME);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_INDEX_MAP.put(PduHeaders.EXPIRY, PDU_COLUMN_EXPIRY);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_SIZE, PDU_COLUMN_MESSAGE_SIZE);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_NAME_MAP = new HashMap<Integer, String>();
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_NAME_MAP.put(PduHeaders.DATE, Mms.DATE);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_TIME, Mms.DELIVERY_TIME);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_NAME_MAP.put(PduHeaders.EXPIRY, Mms.EXPIRY);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LONG_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_SIZE, Mms.MESSAGE_SIZE);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PDU_CACHE_INSTANCE = PduCache.getInstance();
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final ContentResolver mContentResolver;
281ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor    private final DrmManagerClient mDrmManagerClient;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PduPersister(Context context) {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContentResolver = context.getContentResolver();
286ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        mDrmManagerClient = new DrmManagerClient(context);
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Get(or create if not exist) an instance of PduPersister */
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static PduPersister getPduPersister(Context context) {
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((sPersister == null) || !context.equals(sPersister.mContext)) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sPersister = new PduPersister(context);
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sPersister;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setEncodedStringValueToHeaders(
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor c, int columnIndex,
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders headers, int mapColumn) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String s = c.getString(columnIndex);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((s != null) && (s.length() > 0)) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int charset = c.getInt(charsetColumnIndex);
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            EncodedStringValue value = new EncodedStringValue(
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    charset, getBytes(s));
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            headers.setEncodedStringValue(value, mapColumn);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setTextStringToHeaders(
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor c, int columnIndex,
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders headers, int mapColumn) {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String s = c.getString(columnIndex);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s != null) {
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            headers.setTextString(getBytes(s), mapColumn);
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setOctetToHeaders(
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor c, int columnIndex,
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders headers, int mapColumn) throws InvalidHeaderValueException {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!c.isNull(columnIndex)) {
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int b = c.getInt(columnIndex);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            headers.setOctet(b, mapColumn);
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setLongToHeaders(
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor c, int columnIndex,
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PduHeaders headers, int mapColumn) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!c.isNull(columnIndex)) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long l = c.getLong(columnIndex);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            headers.setLongInteger(l, mapColumn);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Integer getIntegerFromPartColumn(Cursor c, int columnIndex) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!c.isNull(columnIndex)) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return c.getInt(columnIndex);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private byte[] getByteArrayFromPartColumn(Cursor c, int columnIndex) {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!c.isNull(columnIndex)) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getBytes(c.getString(columnIndex));
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PduPart[] loadParts(long msgId) throws MmsException {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Cursor c = SqliteWrapper.query(mContext, mContentResolver,
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("content://mms/" + msgId + "/part"),
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PART_PROJECTION, null, null, null);
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PduPart[] parts = null;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((c == null) || (c.getCount() == 0)) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (LOCAL_LOGV) {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.v(TAG, "loadParts(" + msgId + "): no part to load.");
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int partCount = c.getCount();
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int partIdx = 0;
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            parts = new PduPart[partCount];
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PduPart part = new PduPart();
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Integer charset = getIntegerFromPartColumn(
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_CHARSET);
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (charset != null) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setCharset(charset);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] contentDisposition = getByteArrayFromPartColumn(
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_CONTENT_DISPOSITION);
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (contentDisposition != null) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setContentDisposition(contentDisposition);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] contentId = getByteArrayFromPartColumn(
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_CONTENT_ID);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (contentId != null) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setContentId(contentId);
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] contentLocation = getByteArrayFromPartColumn(
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_CONTENT_LOCATION);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (contentLocation != null) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setContentLocation(contentLocation);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] contentType = getByteArrayFromPartColumn(
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_CONTENT_TYPE);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (contentType != null) {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setContentType(contentType);
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new MmsException("Content-Type must be set.");
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] fileName = getByteArrayFromPartColumn(
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_FILENAME);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (fileName != null) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setFilename(fileName);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] name = getByteArrayFromPartColumn(
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c, PART_COLUMN_NAME);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (name != null) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setName(name);
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Construct a Uri for this part.
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long partId = c.getLong(PART_COLUMN_ID);
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri partURI = Uri.parse("content://mms/part/" + partId);
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                part.setDataUri(partURI);
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // For images/audio/video, we won't keep their data in Part
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because their renderer accept Uri as source.
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String type = toIsoString(contentType);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!ContentType.isImageType(type)
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        && !ContentType.isAudioType(type)
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        && !ContentType.isVideoType(type)) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    InputStream is = null;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
430f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    // Store simple string values directly in the database instead of an
431f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    // external file.  This makes the text searchable and retrieval slightly
432f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    // faster.
433dbac180d8342a7db2bb9994f937869eecb6b50ffTom Taylor                    if (ContentType.TEXT_PLAIN.equals(type) || ContentType.APP_SMIL.equals(type)
434dbac180d8342a7db2bb9994f937869eecb6b50ffTom Taylor                            || ContentType.TEXT_HTML.equals(type)) {
435f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        String text = c.getString(PART_COLUMN_TEXT);
436b054f275369f3909a2eda1d2ae6a44cf62081d18Mark Wagner                        byte [] blob = new EncodedStringValue(text != null ? text : "")
437b054f275369f3909a2eda1d2ae6a44cf62081d18Mark Wagner                            .getTextString();
438f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        baos.write(blob, 0, blob.length);
439f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    } else {
440f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner
441f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        try {
442f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            is = mContentResolver.openInputStream(partURI);
443f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner
444f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            byte[] buffer = new byte[256];
445f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            int len = is.read(buffer);
446f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            while (len >= 0) {
447f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                baos.write(buffer, 0, len);
448f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                len = is.read(buffer);
449f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            }
450f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        } catch (IOException e) {
451f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            Log.e(TAG, "Failed to load part data", e);
452f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            c.close();
453f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            throw new MmsException(e);
454f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        } finally {
455f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            if (is != null) {
456f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                try {
457f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                    is.close();
458f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                } catch (IOException e) {
459f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                    Log.e(TAG, "Failed to close stream", e);
460f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                                } // Ignore
461f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                            }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    part.setData(baos.toByteArray());
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parts[partIdx++] = part;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (c != null) {
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                c.close();
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return parts;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadAddress(long msgId, PduHeaders headers) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Cursor c = SqliteWrapper.query(mContext, mContentResolver,
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("content://mms/" + msgId + "/addr"),
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new String[] { Addr.ADDRESS, Addr.CHARSET, Addr.TYPE },
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null, null, null);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (c != null) {
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (c.moveToNext()) {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String addr = c.getString(0);
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!TextUtils.isEmpty(addr)) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int addrType = c.getInt(2);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        switch (addrType) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case PduHeaders.FROM:
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                headers.setEncodedStringValue(
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        new EncodedStringValue(c.getInt(1), getBytes(addr)),
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        addrType);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case PduHeaders.TO:
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case PduHeaders.CC:
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            case PduHeaders.BCC:
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                headers.appendEncodedStringValue(
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        new EncodedStringValue(c.getInt(1), getBytes(addr)),
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        addrType);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            default:
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.e(TAG, "Unknown address type: " + addrType);
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                break;
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                c.close();
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Load a PDU from storage by given Uri.
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The Uri of the PDU to be loaded.
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A generic PDU object, it may be cast to dedicated PDU.
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws MmsException Failed to load some fields of a PDU.
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GenericPdu load(Uri uri) throws MmsException {
522733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        GenericPdu pdu = null;
523733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        PduCacheEntry cacheEntry = null;
524733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        int msgBox = 0;
525733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        long threadId = -1;
526733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        try {
527733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            synchronized(PDU_CACHE_INSTANCE) {
528733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
529733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    if (LOCAL_LOGV) {
530733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                        Log.v(TAG, "load: " + uri + " blocked by isUpdating()");
531733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    }
532733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    try {
533733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                        PDU_CACHE_INSTANCE.wait();
534733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    } catch (InterruptedException e) {
535733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                        Log.e(TAG, "load: ", e);
536733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    }
537733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    cacheEntry = PDU_CACHE_INSTANCE.get(uri);
538733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    if (cacheEntry != null) {
539733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                        return cacheEntry.getPdu();
540733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    }
5413b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                }
542733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                // Tell the cache to indicate to other callers that this item
543733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                // is currently being updated.
544733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                PDU_CACHE_INSTANCE.setUpdating(uri, true);
5453b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
547733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri,
548733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    PDU_PROJECTION, null, null, null);
549733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            PduHeaders headers = new PduHeaders();
550733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            Set<Entry<Integer, Integer>> set;
551733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            long msgId = ContentUris.parseId(uri);
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
553733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            try {
554733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) {
555733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    throw new MmsException("Bad uri: " + uri);
556733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
558733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX);
559733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                threadId = c.getLong(PDU_COLUMN_THREAD_ID);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
561733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                set = ENCODED_STRING_COLUMN_INDEX_MAP.entrySet();
562733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                for (Entry<Integer, Integer> e : set) {
563733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    setEncodedStringValueToHeaders(
564733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                            c, e.getValue(), headers, e.getKey());
565733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
567733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                set = TEXT_STRING_COLUMN_INDEX_MAP.entrySet();
568733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                for (Entry<Integer, Integer> e : set) {
569733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    setTextStringToHeaders(
570733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                            c, e.getValue(), headers, e.getKey());
571733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
573733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                set = OCTET_COLUMN_INDEX_MAP.entrySet();
574733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                for (Entry<Integer, Integer> e : set) {
575733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    setOctetToHeaders(
576733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                            c, e.getValue(), headers, e.getKey());
577733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                set = LONG_COLUMN_INDEX_MAP.entrySet();
580733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                for (Entry<Integer, Integer> e : set) {
581733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    setLongToHeaders(
582733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                            c, e.getValue(), headers, e.getKey());
583733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
584733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            } finally {
585733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                if (c != null) {
586733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    c.close();
587733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
590733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            // Check whether 'msgId' has been assigned a valid value.
591733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            if (msgId == -1L) {
592733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                throw new MmsException("Error! ID of the message: -1.");
593733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
595733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            // Load address information of the MM.
596733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            loadAddress(msgId, headers);
597733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor
598733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
599733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            PduBody body = new PduBody();
600733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor
601733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            // For PDU which type is M_retrieve.conf or Send.req, we should
602733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            // load multiparts and put them into the body of the PDU.
603733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
604733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
605733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                PduPart[] parts = loadParts(msgId);
606733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                if (parts != null) {
607733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    int partsNum = parts.length;
608733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    for (int i = 0; i < partsNum; i++) {
609733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                        body.addPart(parts[i]);
610733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
614733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            switch (msgType) {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new NotificationInd(headers);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new DeliveryInd(headers);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new ReadOrigInd(headers);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new RetrieveConf(headers, body);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new SendReq(headers, body);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new AcknowledgeInd(headers);
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new NotifyRespInd(headers);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pdu = new ReadRecInd(headers);
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new MmsException(
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Unsupported PDU type: " + Integer.toHexString(msgType));
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new MmsException(
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Unrecognized PDU type: " + Integer.toHexString(msgType));
661733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            }
662733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        } finally {
663733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            synchronized(PDU_CACHE_INSTANCE) {
664733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                if (pdu != null) {
665733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    assert(PDU_CACHE_INSTANCE.get(uri) == null);
666733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    // Update the cache entry with the real info
667733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    cacheEntry = new PduCacheEntry(pdu, msgBox, threadId);
668733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                    PDU_CACHE_INSTANCE.put(uri, cacheEntry);
669733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                }
670733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                PDU_CACHE_INSTANCE.setUpdating(uri, false);
671733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor                PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead
672733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor            }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
674733e697776dc6f02d04ec3ae9764bb6034ad0e6aTom Taylor        return pdu;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void persistAddress(
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long msgId, int type, EncodedStringValue[] array) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentValues values = new ContentValues(3);
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (EncodedStringValue addr : array) {
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.clear(); // Clear all values first.
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Addr.ADDRESS, toIsoString(addr.getTextString()));
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Addr.CHARSET, addr.getCharacterSet());
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Addr.TYPE, type);
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Uri uri = Uri.parse("content://mms/" + msgId + "/addr");
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SqliteWrapper.insert(mContext, mContentResolver, uri, values);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Uri persistPart(PduPart part, long msgId)
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws MmsException {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Uri uri = Uri.parse("content://mms/" + msgId + "/part");
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentValues values = new ContentValues(8);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int charset = part.getCharset();
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (charset != 0 ) {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CHARSET, charset);
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String contentType = null;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentType() != null) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contentType = toIsoString(part.getContentType());
705e29288629da1771f44623ada19963ca7c71199a7Owen Lin
706e29288629da1771f44623ada19963ca7c71199a7Owen Lin            // There is no "image/jpg" in Android (and it's an invalid mimetype).
707e29288629da1771f44623ada19963ca7c71199a7Owen Lin            // Change it to "image/jpeg"
708e29288629da1771f44623ada19963ca7c71199a7Owen Lin            if (ContentType.IMAGE_JPG.equals(contentType)) {
709e29288629da1771f44623ada19963ca7c71199a7Owen Lin                contentType = ContentType.IMAGE_JPEG;
710e29288629da1771f44623ada19963ca7c71199a7Owen Lin            }
711e29288629da1771f44623ada19963ca7c71199a7Owen Lin
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_TYPE, contentType);
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // To ensure the SMIL part is always the first part.
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ContentType.APP_SMIL.equals(contentType)) {
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                values.put(Part.SEQ, -1);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException("MIME type of the part must be set.");
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getFilename() != null) {
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String fileName = new String(part.getFilename());
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.FILENAME, fileName);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getName() != null) {
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = new String(part.getName());
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.NAME, name);
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object value = null;
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentDisposition() != null) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            value = toIsoString(part.getContentDisposition());
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_DISPOSITION, (String) value);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentId() != null) {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            value = toIsoString(part.getContentId());
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_ID, (String) value);
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentLocation() != null) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            value = toIsoString(part.getContentLocation());
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_LOCATION, (String) value);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res == null) {
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException("Failed to persist part, return null.");
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        persistData(part, res, contentType);
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // After successfully store the data, we should update
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the dataUri of the part.
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        part.setDataUri(res);
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return res;
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Save data of the part into storage. The source data may be given
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by a byte[] or a Uri. If it's a byte[], directly save it
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * into storage, otherwise load source data from the dataUri and then
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * save it. If the data is an image, we may scale down it according
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to user preference.
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param part The PDU part which contains data to be saved.
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI of the part.
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentType The MIME type of the part.
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws MmsException Cannot find source data or error occurred
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         while saving the data.
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void persistData(PduPart part, Uri uri,
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String contentType)
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws MmsException {
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OutputStream os = null;
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputStream is = null;
778ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        DrmConvertSession drmConvertSession = null;
779ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        Uri dataUri = null;
780ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        String path = null;
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            byte[] data = part.getData();
784dbac180d8342a7db2bb9994f937869eecb6b50ffTom Taylor            if (ContentType.TEXT_PLAIN.equals(contentType)
785dbac180d8342a7db2bb9994f937869eecb6b50ffTom Taylor                    || ContentType.APP_SMIL.equals(contentType)
786dbac180d8342a7db2bb9994f937869eecb6b50ffTom Taylor                    || ContentType.TEXT_HTML.equals(contentType)) {
787f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                ContentValues cv = new ContentValues();
788a87afd07c0093cab638e9ef9bc2c53c8200ca711Tom Taylor                cv.put(Telephony.Mms.Part.TEXT, new EncodedStringValue(data).getString());
789f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                if (mContentResolver.update(uri, cv, null, null) != 1) {
790f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    throw new MmsException("unable to update " + uri.toString());
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
793ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                boolean isDrm = DownloadDrmHelper.isDrmConvertNeeded(contentType);
794ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                if (isDrm) {
795ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    if (uri != null) {
796ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        try {
797ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            path = convertUriToPath(mContext, uri);
798ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            if (LOCAL_LOGV) {
799ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                Log.v(TAG, "drm uri: " + uri + " path: " + path);
800ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            }
801ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            File f = new File(path);
802ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            long len = f.length();
803ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            if (LOCAL_LOGV) {
804ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                Log.v(TAG, "drm path: " + path + " len: " + len);
805ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            }
806ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            if (len > 0) {
807ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                // we're not going to re-persist and re-encrypt an already
808ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                // converted drm file
809ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                return;
810ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            }
811ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        } catch (Exception e) {
812ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            Log.e(TAG, "Can't get file info for: " + part.getDataUri(), e);
813ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        }
814ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    }
815ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    // We haven't converted the file yet, start the conversion
816ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    drmConvertSession = DrmConvertSession.open(mContext, contentType);
817ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    if (drmConvertSession == null) {
818ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        throw new MmsException("Mimetype " + contentType +
819ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                " can not be converted.");
820ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    }
821ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                }
822f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                os = mContentResolver.openOutputStream(uri);
823f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                if (data == null) {
824ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    dataUri = part.getDataUri();
825f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    if ((dataUri == null) || (dataUri == uri)) {
826f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        Log.w(TAG, "Can't find data for this part.");
827f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        return;
828f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    }
829f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    is = mContentResolver.openInputStream(dataUri);
830f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner
831f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    if (LOCAL_LOGV) {
832f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        Log.v(TAG, "Saving data to: " + uri);
833f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    }
834f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner
8359962ca12fbafdf642a03ed047c496aae7a893b9aMatthias Thomae                    byte[] buffer = new byte[8192];
836f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    for (int len = 0; (len = is.read(buffer)) != -1; ) {
837ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        if (!isDrm) {
838ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            os.write(buffer, 0, len);
839ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        } else {
840ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            byte[] convertedData = drmConvertSession.convert(buffer, len);
841ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            if (convertedData != null) {
842ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                os.write(convertedData, 0, convertedData.length);
843ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            } else {
844ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                throw new MmsException("Error converting drm data.");
845ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            }
846ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        }
847f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    }
848f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                } else {
849f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    if (LOCAL_LOGV) {
850f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                        Log.v(TAG, "Saving data to: " + uri);
851f4f8a7fe467c2f7514bf528d0a3e8926c2813c0fMark Wagner                    }
852ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    if (!isDrm) {
853ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        os.write(data);
854ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    } else {
855ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        dataUri = uri;
856ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        byte[] convertedData = drmConvertSession.convert(data, data.length);
857ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        if (convertedData != null) {
858ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            os.write(convertedData, 0, convertedData.length);
859ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        } else {
860ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            throw new MmsException("Error converting drm data.");
861ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        }
862ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (FileNotFoundException e) {
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Failed to open Input/Output stream.", e);
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException(e);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Failed to read/write data.", e);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException(e);
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (os != null) {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    os.close();
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (IOException e) {
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.e(TAG, "IOException while closing: " + os, e);
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } // Ignore
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (is != null) {
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    is.close();
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (IOException e) {
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.e(TAG, "IOException while closing: " + is, e);
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } // Ignore
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
886ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            if (drmConvertSession != null) {
887ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                drmConvertSession.close(path);
888ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor
889ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                // Reset the permissions on the encrypted part file so everyone has only read
890ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                // permission.
891ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                File f = new File(path);
892ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                ContentValues values = new ContentValues(0);
893ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                SqliteWrapper.update(mContext, mContentResolver,
894ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                     Uri.parse("content://mms/resetFilePerm/" + f.getName()),
895ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                     values, null, null);
896ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            }
897ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        }
898ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor    }
899ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor
900ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor    /**
901ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     * This method expects uri in the following format
902ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     *     content://media/<table_name>/<row_index> (or)
903ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     *     file://sdcard/test.mp4
904ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     *     http://test.com/test.mp4
905ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     *
906ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     * Here <table_name> shall be "video" or "audio" or "images"
907ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     * <row_index> the index of the content in given table
908ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor     */
909ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor    static public String convertUriToPath(Context context, Uri uri) {
910ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        String path = null;
911ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        if (null != uri) {
912ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            String scheme = uri.getScheme();
913ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            if (null == scheme || scheme.equals("") ||
914ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    scheme.equals(ContentResolver.SCHEME_FILE)) {
915ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                path = uri.getPath();
916ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor
917ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            } else if (scheme.equals("http")) {
918ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                path = uri.toString();
919ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor
920ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
921ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                String[] projection = new String[] {MediaStore.MediaColumns.DATA};
922ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                Cursor cursor = null;
923ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                try {
924ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    cursor = context.getContentResolver().query(uri, projection, null,
925ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            null, null);
926ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
927ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        throw new IllegalArgumentException("Given Uri could not be found" +
928ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                                " in media store");
929ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    }
930ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
931ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    path = cursor.getString(pathIndex);
932ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                } catch (SQLiteException e) {
933ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    throw new IllegalArgumentException("Given Uri is not formatted in a way " +
934ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                            "so that it can be found in media store.");
935ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                } finally {
936ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    if (null != cursor) {
937ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                        cursor.close();
938ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                    }
939ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                }
940ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            } else {
941ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor                throw new IllegalArgumentException("Given Uri scheme is not supported");
942ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor            }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
944ca184870ca6db8cda264a466582f19e71f7233cdTom Taylor        return path;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateAddress(
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long msgId, int type, EncodedStringValue[] array) {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Delete old address information and then insert new ones.
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SqliteWrapper.delete(mContext, mContentResolver,
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("content://mms/" + msgId + "/addr"),
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Addr.TYPE + "=" + type, null);
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        persistAddress(msgId, type, array);
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Update headers of a SendReq.
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The PDU which need to be updated.
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param pdu New headers.
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws MmsException Bad URI or updating failed.
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateHeaders(Uri uri, SendReq sendReq) {
9653b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        synchronized(PDU_CACHE_INSTANCE) {
9663b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // If the cache item is getting updated, wait until it's done updating before
9673b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // purging it.
9683b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
9692dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                if (LOCAL_LOGV) {
9702dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                    Log.v(TAG, "updateHeaders: " + uri + " blocked by isUpdating()");
9712dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                }
9723b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                try {
9733b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    PDU_CACHE_INSTANCE.wait();
9743b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                } catch (InterruptedException e) {
9753b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    Log.e(TAG, "updateHeaders: ", e);
9763b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                }
9773b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
9783b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        }
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PDU_CACHE_INSTANCE.purge(uri);
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
981a67c8cd581e00a28661f7b727bf74727c9a7f688Tom Taylor        ContentValues values = new ContentValues(10);
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] contentType = sendReq.getContentType();
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (contentType != null) {
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.CONTENT_TYPE, toIsoString(contentType));
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long date = sendReq.getDate();
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (date != -1) {
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.DATE, date);
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int deliveryReport = sendReq.getDeliveryReport();
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deliveryReport != 0) {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.DELIVERY_REPORT, deliveryReport);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long expiry = sendReq.getExpiry();
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (expiry != -1) {
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.EXPIRY, expiry);
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] msgClass = sendReq.getMessageClass();
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (msgClass != null) {
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass));
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int priority = sendReq.getPriority();
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (priority != 0) {
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.PRIORITY, priority);
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int readReport = sendReq.getReadReport();
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (readReport != 0) {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.READ_REPORT, readReport);
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] transId = sendReq.getTransactionId();
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (transId != null) {
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.TRANSACTION_ID, toIsoString(transId));
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EncodedStringValue subject = sendReq.getSubject();
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (subject != null) {
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.SUBJECT, toIsoString(subject.getTextString()));
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet());
10266cec6e168b798ebf50fb415bc7377bea56f70271Satish Roddom        } else {
10276cec6e168b798ebf50fb415bc7377bea56f70271Satish Roddom            values.put(Mms.SUBJECT, "");
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1029b054f275369f3909a2eda1d2ae6a44cf62081d18Mark Wagner
1030a67c8cd581e00a28661f7b727bf74727c9a7f688Tom Taylor        long messageSize = sendReq.getMessageSize();
1031a67c8cd581e00a28661f7b727bf74727c9a7f688Tom Taylor        if (messageSize > 0) {
1032a67c8cd581e00a28661f7b727bf74727c9a7f688Tom Taylor            values.put(Mms.MESSAGE_SIZE, messageSize);
1033a67c8cd581e00a28661f7b727bf74727c9a7f688Tom Taylor        }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PduHeaders headers = sendReq.getPduHeaders();
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        HashSet<String> recipients = new HashSet<String>();
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int addrType : ADDRESS_FIELDS) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            EncodedStringValue[] array = null;
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (addrType == PduHeaders.FROM) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                EncodedStringValue v = headers.getEncodedStringValue(addrType);
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (v != null) {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = new EncodedStringValue[1];
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array[0] = v;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = headers.getEncodedStringValues(addrType);
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array != null) {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long msgId = ContentUris.parseId(uri);
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateAddress(msgId, addrType, array);
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (addrType == PduHeaders.TO) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (EncodedStringValue v : array) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (v != null) {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            recipients.add(v.getString());
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1061aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor        if (!recipients.isEmpty()) {
1062aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor            long threadId = Threads.getOrCreateThreadId(mContext, recipients);
1063aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor            values.put(Mms.THREAD_ID, threadId);
1064aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor        }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updatePart(Uri uri, PduPart part) throws MmsException {
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentValues values = new ContentValues(7);
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int charset = part.getCharset();
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (charset != 0 ) {
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CHARSET, charset);
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String contentType = null;
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentType() != null) {
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contentType = toIsoString(part.getContentType());
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_TYPE, contentType);
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException("MIME type of the part must be set.");
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getFilename() != null) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String fileName = new String(part.getFilename());
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.FILENAME, fileName);
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getName() != null) {
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = new String(part.getName());
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.NAME, name);
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object value = null;
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentDisposition() != null) {
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            value = toIsoString(part.getContentDisposition());
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_DISPOSITION, (String) value);
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentId() != null) {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            value = toIsoString(part.getContentId());
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_ID, (String) value);
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (part.getContentLocation() != null) {
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            value = toIsoString(part.getContentLocation());
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values.put(Part.CONTENT_LOCATION, (String) value);
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Only update the data when:
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // 1. New binary data supplied or
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // 2. The Uri of the part is different from the current one.
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((part.getData() != null)
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (uri != part.getDataUri())) {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            persistData(part, uri, contentType);
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Update all parts of a PDU.
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The PDU which need to be updated.
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param body New message body of the PDU.
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws MmsException Bad URI or updating failed.
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateParts(Uri uri, PduBody body)
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws MmsException {
11313b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        try {
11323b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            PduCacheEntry cacheEntry;
11333b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            synchronized(PDU_CACHE_INSTANCE) {
11343b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
11352dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                    if (LOCAL_LOGV) {
11362dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                        Log.v(TAG, "updateParts: " + uri + " blocked by isUpdating()");
11372dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                    }
11383b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    try {
11393b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                        PDU_CACHE_INSTANCE.wait();
11403b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    } catch (InterruptedException e) {
11413b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                        Log.e(TAG, "updateParts: ", e);
11423b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    }
11433b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    cacheEntry = PDU_CACHE_INSTANCE.get(uri);
11443b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    if (cacheEntry != null) {
11453b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                        ((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body);
11463b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    }
11473b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                }
11483b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                // Tell the cache to indicate to other callers that this item
11493b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                // is currently being updated.
11503b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                PDU_CACHE_INSTANCE.setUpdating(uri, true);
11513b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11533b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>();
11543b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            HashMap<Uri, PduPart> toBeUpdated = new HashMap<Uri, PduPart>();
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11563b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            int partsNum = body.getPartsNum();
11573b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            StringBuilder filter = new StringBuilder().append('(');
11583b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            for (int i = 0; i < partsNum; i++) {
11593b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                PduPart part = body.getPart(i);
11603b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                Uri partUri = part.getDataUri();
11613b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                if ((partUri == null) || !partUri.getAuthority().startsWith("mms")) {
11623b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    toBeCreated.add(part);
11633b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                } else {
11643b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    toBeUpdated.put(partUri, part);
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11663b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    // Don't use 'i > 0' to determine whether we should append
11673b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    // 'AND' since 'i = 0' may be skipped in another branch.
11683b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    if (filter.length() > 1) {
11693b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                        filter.append(" AND ");
11703b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11723b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    filter.append(Part._ID);
11733b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    filter.append("!=");
11743b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment());
11753b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11773b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            filter.append(')');
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11793b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            long msgId = ContentUris.parseId(uri);
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11813b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // Remove the parts which doesn't exist anymore.
11823b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            SqliteWrapper.delete(mContext, mContentResolver,
11833b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"),
11843b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    filter.length() > 2 ? filter.toString() : null, null);
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11863b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // Create new parts which didn't exist before.
11873b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            for (PduPart part : toBeCreated) {
11883b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                persistPart(part, msgId);
11893b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11913b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // Update the modified parts.
11923b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            for (Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
11933b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                updatePart(e.getKey(), e.getValue());
11943b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
11953b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        } finally {
11963b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            synchronized(PDU_CACHE_INSTANCE) {
11973b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                PDU_CACHE_INSTANCE.setUpdating(uri, false);
11983b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                PDU_CACHE_INSTANCE.notifyAll();
11993b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Persist a PDU object to specific location in the storage.
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param pdu The PDU object to be stored.
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri Where to store the given PDU object.
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A Uri which can be used to access the stored PDU.
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Uri persist(GenericPdu pdu, Uri uri) throws MmsException {
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (uri == null) {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException("Uri may not be null.");
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12143b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        long msgId = -1;
12153b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        try {
12163b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            msgId = ContentUris.parseId(uri);
12173b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        } catch (NumberFormatException e) {
12183b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // the uri ends with "inbox" or something else like that
12193b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        }
12203b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        boolean existingUri = msgId != -1;
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12223b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        if (!existingUri && MESSAGE_BOX_MAP.get(uri) == null) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException(
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Bad destination, must be one of "
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "content://mms/inbox, content://mms/sent, "
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "content://mms/drafts, content://mms/outbox, "
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "content://mms/temp.");
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12293b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        synchronized(PDU_CACHE_INSTANCE) {
12303b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // If the cache item is getting updated, wait until it's done updating before
12313b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // purging it.
12323b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
12332dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                if (LOCAL_LOGV) {
12342dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                    Log.v(TAG, "persist: " + uri + " blocked by isUpdating()");
12352dc6c7fa48d749773e5ccbc98633d7cf9d35e7acTom Taylor                }
12363b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                try {
12373b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    PDU_CACHE_INSTANCE.wait();
12383b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                } catch (InterruptedException e) {
12393b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                    Log.e(TAG, "persist1: ", e);
12403b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                }
12413b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
12423b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        }
12434ddacd014bee1bdb14239cc9d4bc763a8601a7a6Tom Taylor        PDU_CACHE_INSTANCE.purge(uri);
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PduHeaders header = pdu.getPduHeaders();
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PduBody body = null;
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentValues values = new ContentValues();
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Set<Entry<Integer, String>> set;
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        set = ENCODED_STRING_COLUMN_NAME_MAP.entrySet();
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Entry<Integer, String> e : set) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int field = e.getKey();
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            EncodedStringValue encodedString = header.getEncodedStringValue(field);
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (encodedString != null) {
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field);
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                values.put(e.getValue(), toIsoString(encodedString.getTextString()));
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                values.put(charsetColumn, encodedString.getCharacterSet());
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        set = TEXT_STRING_COLUMN_NAME_MAP.entrySet();
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Entry<Integer, String> e : set){
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            byte[] text = header.getTextString(e.getKey());
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (text != null) {
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                values.put(e.getValue(), toIsoString(text));
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        set = OCTET_COLUMN_NAME_MAP.entrySet();
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Entry<Integer, String> e : set){
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int b = header.getOctet(e.getKey());
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (b != 0) {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                values.put(e.getValue(), b);
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        set = LONG_COLUMN_NAME_MAP.entrySet();
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Entry<Integer, String> e : set){
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long l = header.getLongInteger(e.getKey());
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (l != -1L) {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                values.put(e.getValue(), l);
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        HashMap<Integer, EncodedStringValue[]> addressMap =
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new HashMap<Integer, EncodedStringValue[]>(ADDRESS_FIELDS.length);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Save address information.
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int addrType : ADDRESS_FIELDS) {
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            EncodedStringValue[] array = null;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (addrType == PduHeaders.FROM) {
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                EncodedStringValue v = header.getEncodedStringValue(addrType);
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (v != null) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = new EncodedStringValue[1];
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array[0] = v;
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                array = header.getEncodedStringValues(addrType);
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addressMap.put(addrType, array);
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        HashSet<String> recipients = new HashSet<String>();
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int msgType = pdu.getMessageType();
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Here we only allocate thread ID for M-Notification.ind,
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // M-Retrieve.conf and M-Send.req.
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Some of other PDU types may be allocated a thread ID outside
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this scope.
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND)
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            EncodedStringValue[] array = null;
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msgType) {
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = addressMap.get(PduHeaders.FROM);
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case PduHeaders.MESSAGE_TYPE_SEND_REQ:
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    array = addressMap.get(PduHeaders.TO);
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array != null) {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (EncodedStringValue v : array) {
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (v != null) {
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        recipients.add(v.getString());
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1329aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor            if (!recipients.isEmpty()) {
1330aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor                long threadId = Threads.getOrCreateThreadId(mContext, recipients);
1331aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor                values.put(Mms.THREAD_ID, threadId);
1332aad847cb0c9af8734bd51ca779b9762e51525c76Tom Taylor            }
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Save parts first to avoid inconsistent message is loaded
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // while saving the parts.
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long dummyId = System.currentTimeMillis(); // Dummy ID of the msg.
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get body if the PDU is a RetrieveConf or SendReq.
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pdu instanceof MultimediaMessagePdu) {
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            body = ((MultimediaMessagePdu) pdu).getBody();
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Start saving parts if necessary.
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (body != null) {
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int partsNum = body.getPartsNum();
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < partsNum; i++) {
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    PduPart part = body.getPart(i);
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    persistPart(part, dummyId);
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13513b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        Uri res = null;
13523b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        if (existingUri) {
13533b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            res = uri;
13543b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            SqliteWrapper.update(mContext, mContentResolver, res, values, null, null);
13553b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        } else {
13563b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
13573b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            if (res == null) {
13583b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor                throw new MmsException("persist() failed: return null.");
13593b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            }
13603b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // Get the real ID of the PDU and update all parts which were
13613b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            // saved with the dummy ID.
13623b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            msgId = ContentUris.parseId(res);
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        values = new ContentValues(1);
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        values.put(Part.MSG_ID, msgId);
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SqliteWrapper.update(mContext, mContentResolver,
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             Uri.parse("content://mms/" + dummyId + "/part"),
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             values, null, null);
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We should return the longest URI of the persisted PDU, for
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // example, if input URI is "content://mms/inbox" and the _ID of
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // persisted PDU is '8', we should return "content://mms/inbox/8"
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // instead of "content://mms/8".
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // FIXME: Should the MmsProvider be responsible for this???
13753b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        if (!existingUri) {
13763b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor            res = Uri.parse(uri + "/" + msgId);
13773b259a09635f0670e416adb906f0ed69cd74f7fcTom Taylor        }
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Save address information.
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int addrType : ADDRESS_FIELDS) {
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            EncodedStringValue[] array = addressMap.get(addrType);
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array != null) {
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                persistAddress(msgId, addrType, array);
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return res;
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Move a PDU object from one location to another.
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param from Specify the PDU object to be moved.
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param to The destination location, should be one of the following:
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        "content://mms/inbox", "content://mms/sent",
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        "content://mms/drafts", "content://mms/outbox",
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        "content://mms/trash".
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return New Uri of the moved PDU.
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws MmsException Error occurred while moving the message.
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Uri move(Uri from, Uri to) throws MmsException {
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether the 'msgId' has been assigned a valid value.
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long msgId = ContentUris.parseId(from);
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (msgId == -1L) {
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException("Error! ID of the message: -1.");
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get corresponding int value of destination box.
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer msgBox = MESSAGE_BOX_MAP.get(to);
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (msgBox == null) {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new MmsException(
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Bad destination, must be one of "
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "content://mms/inbox, content://mms/sent, "
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "content://mms/drafts, content://mms/outbox, "
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "content://mms/temp.");
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentValues values = new ContentValues(1);
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        values.put(Mms.MESSAGE_BOX, msgBox);
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SqliteWrapper.update(mContext, mContentResolver, from, values, null, null);
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ContentUris.withAppendedId(to, msgId);
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Wrap a byte[] into a String.
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String toIsoString(byte[] bytes) {
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1);
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (UnsupportedEncodingException e) {
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Impossible to reach here!
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "ISO_8859_1 must be supported!", e);
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "";
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unpack a given String into a byte[].
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static byte[] getBytes(String data) {
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (UnsupportedEncodingException e) {
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Impossible to reach here!
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "ISO_8859_1 must be supported!", e);
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new byte[0];
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove all objects in the temporary path.
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void release() {
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Uri uri = Uri.parse(TEMPORARY_DRM_OBJECT_URI);
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SqliteWrapper.delete(mContext, mContentResolver, uri, null, null);
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Find all messages to be sent or downloaded before certain time.
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Cursor getPendingMessages(long dueTime) {
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon();
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uriBuilder.appendQueryParameter("protocol", "mms");
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String selection = PendingMessages.ERROR_TYPE + " < ?"
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " AND " + PendingMessages.DUE_TIME + " <= ?";
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String[] selectionArgs = new String[] {
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String.valueOf(MmsSms.ERR_TYPE_GENERIC_PERMANENT),
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String.valueOf(dueTime)
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return SqliteWrapper.query(mContext, mContentResolver,
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uriBuilder.build(), null, selection, selectionArgs,
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PendingMessages.DUE_TIME);
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1478