1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2007-2008 Esmertec AG. 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2007-2008 The Android Open Source Project 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.mmslib.pdu; 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ContentResolver; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ContentUris; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ContentValues; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.DatabaseUtils; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.sqlite.SQLiteException; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.MediaStore; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony.Mms; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony.Mms.Addr; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony.Mms.Part; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony.MmsSms; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony.MmsSms.PendingMessages; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.util.ArrayMap; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.util.SimpleArrayMap; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.telephony.PhoneNumberUtils; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.Log; 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.SparseArray; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.SparseIntArray; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.InvalidHeaderValueException; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.MmsException; 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.SqliteWrapper; 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.util.DownloadDrmHelper; 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.util.DrmConvertSession; 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.util.PduCache; 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.util.PduCacheEntry; 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsSmsUtils; 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert; 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ContentType; 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.OsUtil; 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.ByteArrayOutputStream; 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.File; 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.FileNotFoundException; 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.IOException; 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.InputStream; 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.OutputStream; 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.UnsupportedEncodingException; 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.ArrayList; 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.HashSet; 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Map; 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This class is the high-level manager of PDU storage. 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class PduPersister { 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = "PduPersister"; 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final boolean LOCAL_LOGV = false; 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * The uri of temporary drm objects. 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String TEMPORARY_DRM_OBJECT_URI = 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "content://mms/" + Long.MAX_VALUE + "/part"; 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Indicate that we transiently failed to process a MM. 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PROC_STATUS_TRANSIENT_FAILURE = 1; 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Indicate that we permanently failed to process a MM. 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PROC_STATUS_PERMANENTLY_FAILURE = 2; 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Indicate that we have successfully processed a MM. 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PROC_STATUS_COMPLETED = 3; 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String BEGIN_VCARD = "BEGIN:VCARD"; 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static PduPersister sPersister; 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final PduCache PDU_CACHE_INSTANCE; 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int[] ADDRESS_FIELDS = new int[]{ 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduHeaders.BCC, 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduHeaders.CC, 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduHeaders.FROM, 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduHeaders.TO 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PDU_PROJECTION = new String[]{ 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms._ID, 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.MESSAGE_BOX, 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.THREAD_ID, 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.RETRIEVE_TEXT, 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.SUBJECT, 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.CONTENT_LOCATION, 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.CONTENT_TYPE, 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.MESSAGE_CLASS, 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.MESSAGE_ID, 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.RESPONSE_TEXT, 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.TRANSACTION_ID, 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.CONTENT_CLASS, 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.DELIVERY_REPORT, 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.MESSAGE_TYPE, 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.MMS_VERSION, 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.PRIORITY, 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.READ_REPORT, 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.READ_STATUS, 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.REPORT_ALLOWED, 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.RETRIEVE_STATUS, 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.STATUS, 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.DATE, 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.DELIVERY_TIME, 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.EXPIRY, 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.MESSAGE_SIZE, 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.SUBJECT_CHARSET, 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.RETRIEVE_TEXT_CHARSET, 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.READ, 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Mms.SEEN, 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_ID = 0; 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_MESSAGE_BOX = 1; 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_THREAD_ID = 2; 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_RETRIEVE_TEXT = 3; 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_SUBJECT = 4; 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_CONTENT_LOCATION = 5; 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_CONTENT_TYPE = 6; 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_MESSAGE_CLASS = 7; 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_MESSAGE_ID = 8; 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_RESPONSE_TEXT = 9; 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_TRANSACTION_ID = 10; 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_CONTENT_CLASS = 11; 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_DELIVERY_REPORT = 12; 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_MESSAGE_TYPE = 13; 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_MMS_VERSION = 14; 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_PRIORITY = 15; 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_READ_REPORT = 16; 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_READ_STATUS = 17; 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_REPORT_ALLOWED = 18; 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_RETRIEVE_STATUS = 19; 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_STATUS = 20; 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_DATE = 21; 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_DELIVERY_TIME = 22; 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_EXPIRY = 23; 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_MESSAGE_SIZE = 24; 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_SUBJECT_CHARSET = 25; 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_RETRIEVE_TEXT_CHARSET = 26; 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_READ = 27; 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int PDU_COLUMN_SEEN = 28; 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String[] PART_PROJECTION = new String[] { 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part._ID, 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.CHARSET, 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.CONTENT_DISPOSITION, 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.CONTENT_ID, 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.CONTENT_LOCATION, 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.CONTENT_TYPE, 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.FILENAME, 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.NAME, 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Part.TEXT 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_ID = 0; 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_CHARSET = 1; 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_CONTENT_DISPOSITION = 2; 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_CONTENT_ID = 3; 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_CONTENT_LOCATION = 4; 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_CONTENT_TYPE = 5; 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_FILENAME = 6; 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_NAME = 7; 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PART_COLUMN_TEXT = 8; 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SimpleArrayMap<Uri, Integer> MESSAGE_BOX_MAP; 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // These map are used for convenience in persist() and load(). 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseIntArray CHARSET_COLUMN_INDEX_MAP; 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseIntArray ENCODED_STRING_COLUMN_INDEX_MAP; 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseIntArray TEXT_STRING_COLUMN_INDEX_MAP; 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseIntArray OCTET_COLUMN_INDEX_MAP; 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseIntArray LONG_COLUMN_INDEX_MAP; 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseArray<String> CHARSET_COLUMN_NAME_MAP; 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseArray<String> ENCODED_STRING_COLUMN_NAME_MAP; 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseArray<String> TEXT_STRING_COLUMN_NAME_MAP; 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseArray<String> OCTET_COLUMN_NAME_MAP; 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SparseArray<String> LONG_COLUMN_NAME_MAP; 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static { 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MESSAGE_BOX_MAP = new SimpleArrayMap<Uri, Integer>(); 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MESSAGE_BOX_MAP.put(Mms.Inbox.CONTENT_URI, Mms.MESSAGE_BOX_INBOX); 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MESSAGE_BOX_MAP.put(Mms.Sent.CONTENT_URI, Mms.MESSAGE_BOX_SENT); 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MESSAGE_BOX_MAP.put(Mms.Draft.CONTENT_URI, Mms.MESSAGE_BOX_DRAFTS); 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MESSAGE_BOX_MAP.put(Mms.Outbox.CONTENT_URI, Mms.MESSAGE_BOX_OUTBOX); 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CHARSET_COLUMN_INDEX_MAP = new SparseIntArray(); 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT_CHARSET); 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT_CHARSET); 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CHARSET_COLUMN_NAME_MAP = new SparseArray<String>(); 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CHARSET_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT_CHARSET); 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CHARSET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT_CHARSET); 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Encoded string field code -> column index/name map. 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_INDEX_MAP = new SparseIntArray(); 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT); 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT); 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_NAME_MAP = new SparseArray<String>(); 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT); 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT); 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Text string field code -> column index/name map. 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP = new SparseIntArray(); 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_LOCATION, PDU_COLUMN_CONTENT_LOCATION); 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_TYPE, PDU_COLUMN_CONTENT_TYPE); 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_CLASS, PDU_COLUMN_MESSAGE_CLASS); 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_ID, PDU_COLUMN_MESSAGE_ID); 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RESPONSE_TEXT, PDU_COLUMN_RESPONSE_TEXT); 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.TRANSACTION_ID, PDU_COLUMN_TRANSACTION_ID); 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP = new SparseArray<String>(); 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_LOCATION, Mms.CONTENT_LOCATION); 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_TYPE, Mms.CONTENT_TYPE); 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_CLASS, Mms.MESSAGE_CLASS); 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_ID, Mms.MESSAGE_ID); 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.RESPONSE_TEXT, Mms.RESPONSE_TEXT); 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.TRANSACTION_ID, Mms.TRANSACTION_ID); 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Octet field code -> column index/name map. 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP = new SparseIntArray(); 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_CLASS, PDU_COLUMN_CONTENT_CLASS); 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_REPORT, PDU_COLUMN_DELIVERY_REPORT); 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_TYPE, PDU_COLUMN_MESSAGE_TYPE); 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MMS_VERSION, PDU_COLUMN_MMS_VERSION); 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.PRIORITY, PDU_COLUMN_PRIORITY); 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_REPORT, PDU_COLUMN_READ_REPORT); 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_STATUS, PDU_COLUMN_READ_STATUS); 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.REPORT_ALLOWED, PDU_COLUMN_REPORT_ALLOWED); 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_STATUS, PDU_COLUMN_RETRIEVE_STATUS); 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.put(PduHeaders.STATUS, PDU_COLUMN_STATUS); 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP = new SparseArray<String>(); 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_CLASS, Mms.CONTENT_CLASS); 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_REPORT, Mms.DELIVERY_REPORT); 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_TYPE, Mms.MESSAGE_TYPE); 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.MMS_VERSION, Mms.MMS_VERSION); 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.PRIORITY, Mms.PRIORITY); 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_REPORT, Mms.READ_REPORT); 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_STATUS, Mms.READ_STATUS); 277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.REPORT_ALLOWED, Mms.REPORT_ALLOWED); 278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_STATUS, Mms.RETRIEVE_STATUS); 279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_NAME_MAP.put(PduHeaders.STATUS, Mms.STATUS); 280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Long field code -> column index/name map. 282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_INDEX_MAP = new SparseIntArray(); 283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_INDEX_MAP.put(PduHeaders.DATE, PDU_COLUMN_DATE); 284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_TIME, PDU_COLUMN_DELIVERY_TIME); 285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_INDEX_MAP.put(PduHeaders.EXPIRY, PDU_COLUMN_EXPIRY); 286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_SIZE, PDU_COLUMN_MESSAGE_SIZE); 287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_NAME_MAP = new SparseArray<String>(); 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_NAME_MAP.put(PduHeaders.DATE, Mms.DATE); 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_TIME, Mms.DELIVERY_TIME); 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_NAME_MAP.put(PduHeaders.EXPIRY, Mms.EXPIRY); 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_SIZE, Mms.MESSAGE_SIZE); 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE = PduCache.getInstance(); 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final Context mContext; 298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final ContentResolver mContentResolver; 300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private PduPersister(final Context context) { 302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContext = context; 303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContentResolver = context.getContentResolver(); 304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** Get(or create if not exist) an instance of PduPersister */ 307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static PduPersister getPduPersister(final Context context) { 308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((sPersister == null) || !context.equals(sPersister.mContext)) { 309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sPersister = new PduPersister(context); 310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "PduPersister getPduPersister"); 313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return sPersister; 316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void setEncodedStringValueToHeaders( 319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c, final int columnIndex, 320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers, final int mapColumn) { 321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String s = c.getString(columnIndex); 322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((s != null) && (s.length() > 0)) { 323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn); 324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int charset = c.getInt(charsetColumnIndex); 325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue value = new EncodedStringValue( 326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd charset, getBytes(s)); 327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd headers.setEncodedStringValue(value, mapColumn); 328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void setTextStringToHeaders( 332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c, final int columnIndex, 333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers, final int mapColumn) { 334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String s = c.getString(columnIndex); 335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (s != null) { 336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd headers.setTextString(getBytes(s), mapColumn); 337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void setOctetToHeaders( 341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c, final int columnIndex, 342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers, final int mapColumn) throws InvalidHeaderValueException { 343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!c.isNull(columnIndex)) { 344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int b = c.getInt(columnIndex); 345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd headers.setOctet(b, mapColumn); 346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void setLongToHeaders( 350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c, final int columnIndex, 351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers, final int mapColumn) { 352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!c.isNull(columnIndex)) { 353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long l = c.getLong(columnIndex); 354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd headers.setLongInteger(l, mapColumn); 355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private Integer getIntegerFromPartColumn(final Cursor c, final int columnIndex) { 359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!c.isNull(columnIndex)) { 360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return c.getInt(columnIndex); 361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private byte[] getByteArrayFromPartColumn(final Cursor c, final int columnIndex) { 366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!c.isNull(columnIndex)) { 367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return getBytes(c.getString(columnIndex)); 368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private PduPart[] loadParts(final long msgId) throws MmsException { 373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c = SqliteWrapper.query(mContext, mContentResolver, 374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri.parse("content://mms/" + msgId + "/part"), 375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PART_PROJECTION, null, null, null); 376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduPart[] parts = null; 378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((c == null) || (c.getCount() == 0)) { 381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 382d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "loadParts(" + msgId + "): no part to load."); 383d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int partCount = c.getCount(); 388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int partIdx = 0; 389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd parts = new PduPart[partCount]; 390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (c.moveToNext()) { 391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduPart part = new PduPart(); 392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Integer charset = getIntegerFromPartColumn( 393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_CHARSET); 394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (charset != null) { 395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setCharset(charset); 396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] contentDisposition = getByteArrayFromPartColumn( 399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_CONTENT_DISPOSITION); 400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentDisposition != null) { 401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setContentDisposition(contentDisposition); 402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] contentId = getByteArrayFromPartColumn( 405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_CONTENT_ID); 406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentId != null) { 407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setContentId(contentId); 408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] contentLocation = getByteArrayFromPartColumn( 411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_CONTENT_LOCATION); 412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentLocation != null) { 413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setContentLocation(contentLocation); 414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] contentType = getByteArrayFromPartColumn( 417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_CONTENT_TYPE); 418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentType != null) { 419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setContentType(contentType); 420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Content-Type must be set."); 422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] fileName = getByteArrayFromPartColumn( 425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_FILENAME); 426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (fileName != null) { 427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setFilename(fileName); 428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] name = getByteArrayFromPartColumn( 431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, PART_COLUMN_NAME); 432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (name != null) { 433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setName(name); 434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Construct a Uri for this part. 437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long partId = c.getLong(PART_COLUMN_ID); 438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri partURI = Uri.parse("content://mms/part/" + partId); 439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setDataUri(partURI); 440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // For images/audio/video, we won't keep their data in Part 442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // because their renderer accept Uri as source. 443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String type = toIsoString(contentType); 444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContentType.isImageType(type) 445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && !ContentType.isAudioType(type) 446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && !ContentType.isVideoType(type)) { 447d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 448d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd InputStream is = null; 449d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 450d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Store simple string values directly in the database instead of an 451d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // external file. This makes the text searchable and retrieval slightly 452d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // faster. 453d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ContentType.TEXT_PLAIN.equals(type) || ContentType.APP_SMIL.equals(type) 454d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || ContentType.TEXT_HTML.equals(type)) { 455d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String text = c.getString(PART_COLUMN_TEXT); 456d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] blob = new EncodedStringValue( 457d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd charset != null ? charset : CharacterSets.DEFAULT_CHARSET, 458d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd text != null ? text : "") 459d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getTextString(); 460d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd baos.write(blob, 0, blob.length); 461d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 462d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 463d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 464d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd is = mContentResolver.openInputStream(partURI); 465d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 466d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] buffer = new byte[256]; 467d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int len = is.read(buffer); 468d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (len >= 0) { 469d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd baos.write(buffer, 0, len); 470d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd len = is.read(buffer); 471d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 472d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final IOException e) { 473d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Failed to load part data", e); 474d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c.close(); 475d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException(e); 476d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 477d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (is != null) { 478d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 479d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd is.close(); 480d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final IOException e) { 481d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Failed to close stream", e); 482d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } // Ignore 483d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 484d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 485d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 486d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setData(baos.toByteArray()); 487d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 488d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd parts[partIdx++] = part; 489d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 490d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 491d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (c != null) { 492d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c.close(); 493d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 494d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 495d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 496d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return parts; 497d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 498d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 499d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void loadAddress(final long msgId, final PduHeaders headers) { 500d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c = SqliteWrapper.query(mContext, mContentResolver, 501d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri.parse("content://mms/" + msgId + "/addr"), 502d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[]{Addr.ADDRESS, Addr.CHARSET, Addr.TYPE}, 503d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, null, null); 504d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 505d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (c != null) { 506d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 507d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (c.moveToNext()) { 508d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String addr = c.getString(0); 509d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!TextUtils.isEmpty(addr)) { 510d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int addrType = c.getInt(2); 511d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch (addrType) { 512d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.FROM: 513d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd headers.setEncodedStringValue( 514d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new EncodedStringValue(c.getInt(1), getBytes(addr)), 515d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd addrType); 516d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 517d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.TO: 518d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.CC: 519d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.BCC: 520d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd headers.appendEncodedStringValue( 521d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new EncodedStringValue(c.getInt(1), getBytes(addr)), 522d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd addrType); 523d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 524d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd default: 525d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Unknown address type: " + addrType); 526d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 527d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 528d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 529d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 530d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 531d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c.close(); 532d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 533d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 534d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 535d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 536d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 537d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Load a PDU from a given cursor 538d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 539d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param c The cursor 540d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return A parsed PDU from the database row 541d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 542d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public GenericPdu load(final Cursor c) throws MmsException { 543d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers = new PduHeaders(); 544d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId = c.getLong(PDU_COLUMN_ID); 545d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Fill in the headers from the PDU columns 546d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd loadHeadersFromCursor(c, headers); 547d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Load address information of the MM. 548d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd loadAddress(msgId, headers); 549d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Load parts for the PDU body 550d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE); 551d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduBody body = loadBody(msgId, msgType); 552d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return createPdu(msgType, headers, body); 553d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 554d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 555d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 556d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Load a PDU from storage by given Uri. 557d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 558d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param uri The Uri of the PDU to be loaded. 559d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return A generic PDU object, it may be cast to dedicated PDU. 560d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @throws MmsException Failed to load some fields of a PDU. 561d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 562d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public GenericPdu load(final Uri uri) throws MmsException { 563d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd GenericPdu pdu = null; 564d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduCacheEntry cacheEntry = null; 565d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int msgBox = 0; 566d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long threadId = -1; 567d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 568d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (PDU_CACHE_INSTANCE) { 569d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PDU_CACHE_INSTANCE.isUpdating(uri)) { 570d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 571d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "load: " + uri + " blocked by isUpdating()"); 572d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 573d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 574d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.wait(); 575d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final InterruptedException e) { 576d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "load: ", e); 577d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 578d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 579d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 580d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check if the pdu is already loaded 581d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cacheEntry = PDU_CACHE_INSTANCE.get(uri); 582d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cacheEntry != null) { 583d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return cacheEntry.getPdu(); 584d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 585d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 586d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Tell the cache to indicate to other callers that this item 587d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // is currently being updated. 588d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.setUpdating(uri, true); 589d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 590d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 591d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri, 592d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_PROJECTION, null, null, null); 593d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers = new PduHeaders(); 594d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId = ContentUris.parseId(uri); 595d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 596d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 597d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) { 598d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; // MMS not found 599d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 600d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 601d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX); 602d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd //threadId = c.getLong(PDU_COLUMN_THREAD_ID); 603d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd loadHeadersFromCursor(c, headers); 604d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 605d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (c != null) { 606d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c.close(); 607d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 608d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 609d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 610d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check whether 'msgId' has been assigned a valid value. 611d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (msgId == -1L) { 612d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Error! ID of the message: -1."); 613d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 614d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 615d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Load address information of the MM. 616d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd loadAddress(msgId, headers); 617d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 618d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE); 619d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduBody body = loadBody(msgId, msgType); 620d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd pdu = createPdu(msgType, headers, body); 621d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 622d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (PDU_CACHE_INSTANCE) { 623d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (pdu != null) { 624d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.isNull(PDU_CACHE_INSTANCE.get(uri), "Pdu exists for " + uri); 625d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update the cache entry with the real info 626d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cacheEntry = new PduCacheEntry(pdu, msgBox, threadId); 627d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.put(uri, cacheEntry); 628d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 629d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.setUpdating(uri, false); 630d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead 631d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 632d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 633d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return pdu; 634d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 635d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 636d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void loadHeadersFromCursor(final Cursor c, final PduHeaders headers) 637d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throws InvalidHeaderValueException { 638d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = ENCODED_STRING_COLUMN_INDEX_MAP.size(); --i >= 0; ) { 639d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setEncodedStringValueToHeaders( 640d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, ENCODED_STRING_COLUMN_INDEX_MAP.valueAt(i), headers, 641d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ENCODED_STRING_COLUMN_INDEX_MAP.keyAt(i)); 642d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 643d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = TEXT_STRING_COLUMN_INDEX_MAP.size(); --i >= 0; ) { 644d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setTextStringToHeaders( 645d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, TEXT_STRING_COLUMN_INDEX_MAP.valueAt(i), headers, 646d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TEXT_STRING_COLUMN_INDEX_MAP.keyAt(i)); 647d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 648d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = OCTET_COLUMN_INDEX_MAP.size(); --i >= 0; ) { 649d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setOctetToHeaders( 650d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, OCTET_COLUMN_INDEX_MAP.valueAt(i), headers, 651d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OCTET_COLUMN_INDEX_MAP.keyAt(i)); 652d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 653d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = LONG_COLUMN_INDEX_MAP.size(); --i >= 0; ) { 654d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setLongToHeaders( 655d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd c, LONG_COLUMN_INDEX_MAP.valueAt(i), headers, 656d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LONG_COLUMN_INDEX_MAP.keyAt(i)); 657d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 658d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 659d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 660d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private GenericPdu createPdu(final int msgType, final PduHeaders headers, final PduBody body) 661d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throws MmsException { 662d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch (msgType) { 663d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: 664d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new NotificationInd(headers); 665d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_DELIVERY_IND: 666d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new DeliveryInd(headers); 667d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND: 668d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new ReadOrigInd(headers); 669d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: 670d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new RetrieveConf(headers, body); 671d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_SEND_REQ: 672d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new SendReq(headers, body); 673d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND: 674d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new AcknowledgeInd(headers); 675d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND: 676d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new NotifyRespInd(headers); 677d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_READ_REC_IND: 678d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new ReadRecInd(headers); 679d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_SEND_CONF: 680d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_FORWARD_REQ: 681d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_FORWARD_CONF: 682d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ: 683d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF: 684d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ: 685d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF: 686d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ: 687d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF: 688d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ: 689d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF: 690d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_MBOX_DESCR: 691d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_DELETE_REQ: 692d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_DELETE_CONF: 693d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_CANCEL_REQ: 694d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_CANCEL_CONF: 695d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException( 696d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "Unsupported PDU type: " + Integer.toHexString(msgType)); 697d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 698d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd default: 699d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException( 700d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "Unrecognized PDU type: " + Integer.toHexString(msgType)); 701d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 702d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 703d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 704d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private PduBody loadBody(final long msgId, final int msgType) throws MmsException { 705d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduBody body = new PduBody(); 706d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 707d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // For PDU which type is M_retrieve.conf or Send.req, we should 708d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // load multiparts and put them into the body of the PDU. 709d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) 710d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) { 711d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduPart[] parts = loadParts(msgId); 712d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (parts != null) { 713d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int partsNum = parts.length; 714d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < partsNum; i++) { 715d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd body.addPart(parts[i]); 716d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 717d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 718d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 719d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 720d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return body; 721d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 722d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 723d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void persistAddress( 724d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId, final int type, final EncodedStringValue[] array) { 725d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(3); 726d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 727d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final EncodedStringValue addr : array) { 728d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.clear(); // Clear all values first. 729d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Addr.ADDRESS, toIsoString(addr.getTextString())); 730d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Addr.CHARSET, addr.getCharacterSet()); 731d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Addr.TYPE, type); 732d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 733d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = Uri.parse("content://mms/" + msgId + "/addr"); 734d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.insert(mContext, mContentResolver, uri, values); 735d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 736d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 737d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 738d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static String getPartContentType(final PduPart part) { 739d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return part.getContentType() == null ? null : toIsoString(part.getContentType()); 740d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 741d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 742d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void getValues(final PduPart part, final ContentValues values) { 743d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd byte[] bytes = part.getFilename(); 744d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (bytes != null) { 745d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.FILENAME, new String(bytes)); 746d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 747d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 748d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bytes = part.getName(); 749d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (bytes != null) { 750d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.NAME, new String(bytes)); 751d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 752d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 753d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bytes = part.getContentDisposition(); 754d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (bytes != null) { 755d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CONTENT_DISPOSITION, toIsoString(bytes)); 756d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 757d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 758d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bytes = part.getContentId(); 759d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (bytes != null) { 760d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CONTENT_ID, toIsoString(bytes)); 761d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 762d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 763d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bytes = part.getContentLocation(); 764d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (bytes != null) { 765d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CONTENT_LOCATION, toIsoString(bytes)); 766d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 767d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 768d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 769d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public Uri persistPart(final PduPart part, final long msgId, 770d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Map<Uri, InputStream> preOpenedFiles) throws MmsException { 771d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = Uri.parse("content://mms/" + msgId + "/part"); 772d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(8); 773d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 774d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int charset = part.getCharset(); 775d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (charset != 0) { 776d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CHARSET, charset); 777d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 778d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 779d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String contentType = getPartContentType(part); 780d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] data = part.getData(); 781d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 782d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 783d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "PduPersister.persistPart part: " + uri + " contentType: " + 784d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentType); 785d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 786d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 787d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentType != null) { 788d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // There is no "image/jpg" in Android (and it's an invalid mimetype). 789d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Change it to "image/jpeg" 790d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ContentType.IMAGE_JPG.equals(contentType)) { 791d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentType = ContentType.IMAGE_JPEG; 792d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 793d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 794d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On somes phones, a vcard comes in as text/plain instead of text/v-card. 795d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Fix it if necessary. 796d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ContentType.TEXT_PLAIN.equals(contentType) && data != null) { 797d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // There might be a more efficient way to just check the beginning of the string 798d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // without encoding the whole thing, but we're concerned that with various 799d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // characters sets, just comparing the byte data to BEGIN_VCARD would not be 800d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // reliable. 801d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String encodedDataString = new EncodedStringValue(charset, data).getString(); 802d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (encodedDataString != null && encodedDataString.startsWith(BEGIN_VCARD)) { 803d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentType = ContentType.TEXT_VCARD; 804d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setContentType(contentType.getBytes()); 805d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { 806d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.d(TAG, "PduPersister.persistPart part: " + uri + " contentType: " + 807d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentType + " changing to vcard"); 808d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 809d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 810d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 811d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 812d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CONTENT_TYPE, contentType); 813d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // To ensure the SMIL part is always the first part. 814d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ContentType.APP_SMIL.equals(contentType)) { 815d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.SEQ, -1); 816d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 817d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 818d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("MIME type of the part must be set."); 819d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 820d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 821d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getValues(part, values); 822d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 823d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri res = null; 824d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 825d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 826d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd res = SqliteWrapper.insert(mContext, mContentResolver, uri, values); 827d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (IllegalStateException e) { 828d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Currently the MMS provider throws an IllegalStateException when it's out of space 829d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(TAG, "SqliteWrapper.insert threw: ", e); 830d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 831d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 832d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (res == null) { 833d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Failed to persist part, return null."); 834d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 835d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 836d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd persistData(part, res, contentType, preOpenedFiles); 837d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // After successfully store the data, we should update 838d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the dataUri of the part. 839d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd part.setDataUri(res); 840d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 841d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return res; 842d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 843d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 844d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 845d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Save data of the part into storage. The source data may be given 846d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * by a byte[] or a Uri. If it's a byte[], directly save it 847d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * into storage, otherwise load source data from the dataUri and then 848d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * save it. If the data is an image, we may scale down it according 849d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * to user preference. 850d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 851d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param part The PDU part which contains data to be saved. 852d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param uri The URI of the part. 853d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param contentType The MIME type of the part. 854d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts. 855d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @throws MmsException Cannot find source data or error occurred 856d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * while saving the data. 857d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 858d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void persistData(final PduPart part, final Uri uri, 859d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String contentType, final Map<Uri, InputStream> preOpenedFiles) 860d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throws MmsException { 861d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd OutputStream os = null; 862d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd InputStream is = null; 863d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DrmConvertSession drmConvertSession = null; 864d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri dataUri = null; 865d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String path = null; 866d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 867d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 868d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] data = part.getData(); 869d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int charset = part.getCharset(); 870d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ContentType.TEXT_PLAIN.equals(contentType) 871d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || ContentType.APP_SMIL.equals(contentType) 872d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || ContentType.TEXT_HTML.equals(contentType)) { 873d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Some phone could send MMS with a text part having empty data 874d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Let's just skip those parts. 875d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // EncodedStringValue() throws NPE if data is empty 876d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (data != null) { 877d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues cv = new ContentValues(); 878d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cv.put(Mms.Part.TEXT, new EncodedStringValue(charset, data).getString()); 879d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mContentResolver.update(uri, cv, null, null) != 1) { 880d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("unable to update " + uri.toString()); 881d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 882d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 883d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 884d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isDrm = DownloadDrmHelper.isDrmConvertNeeded(contentType); 885d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isDrm) { 886d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (uri != null) { 887d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 888d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd path = convertUriToPath(mContext, uri); 889d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 890d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "drm uri: " + uri + " path: " + path); 891d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 892d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final File f = new File(path); 893d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long len = f.length(); 894d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 895d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "drm path: " + path + " len: " + len); 896d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 897d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (len > 0) { 898d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // we're not going to re-persist and re-encrypt an already 899d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // converted drm file 900d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 901d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 902d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final Exception e) { 903d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Can't get file info for: " + part.getDataUri(), e); 904d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 905d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 906d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We haven't converted the file yet, start the conversion 907d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd drmConvertSession = DrmConvertSession.open(mContext, contentType); 908d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (drmConvertSession == null) { 909d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Mimetype " + contentType + 910d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd " can not be converted."); 911d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 912d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 913d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // uri can look like: 914d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // content://mms/part/98 915d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd os = mContentResolver.openOutputStream(uri); 916d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (os == null) { 917d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Failed to create output stream on " + uri); 918d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 919d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (data == null) { 920d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd dataUri = part.getDataUri(); 921d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((dataUri == null) || (dataUri == uri)) { 922d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.w(TAG, "Can't find data for this part."); 923d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 924d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 925d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // dataUri can look like: 926d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // content://com.google.android.gallery3d.provider/picasa/item/5720646660183715 927d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (preOpenedFiles != null && preOpenedFiles.containsKey(dataUri)) { 928d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd is = preOpenedFiles.get(dataUri); 929d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 930d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (is == null) { 931d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd is = mContentResolver.openInputStream(dataUri); 932d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 933d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (is == null) { 934d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Failed to create input stream on " + dataUri); 935d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 936d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 937d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Saving data to: " + uri); 938d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 939d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 940d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] buffer = new byte[8192]; 941d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int len = 0; (len = is.read(buffer)) != -1; ) { 942d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!isDrm) { 943d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd os.write(buffer, 0, len); 944d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 945d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] convertedData = drmConvertSession.convert(buffer, len); 946d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (convertedData != null) { 947d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd os.write(convertedData, 0, convertedData.length); 948d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 949d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Error converting drm data."); 950d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 951d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 952d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 953d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 954d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 955d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Saving data to: " + uri); 956d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 957d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!isDrm) { 958d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd os.write(data); 959d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 960d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd dataUri = uri; 961d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] convertedData = drmConvertSession.convert(data, data.length); 962d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (convertedData != null) { 963d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd os.write(convertedData, 0, convertedData.length); 964d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 965d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Error converting drm data."); 966d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 967d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 968d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 969d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 970d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final SQLiteException e) { 971d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Failed with SQLiteException.", e); 972d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException(e); 973d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final FileNotFoundException e) { 974d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Failed to open Input/Output stream.", e); 975d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException(e); 976d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final IOException e) { 977d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "Failed to read/write data.", e); 978d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException(e); 979d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 980d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (os != null) { 981d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 982d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd os.close(); 983d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final IOException e) { 984d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "IOException while closing: " + os, e); 985d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } // Ignore 986d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 987d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (is != null) { 988d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 989d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd is.close(); 990d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final IOException e) { 991d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "IOException while closing: " + is, e); 992d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } // Ignore 993d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 994d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (drmConvertSession != null) { 995d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd drmConvertSession.close(path); 996d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 997d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Reset the permissions on the encrypted part file so everyone has only read 998d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // permission. 999d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final File f = new File(path); 1000d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(0); 1001d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.update(mContext, mContentResolver, 1002d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri.parse("content://mms/resetFilePerm/" + f.getName()), 1003d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values, null, null); 1004d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1005d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1006d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1007d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1008d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1009d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This method expects uri in the following format 1010d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * content://media/<table_name>/<row_index> (or) 1011d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * file://sdcard/test.mp4 1012d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://test.com/test.mp4 1013d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1014d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Here <table_name> shall be "video" or "audio" or "images" 1015d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * <row_index> the index of the content in given table 1016d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1017d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static String convertUriToPath(final Context context, final Uri uri) { 1018d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String path = null; 1019d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (null != uri) { 1020d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String scheme = uri.getScheme(); 1021d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (null == scheme || scheme.equals("") || 1022d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd scheme.equals(ContentResolver.SCHEME_FILE)) { 1023d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd path = uri.getPath(); 1024d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1025d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (scheme.equals("http")) { 1026d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd path = uri.toString(); 1027d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1028d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { 1029d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String[] projection = new String[] {MediaStore.MediaColumns.DATA}; 1030d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 1031d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1032d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = context.getContentResolver().query(uri, projection, null, 1033d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, null); 1034d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) { 1035d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new IllegalArgumentException("Given Uri could not be found" + 1036d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd " in media store"); 1037d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1038d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int pathIndex = 1039d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA); 1040d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd path = cursor.getString(pathIndex); 1041d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final SQLiteException e) { 1042d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new IllegalArgumentException("Given Uri is not formatted in a way " + 1043d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "so that it can be found in media store."); 1044d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 1045d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (null != cursor) { 1046d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 1047d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1048d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1049d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1050d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new IllegalArgumentException("Given Uri scheme is not supported"); 1051d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1052d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1053d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return path; 1054d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1055d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1056d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateAddress( 1057d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId, final int type, final EncodedStringValue[] array) { 1058d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Delete old address information and then insert new ones. 1059d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.delete(mContext, mContentResolver, 1060d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri.parse("content://mms/" + msgId + "/addr"), 1061d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Addr.TYPE + "=" + type, null); 1062d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1063d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd persistAddress(msgId, type, array); 1064d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1065d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1066d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1067d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Update headers of a SendReq. 1068d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1069d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param uri The PDU which need to be updated. 1070d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param pdu New headers. 1071d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @throws MmsException Bad URI or updating failed. 1072d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1073d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void updateHeaders(final Uri uri, final SendReq sendReq) { 1074d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (PDU_CACHE_INSTANCE) { 1075d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If the cache item is getting updated, wait until it's done updating before 1076d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // purging it. 1077d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PDU_CACHE_INSTANCE.isUpdating(uri)) { 1078d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 1079d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "updateHeaders: " + uri + " blocked by isUpdating()"); 1080d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1081d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1082d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.wait(); 1083d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final InterruptedException e) { 1084d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "updateHeaders: ", e); 1085d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1086d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1087d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1088d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.purge(uri); 1089d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1090d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(10); 1091d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] contentType = sendReq.getContentType(); 1092d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentType != null) { 1093d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.CONTENT_TYPE, toIsoString(contentType)); 1094d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1095d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1096d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long date = sendReq.getDate(); 1097d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (date != -1) { 1098d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.DATE, date); 1099d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int deliveryReport = sendReq.getDeliveryReport(); 1102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (deliveryReport != 0) { 1103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.DELIVERY_REPORT, deliveryReport); 1104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long expiry = sendReq.getExpiry(); 1107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (expiry != -1) { 1108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.EXPIRY, expiry); 1109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] msgClass = sendReq.getMessageClass(); 1112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (msgClass != null) { 1113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass)); 1114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int priority = sendReq.getPriority(); 1117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (priority != 0) { 1118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.PRIORITY, priority); 1119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int readReport = sendReq.getReadReport(); 1122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (readReport != 0) { 1123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.READ_REPORT, readReport); 1124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] transId = sendReq.getTransactionId(); 1127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (transId != null) { 1128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.TRANSACTION_ID, toIsoString(transId)); 1129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue subject = sendReq.getSubject(); 1132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (subject != null) { 1133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.SUBJECT, toIsoString(subject.getTextString())); 1134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet()); 1135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.SUBJECT, ""); 1137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long messageSize = sendReq.getMessageSize(); 1140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (messageSize > 0) { 1141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.MESSAGE_SIZE, messageSize); 1142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders headers = sendReq.getPduHeaders(); 1145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final HashSet<String> recipients = new HashSet<String>(); 1146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final int addrType : ADDRESS_FIELDS) { 1147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd EncodedStringValue[] array = null; 1148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (addrType == PduHeaders.FROM) { 1149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue v = headers.getEncodedStringValue(addrType); 1150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (v != null) { 1151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd array = new EncodedStringValue[1]; 1152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd array[0] = v; 1153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd array = headers.getEncodedStringValues(addrType); 1156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (array != null) { 1159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId = ContentUris.parseId(uri); 1160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateAddress(msgId, addrType, array); 1161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (addrType == PduHeaders.TO) { 1162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final EncodedStringValue v : array) { 1163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (v != null) { 1164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd recipients.add(v.getString()); 1165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!recipients.isEmpty()) { 1171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long threadId = MmsSmsUtils.Threads.getOrCreateThreadId(mContext, recipients); 1172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.THREAD_ID, threadId); 1173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null); 1176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updatePart(final Uri uri, final PduPart part, 1180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Map<Uri, InputStream> preOpenedFiles) 1181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throws MmsException { 1182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(7); 1183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int charset = part.getCharset(); 1185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (charset != 0) { 1186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CHARSET, charset); 1187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String contentType = null; 1190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (part.getContentType() != null) { 1191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentType = toIsoString(part.getContentType()); 1192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.CONTENT_TYPE, contentType); 1193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("MIME type of the part must be set."); 1195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getValues(part, values); 1198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null); 1200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Only update the data when: 1202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // 1. New binary data supplied or 1203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // 2. The Uri of the part is different from the current one. 1204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((part.getData() != null) 1205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (uri != part.getDataUri())) { 1206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd persistData(part, uri, contentType, preOpenedFiles); 1207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Update all parts of a PDU. 1212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param uri The PDU which need to be updated. 1214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param body New message body of the PDU. 1215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts. 1216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @throws MmsException Bad URI or updating failed. 1217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void updateParts(final Uri uri, final PduBody body, 1219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Map<Uri, InputStream> preOpenedFiles) 1220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throws MmsException { 1221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduCacheEntry cacheEntry; 1223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (PDU_CACHE_INSTANCE) { 1224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PDU_CACHE_INSTANCE.isUpdating(uri)) { 1225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 1226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "updateParts: " + uri + " blocked by isUpdating()"); 1227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.wait(); 1230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final InterruptedException e) { 1231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "updateParts: ", e); 1232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cacheEntry = PDU_CACHE_INSTANCE.get(uri); 1234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cacheEntry != null) { 1235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body); 1236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Tell the cache to indicate to other callers that this item 1239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // is currently being updated. 1240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.setUpdating(uri, true); 1241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>(); 1244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ArrayMap<Uri, PduPart> toBeUpdated = new ArrayMap<Uri, PduPart>(); 1245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int partsNum = body.getPartsNum(); 1247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final StringBuilder filter = new StringBuilder().append('('); 1248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < partsNum; i++) { 1249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduPart part = body.getPart(i); 1250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri partUri = part.getDataUri(); 1251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((partUri == null) || !partUri.getAuthority().startsWith("mms")) { 1252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd toBeCreated.add(part); 1253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd toBeUpdated.put(partUri, part); 1255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Don't use 'i > 0' to determine whether we should append 1257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // 'AND' since 'i = 0' may be skipped in another branch. 1258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (filter.length() > 1) { 1259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd filter.append(" AND "); 1260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd filter.append(Part._ID); 1263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd filter.append("!="); 1264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment()); 1265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd filter.append(')'); 1268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId = ContentUris.parseId(uri); 1270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Remove the parts which doesn't exist anymore. 1272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.delete(mContext, mContentResolver, 1273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"), 1274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd filter.length() > 2 ? filter.toString() : null, null); 1275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Create new parts which didn't exist before. 1277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final PduPart part : toBeCreated) { 1278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd persistPart(part, msgId, preOpenedFiles); 1279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update the modified parts. 1282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) { 1283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updatePart(e.getKey(), e.getValue(), preOpenedFiles); 1284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 1286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (PDU_CACHE_INSTANCE) { 1287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.setUpdating(uri, false); 1288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.notifyAll(); 1289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Persist a PDU object to specific location in the storage. 1295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param pdu The PDU object to be stored. 1297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param uri Where to store the given PDU object. 1298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param subId Subscription id associated with this message. 1299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param subPhoneNumber TODO 1300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts. 1301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return A Uri which can be used to access the stored PDU. 1302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public Uri persist(final GenericPdu pdu, final Uri uri, final int subId, 1304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String subPhoneNumber, final Map<Uri, InputStream> preOpenedFiles) 1305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throws MmsException { 1306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (uri == null) { 1307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Uri may not be null."); 1308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd long msgId = -1; 1310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd msgId = ContentUris.parseId(uri); 1312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final NumberFormatException e) { 1313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the uri ends with "inbox" or something else like that 1314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean existingUri = msgId != -1; 1316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!existingUri && MESSAGE_BOX_MAP.get(uri) == null) { 1318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException( 1319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "Bad destination, must be one of " 1320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "content://mms/inbox, content://mms/sent, " 1321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "content://mms/drafts, content://mms/outbox, " 1322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "content://mms/temp." 1323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ); 1324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (PDU_CACHE_INSTANCE) { 1326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If the cache item is getting updated, wait until it's done updating before 1327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // purging it. 1328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PDU_CACHE_INSTANCE.isUpdating(uri)) { 1329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 1330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "persist: " + uri + " blocked by isUpdating()"); 1331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.wait(); 1334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final InterruptedException e) { 1335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "persist1: ", e); 1336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PDU_CACHE_INSTANCE.purge(uri); 1340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduHeaders header = pdu.getPduHeaders(); 1342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduBody body = null; 1343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContentValues values = new ContentValues(); 1344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Mark new messages as seen in the telephony database so that we don't have to 1346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // do a global "set all messages as seen" since that occasionally seems to be 1347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // problematic (i.e. very slow). See bug 18189471. 1348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.SEEN, 1); 1349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd //Set<Entry<Integer, String>> set; 1351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = ENCODED_STRING_COLUMN_NAME_MAP.size(); --i >= 0; ) { 1353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int field = ENCODED_STRING_COLUMN_NAME_MAP.keyAt(i); 1354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue encodedString = header.getEncodedStringValue(field); 1355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (encodedString != null) { 1356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field); 1357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ENCODED_STRING_COLUMN_NAME_MAP.valueAt(i), 1358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd toIsoString(encodedString.getTextString())); 1359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(charsetColumn, encodedString.getCharacterSet()); 1360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = TEXT_STRING_COLUMN_NAME_MAP.size(); --i >= 0; ) { 1364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] text = header.getTextString(TEXT_STRING_COLUMN_NAME_MAP.keyAt(i)); 1365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (text != null) { 1366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(TEXT_STRING_COLUMN_NAME_MAP.valueAt(i), toIsoString(text)); 1367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = OCTET_COLUMN_NAME_MAP.size(); --i >= 0; ) { 1371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int b = header.getOctet(OCTET_COLUMN_NAME_MAP.keyAt(i)); 1372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (b != 0) { 1373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(OCTET_COLUMN_NAME_MAP.valueAt(i), b); 1374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = LONG_COLUMN_NAME_MAP.size(); --i >= 0; ) { 1378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long l = header.getLongInteger(LONG_COLUMN_NAME_MAP.keyAt(i)); 1379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (l != -1L) { 1380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(LONG_COLUMN_NAME_MAP.valueAt(i), l); 1381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1382d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1383d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SparseArray<EncodedStringValue[]> addressMap = 1385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new SparseArray<EncodedStringValue[]>(ADDRESS_FIELDS.length); 1386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Save address information. 1387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final int addrType : ADDRESS_FIELDS) { 1388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd EncodedStringValue[] array = null; 1389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (addrType == PduHeaders.FROM) { 1390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue v = header.getEncodedStringValue(addrType); 1391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (v != null) { 1392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd array = new EncodedStringValue[1]; 1393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd array[0] = v; 1394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd array = header.getEncodedStringValues(addrType); 1397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd addressMap.put(addrType, array); 1399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final HashSet<String> recipients = new HashSet<String>(); 1402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int msgType = pdu.getMessageType(); 1403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Here we only allocate thread ID for M-Notification.ind, 1404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // M-Retrieve.conf and M-Send.req. 1405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Some of other PDU types may be allocated a thread ID outside 1406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // this scope. 1407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) 1408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) 1409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) { 1410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch (msgType) { 1411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: 1412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF: 1413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd loadRecipients(PduHeaders.FROM, recipients, addressMap); 1414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // For received messages (whether group MMS is enabled or not) we want to 1416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // associate this message with the thread composed of all the recipients 1417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // EXCLUDING our own number. This includes the person who sent the 1418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // message (the FROM field above) in addition to the other people the message 1419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // was addressed TO (or CC fields to address group messaging compatibility 1420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // issues with devices that place numbers in this field). Typically our own 1421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // number is in the TO/CC field so we have to remove it in loadRecipients. 1422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd checkAndLoadToCcRecipients(recipients, addressMap, subPhoneNumber); 1423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 1424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case PduHeaders.MESSAGE_TYPE_SEND_REQ: 1425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd loadRecipients(PduHeaders.TO, recipients, addressMap); 1426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 1427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd long threadId = -1L; 1429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!recipients.isEmpty()) { 1430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Given all the recipients associated with this message, find (or create) the 1431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // correct thread. 1432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd threadId = MmsSmsUtils.Threads.getOrCreateThreadId(mContext, recipients); 1433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.w(TAG, "PduPersister.persist No recipients; persisting PDU to thread: " 1435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + threadId); 1436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.THREAD_ID, threadId); 1438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Save parts first to avoid inconsistent message is loaded 1441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // while saving the parts. 1442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long dummyId = System.currentTimeMillis(); // Dummy ID of the msg. 1443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Figure out if this PDU is a text-only message 1445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean textOnly = true; 1446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1447d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Get body if the PDU is a RetrieveConf or SendReq. 1448d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (pdu instanceof MultimediaMessagePdu) { 1449d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd body = ((MultimediaMessagePdu) pdu).getBody(); 1450d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Start saving parts if necessary. 1451d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (body != null) { 1452d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int partsNum = body.getPartsNum(); 1453d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 1454d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "PduPersister.persist partsNum: " + partsNum); 1455d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1456d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (partsNum > 2) { 1457d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // For a text-only message there will be two parts: 1-the SMIL, 2-the text. 1458d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Down a few lines below we're checking to make sure we've only got SMIL or 1459d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // text. We also have to check then we don't have more than two parts. 1460d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Otherwise, a slideshow with two text slides would be marked as textOnly. 1461d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textOnly = false; 1462d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1463d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < partsNum; i++) { 1464d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PduPart part = body.getPart(i); 1465d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd persistPart(part, dummyId, preOpenedFiles); 1466d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1467d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If we've got anything besides text/plain or SMIL part, then we've got 1468d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // an mms message with some other type of attachment. 1469d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String contentType = getPartContentType(part); 1470d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LOCAL_LOGV) { 1471d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "PduPersister.persist part: " + i + " contentType: " + 1472d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentType); 1473d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1474d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contentType != null && !ContentType.APP_SMIL.equals(contentType) 1475d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && !ContentType.TEXT_PLAIN.equals(contentType)) { 1476d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textOnly = false; 1477d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1478d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1479d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1480d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1481d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Record whether this mms message is a simple plain text or not. This is a hint for the 1482d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // UI. 1483d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isAtLeastJB_MR1()) { 1484d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.TEXT_ONLY, textOnly ? 1 : 0); 1485d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1486d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1487d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isAtLeastL_MR1()) { 1488d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.SUBSCRIPTION_ID, subId); 1489d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1490d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.equals(ParticipantData.DEFAULT_SELF_SUB_ID, subId); 1491d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1492d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1493d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri res = null; 1494d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (existingUri) { 1495d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd res = uri; 1496d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.update(mContext, mContentResolver, res, values, null, null); 1497d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1498d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd res = SqliteWrapper.insert(mContext, mContentResolver, uri, values); 1499d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (res == null) { 1500d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("persist() failed: return null."); 1501d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1502d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Get the real ID of the PDU and update all parts which were 1503d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // saved with the dummy ID. 1504d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd msgId = ContentUris.parseId(res); 1505d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1506d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1507d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values = new ContentValues(1); 1508d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Part.MSG_ID, msgId); 1509d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.update(mContext, mContentResolver, 1510d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Uri.parse("content://mms/" + dummyId + "/part"), 1511d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values, null, null); 1512d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We should return the longest URI of the persisted PDU, for 1513d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // example, if input URI is "content://mms/inbox" and the _ID of 1514d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // persisted PDU is '8', we should return "content://mms/inbox/8" 1515d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // instead of "content://mms/8". 1516d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: Should the MmsProvider be responsible for this??? 1517d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!existingUri) { 1518d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd res = Uri.parse(uri + "/" + msgId); 1519d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1520d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1521d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Save address information. 1522d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final int addrType : ADDRESS_FIELDS) { 1523d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue[] array = addressMap.get(addrType); 1524d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (array != null) { 1525d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd persistAddress(msgId, addrType, array); 1526d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1527d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1528d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1529d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return res; 1530d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1531d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1532d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1533d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * For a given address type, extract the recipients from the headers. 1534d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1535d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param addressType can be PduHeaders.FROM or PduHeaders.TO 1536d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param recipients a HashSet that is loaded with the recipients from the FROM or TO 1537d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * headers 1538d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param addressMap a HashMap of the addresses from the ADDRESS_FIELDS header 1539d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1540d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void loadRecipients(final int addressType, final HashSet<String> recipients, 1541d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SparseArray<EncodedStringValue[]> addressMap) { 1542d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue[] array = addressMap.get(addressType); 1543d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (array == null) { 1544d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 1545d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1546d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final EncodedStringValue v : array) { 1547d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (v != null) { 1548d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String number = v.getString(); 1549d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!recipients.contains(number)) { 1550d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Only add numbers which aren't already included. 1551d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd recipients.add(number); 1552d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1553d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1554d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1555d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1556d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1557d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1558d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * For a given address type, extract the recipients from the headers. 1559d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1560d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param recipients a HashSet that is loaded with the recipients from the FROM or TO 1561d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * headers 1562d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param addressMap a HashMap of the addresses from the ADDRESS_FIELDS header 1563d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param selfNumber self phone number 1564d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1565d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void checkAndLoadToCcRecipients(final HashSet<String> recipients, 1566d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SparseArray<EncodedStringValue[]> addressMap, final String selfNumber) { 1567d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue[] arrayTo = addressMap.get(PduHeaders.TO); 1568d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EncodedStringValue[] arrayCc = addressMap.get(PduHeaders.CC); 1569d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ArrayList<String> numbers = new ArrayList<String>(); 1570d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (arrayTo != null) { 1571d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final EncodedStringValue v : arrayTo) { 1572d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (v != null) { 1573d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd numbers.add(v.getString()); 1574d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1575d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1576d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1577d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (arrayCc != null) { 1578d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final EncodedStringValue v : arrayCc) { 1579d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (v != null) { 1580d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd numbers.add(v.getString()); 1581d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1582d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1583d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1584d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final String number : numbers) { 1585d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Only add numbers which aren't my own number. 1586d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (TextUtils.isEmpty(selfNumber) || !PhoneNumberUtils.compare(number, selfNumber)) { 1587d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!recipients.contains(number)) { 1588d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Only add numbers which aren't already included. 1589d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd recipients.add(number); 1590d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1591d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1592d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1593d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1594d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1595d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1596d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Move a PDU object from one location to another. 1597d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1598d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param from Specify the PDU object to be moved. 1599d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param to The destination location, should be one of the following: 1600d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * "content://mms/inbox", "content://mms/sent", 1601d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * "content://mms/drafts", "content://mms/outbox", 1602d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * "content://mms/trash". 1603d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return New Uri of the moved PDU. 1604d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @throws MmsException Error occurred while moving the message. 1605d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1606d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public Uri move(final Uri from, final Uri to) throws MmsException { 1607d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check whether the 'msgId' has been assigned a valid value. 1608d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long msgId = ContentUris.parseId(from); 1609d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (msgId == -1L) { 1610d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException("Error! ID of the message: -1."); 1611d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1612d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1613d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Get corresponding int value of destination box. 1614d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Integer msgBox = MESSAGE_BOX_MAP.get(to); 1615d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (msgBox == null) { 1616d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new MmsException( 1617d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "Bad destination, must be one of " 1618d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "content://mms/inbox, content://mms/sent, " 1619d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "content://mms/drafts, content://mms/outbox, " 1620d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "content://mms/temp." 1621d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ); 1622d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1623d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1624d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(1); 1625d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(Mms.MESSAGE_BOX, msgBox); 1626d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.update(mContext, mContentResolver, from, values, null, null); 1627d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return ContentUris.withAppendedId(to, msgId); 1628d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1629d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1630d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1631d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Wrap a byte[] into a String. 1632d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1633d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static String toIsoString(final byte[] bytes) { 1634d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1635d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1); 1636d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final UnsupportedEncodingException e) { 1637d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Impossible to reach here! 1638d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "ISO_8859_1 must be supported!", e); 1639d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return ""; 1640d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1641d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1642d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1643d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1644d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unpack a given String into a byte[]. 1645d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1646d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static byte[] getBytes(final String data) { 1647d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 1648d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1); 1649d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final UnsupportedEncodingException e) { 1650d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Impossible to reach here! 1651d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Log.e(TAG, "ISO_8859_1 must be supported!", e); 1652d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new byte[0]; 1653d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1654d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1655d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1656d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1657d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Remove all objects in the temporary path. 1658d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1659d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void release() { 1660d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = Uri.parse(TEMPORARY_DRM_OBJECT_URI); 1661d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SqliteWrapper.delete(mContext, mContentResolver, uri, null, null); 1662d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1663d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1664d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1665d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Find all messages to be sent or downloaded before certain time. 1666d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1667d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public Cursor getPendingMessages(final long dueTime) { 1668d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon(); 1669d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd uriBuilder.appendQueryParameter("protocol", "mms"); 1670d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1671d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String selection = PendingMessages.ERROR_TYPE + " < ?" 1672d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " AND " + PendingMessages.DUE_TIME + " <= ?"; 1673d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1674d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String[] selectionArgs = new String[] { 1675d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String.valueOf(MmsSms.ERR_TYPE_GENERIC_PERMANENT), 1676d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String.valueOf(dueTime) 1677d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1678d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1679d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return SqliteWrapper.query(mContext, mContentResolver, 1680d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd uriBuilder.build(), null, selection, selectionArgs, 1681d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PendingMessages.DUE_TIME); 1682d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1683d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 1684