1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.datamodel.action; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Bundle; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcel; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcelable; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleDatabaseOperations; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleNotifications; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModelException; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseWrapper; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.MessagingContentProvider; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.SyncManager; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessageData; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.pdu.PduHeaders; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.DatabaseMessages; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Action used to "receive" an incoming message 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ReceiveMmsMessageAction extends Action implements Parcelable { 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String KEY_SUB_ID = "sub_id"; 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String KEY_PUSH_DATA = "push_data"; 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String KEY_TRANSACTION_ID = "transaction_id"; 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String KEY_CONTENT_LOCATION = "content_location"; 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Create a message received from a particular number in a particular conversation 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ReceiveMmsMessageAction(final int subId, final byte[] pushData) { 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd actionParameters.putInt(KEY_SUB_ID, subId); 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd actionParameters.putByteArray(KEY_PUSH_DATA, pushData); 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Object executeAction() { 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Context context = Factory.get().getApplicationContext(); 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID); 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final byte[] pushData = actionParameters.getByteArray(KEY_PUSH_DATA); 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Write received message to telephony DB 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData message = null; 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData self = BugleDatabaseOperations.getOrCreateSelf(db, subId); 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long received = System.currentTimeMillis(); 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Inform sync that message has been added at local received timestamp 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SyncManager syncManager = DataModel.get().getSyncManager(); 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd syncManager.onNewMessageInserted(received); 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: Should use local time to set received time in MMS message 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseMessages.MmsMessage mms = MmsUtils.processReceivedPdu( 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd context, pushData, self.getSubId(), self.getNormalizedDestination()); 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mms != null) { 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<String> recipients = MmsUtils.getRecipientsByThread(mms.mThreadId); 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String from = MmsUtils.getMmsSender(recipients, mms.getUri()); 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (from == null) { 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.w(TAG, "Received an MMS without sender address; using unknown sender."); 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd from = ParticipantData.getUnknownSenderDestination(); 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData rawSender = ParticipantData.getFromRawPhoneBySimLocale( 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd from, subId); 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean blocked = BugleDatabaseOperations.isBlockedDestination( 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db, rawSender.getNormalizedDestination()); 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean autoDownload = (!blocked && MmsUtils.allowMmsAutoRetrieve(subId)); 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String conversationId = 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.getOrCreateConversationFromThreadId(db, mms.mThreadId, 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd blocked, subId); 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean messageInFocusedConversation = 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.get().isFocusedConversation(conversationId); 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean messageInObservableConversation = 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.get().isNewMessageObservable(conversationId); 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: Also write these values to the telephony provider 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mms.mRead = messageInFocusedConversation; 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mms.mSeen = messageInObservableConversation || blocked; 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Write received placeholder message to our DB 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.beginTransaction(); 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String participantId = 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, rawSender); 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String selfId = 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self); 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd message = MmsUtils.createMmsMessage(mms, conversationId, participantId, selfId, 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (autoDownload ? MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD : 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD)); 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Write the message 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.insertNewMessageInTransaction(db, message); 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!autoDownload) { 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.updateConversationMetadataInTransaction(db, 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd conversationId, message.getMessageId(), message.getReceivedTimeStamp(), 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd blocked, true /* shouldAutoSwitchSelfId */); 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData sender = ParticipantData .getFromId( 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db, participantId); 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleActionToasts.onMessageReceived(conversationId, sender, message); 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // else update the conversation once we have downloaded final message (or failed) 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.setTransactionSuccessful(); 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.endTransaction(); 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update conversation if not immediately initiating a download 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!autoDownload) { 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyMessagesChanged(message.getConversationId()); 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyPartsChanged(); 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Show a notification to let the user know a new message has arrived 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleNotifications.update(false/*silent*/, conversationId, 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleNotifications.UPDATE_ALL); 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Send the NotifyRespInd with DEFERRED status since no auto download 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd actionParameters.putString(KEY_TRANSACTION_ID, mms.mTransactionId); 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd actionParameters.putString(KEY_CONTENT_LOCATION, mms.mContentLocation); 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd requestBackgroundWork(); 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.i(TAG, "ReceiveMmsMessageAction: Received MMS message " + message.getMessageId() 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " in conversation " + message.getConversationId() 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + ", uri = " + message.getSmsMessageUri()); 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(TAG, "ReceiveMmsMessageAction: Skipping processing of incoming PDU"); 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this); 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return message; 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Bundle doBackgroundWork() throws DataModelException { 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Context context = Factory.get().getApplicationContext(); 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID); 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID); 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String contentLocation = actionParameters.getString(KEY_CONTENT_LOCATION); 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MmsUtils.sendNotifyResponseForMmsDownload( 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd context, 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subId, 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MmsUtils.stringToBytes(transactionId, "UTF-8"), 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLocation, 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PduHeaders.STATUS_DEFERRED); 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We don't need to return anything. 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ReceiveMmsMessageAction(final Parcel in) { 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(in); 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final Parcelable.Creator<ReceiveMmsMessageAction> CREATOR 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd = new Parcelable.Creator<ReceiveMmsMessageAction>() { 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ReceiveMmsMessageAction createFromParcel(final Parcel in) { 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new ReceiveMmsMessageAction(in); 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ReceiveMmsMessageAction[] newArray(final int size) { 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new ReceiveMmsMessageAction[size]; 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void writeToParcel(final Parcel parcel, final int flags) { 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd writeActionToParcel(parcel, flags); 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 198