SendRequest.java revision e2b75c7234b90971b3c77d471a05be9ac6b6effb
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mms.service; 18 19import com.google.android.mms.MmsException; 20import com.google.android.mms.pdu.GenericPdu; 21import com.google.android.mms.pdu.PduParser; 22import com.google.android.mms.pdu.PduPersister; 23import com.google.android.mms.pdu.SendConf; 24import com.google.android.mms.pdu.SendReq; 25import com.google.android.mms.util.SqliteWrapper; 26 27import com.android.mms.service.exception.MmsHttpException; 28 29import android.app.Activity; 30import android.app.AppOpsManager; 31import android.app.PendingIntent; 32import android.content.ContentValues; 33import android.content.Context; 34import android.content.Intent; 35import android.database.sqlite.SQLiteException; 36import android.net.Uri; 37import android.os.Binder; 38import android.os.UserHandle; 39import android.provider.Settings; 40import android.provider.Telephony; 41import android.text.TextUtils; 42import android.util.Log; 43 44/** 45 * Request to send an MMS 46 */ 47public class SendRequest extends MmsRequest { 48 private final byte[] mPdu; 49 private final String mLocationUrl; 50 private final PendingIntent mSentIntent; 51 52 public SendRequest(RequestManager manager, long subId, byte[] pdu, Uri messageUri, 53 String locationUrl, PendingIntent sentIntent, String creator) { 54 super(manager, messageUri, subId, creator); 55 mPdu = pdu; 56 mLocationUrl = locationUrl; 57 mSentIntent = sentIntent; 58 } 59 60 @Override 61 protected byte[] doHttp(Context context, ApnSettings apn) throws MmsHttpException { 62 return HttpUtils.httpConnection( 63 context, 64 mLocationUrl != null ? mLocationUrl : apn.getMmscUrl(), 65 mPdu, 66 HttpUtils.HTTP_POST_METHOD, 67 apn.isProxySet(), 68 apn.getProxyAddress(), 69 apn.getProxyPort()); 70 } 71 72 @Override 73 protected PendingIntent getPendingIntent() { 74 return mSentIntent; 75 } 76 77 @Override 78 protected int getRunningQueue() { 79 return MmsService.QUEUE_INDEX_SEND; 80 } 81 82 public void storeInOutbox(Context context) { 83 if (mPdu == null) { 84 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: empty PDU"); 85 return; 86 } 87 try { 88 if (mMessageUri == null) { 89 // This is a new message to send 90 final GenericPdu pdu = (new PduParser(mPdu)).parse(); 91 if (pdu == null) { 92 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: can't parse input PDU"); 93 return; 94 } 95 if (!(pdu instanceof SendReq)) { 96 Log.d(MmsService.TAG, "SendRequest.storeInOutbox: not SendReq"); 97 return; 98 } 99 final PduPersister persister = PduPersister.getPduPersister(context); 100 mMessageUri = persister.persist( 101 pdu, 102 Telephony.Mms.Outbox.CONTENT_URI, 103 true/*createThreadId*/, 104 true/*groupMmsEnabled*/, 105 null/*preOpenedFiles*/); 106 if (mMessageUri == null) { 107 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: can not persist message"); 108 return; 109 } 110 final ContentValues values = new ContentValues(4); 111 values.put(Telephony.Mms.DATE, System.currentTimeMillis() / 1000L); 112 values.put(Telephony.Mms.READ, 1); 113 values.put(Telephony.Mms.SEEN, 1); 114 if (!TextUtils.isEmpty(mCreator)) { 115 values.put(Telephony.Mms.CREATOR, mCreator); 116 } 117 if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 118 null/*where*/, null/*selectionArg*/) != 1) { 119 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: failed to update message"); 120 } 121 } else { 122 // This is a stored message, either in FAILED or DRAFT 123 // Move this to OUTBOX for sending 124 final ContentValues values = new ContentValues(2); 125 // Reset the timestamp 126 values.put(Telephony.Mms.DATE, System.currentTimeMillis() / 1000L); 127 values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_OUTBOX); 128 if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 129 null/*where*/, null/*selectionArg*/) != 1) { 130 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: failed to update message"); 131 } 132 } 133 } catch (MmsException e) { 134 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: can not persist/update message", e); 135 } catch (RuntimeException e) { 136 Log.e(MmsService.TAG, "SendRequest.storeInOutbox: unexpected parsing failure", e); 137 } 138 } 139 140 @Override 141 protected void updateStatus(Context context, int result, byte[] response) { 142 if (mMessageUri == null) { 143 return; 144 } 145 final long identity = Binder.clearCallingIdentity(); 146 try { 147 final int messageStatus = result == Activity.RESULT_OK ? 148 Telephony.Mms.MESSAGE_BOX_SENT : Telephony.Mms.MESSAGE_BOX_FAILED; 149 SendConf sendConf = null; 150 if (response != null && response.length > 0) { 151 final GenericPdu pdu = (new PduParser(response)).parse(); 152 if (pdu != null && pdu instanceof SendConf) { 153 sendConf = (SendConf) pdu; 154 } 155 } 156 final ContentValues values = new ContentValues(3); 157 values.put(Telephony.Mms.MESSAGE_BOX, messageStatus); 158 if (sendConf != null) { 159 values.put(Telephony.Mms.RESPONSE_STATUS, sendConf.getResponseStatus()); 160 values.put(Telephony.Mms.MESSAGE_ID, 161 PduPersister.toIsoString(sendConf.getMessageId())); 162 } 163 SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 164 null/*where*/, null/*selectionArg*/); 165 } catch (SQLiteException e) { 166 Log.e(MmsService.TAG, "SendRequest.updateStatus: can not update message", e); 167 } catch (RuntimeException e) { 168 Log.e(MmsService.TAG, "SendRequest.updateStatus: can not parse response", e); 169 } finally { 170 Binder.restoreCallingIdentity(identity); 171 } 172 } 173 174 /** 175 * Try sending via the carrier app by sending an intent 176 * 177 * @param context The context 178 */ 179 public void trySendingByCarrierApp(Context context) { 180 Intent intent = new Intent(Telephony.Mms.Intents.MMS_SEND_ACTION); 181 intent.putExtra("pdu", mPdu); 182 intent.putExtra("url", mLocationUrl); 183 intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); 184 context.sendOrderedBroadcastAsUser( 185 intent, 186 UserHandle.OWNER, 187 android.Manifest.permission.RECEIVE_MMS, 188 AppOpsManager.OP_RECEIVE_MMS, 189 mCarrierAppResultReceiver, 190 null/*scheduler*/, 191 Activity.RESULT_CANCELED, 192 null/*initialData*/, 193 null/*initialExtras*/); 194 } 195} 196