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