• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.mms.service;
18 
19 import com.google.android.mms.MmsException;
20 import com.google.android.mms.pdu.GenericPdu;
21 import com.google.android.mms.pdu.PduHeaders;
22 import com.google.android.mms.pdu.PduParser;
23 import com.google.android.mms.pdu.PduPersister;
24 import com.google.android.mms.pdu.RetrieveConf;
25 import com.google.android.mms.util.SqliteWrapper;
26 
27 import com.android.mms.service.exception.MmsHttpException;
28 
29 import android.app.Activity;
30 import android.app.AppOpsManager;
31 import android.app.PendingIntent;
32 import android.content.ContentValues;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.database.sqlite.SQLiteException;
36 import android.net.Uri;
37 import android.os.Binder;
38 import android.os.Bundle;
39 import android.os.UserHandle;
40 import android.provider.Telephony;
41 import android.telephony.TelephonyManager;
42 import android.text.TextUtils;
43 import android.util.Log;
44 
45 import java.util.List;
46 
47 /**
48  * Request to download an MMS
49  */
50 public class DownloadRequest extends MmsRequest {
51     private static final String LOCATION_SELECTION =
52             Telephony.Mms.MESSAGE_TYPE + "=? AND " + Telephony.Mms.CONTENT_LOCATION + " =?";
53 
54     private final String mLocationUrl;
55     private final PendingIntent mDownloadedIntent;
56     private final Uri mContentUri;
57 
DownloadRequest(RequestManager manager, long subId, String locationUrl, Uri contentUri, PendingIntent downloadedIntent, String creator, Bundle configOverrides)58     public DownloadRequest(RequestManager manager, long subId, String locationUrl,
59             Uri contentUri, PendingIntent downloadedIntent, String creator,
60             Bundle configOverrides) {
61         super(manager, null/*messageUri*/, subId, creator, configOverrides);
62         mLocationUrl = locationUrl;
63         mDownloadedIntent = downloadedIntent;
64         mContentUri = contentUri;
65     }
66 
67     @Override
doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn)68     protected byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn)
69             throws MmsHttpException {
70         return doHttpForResolvedAddresses(context,
71                 netMgr,
72                 mLocationUrl,
73                 null/*pdu*/,
74                 HttpUtils.HTTP_GET_METHOD,
75                 apn);
76     }
77 
78     @Override
getPendingIntent()79     protected PendingIntent getPendingIntent() {
80         return mDownloadedIntent;
81     }
82 
83     @Override
getRunningQueue()84     protected int getRunningQueue() {
85         return MmsService.QUEUE_INDEX_DOWNLOAD;
86     }
87 
88     @Override
updateStatus(Context context, int result, byte[] response)89     protected void updateStatus(Context context, int result, byte[] response) {
90         if (mRequestManager.getAutoPersistingPref()) {
91             storeInboxMessage(context, result, response);
92         }
93     }
94 
95     /**
96      * Transfer the received response to the caller (for download requests write to content uri)
97      *
98      * @param fillIn the intent that will be returned to the caller
99      * @param response the pdu to transfer
100      */
101     @Override
transferResponse(Intent fillIn, final byte[] response)102     protected boolean transferResponse(Intent fillIn, final byte[] response) {
103         return mRequestManager.writePduToContentUri(mContentUri, response);
104     }
105 
storeInboxMessage(Context context, int result, byte[] response)106     private void storeInboxMessage(Context context, int result, byte[] response) {
107         if (response == null || response.length < 1) {
108             return;
109         }
110         final long identity = Binder.clearCallingIdentity();
111         try {
112             final GenericPdu pdu = (new PduParser(response)).parse();
113             if (pdu == null || !(pdu instanceof RetrieveConf)) {
114                 Log.e(MmsService.TAG, "DownloadRequest.updateStatus: invalid parsed PDU");
115                 return;
116             }
117             // Store the downloaded message
118             final PduPersister persister = PduPersister.getPduPersister(context);
119             mMessageUri = persister.persist(
120                     pdu,
121                     Telephony.Mms.Inbox.CONTENT_URI,
122                     true/*createThreadId*/,
123                     true/*groupMmsEnabled*/,
124                     null/*preOpenedFiles*/);
125             if (mMessageUri == null) {
126                 Log.e(MmsService.TAG, "DownloadRequest.updateStatus: can not persist message");
127                 return;
128             }
129             // Update some of the properties of the message
130             ContentValues values = new ContentValues(5);
131             values.put(Telephony.Mms.DATE, System.currentTimeMillis() / 1000L);
132             values.put(Telephony.Mms.READ, 0);
133             values.put(Telephony.Mms.SEEN, 0);
134             if (!TextUtils.isEmpty(mCreator)) {
135                 values.put(Telephony.Mms.CREATOR, mCreator);
136             }
137             values.put(Telephony.Mms.SUB_ID, mSubId);
138             if (SqliteWrapper.update(
139                     context,
140                     context.getContentResolver(),
141                     mMessageUri,
142                     values,
143                     null/*where*/,
144                     null/*selectionArg*/) != 1) {
145                 Log.e(MmsService.TAG, "DownloadRequest.updateStatus: can not update message");
146             }
147             // Delete the corresponding NotificationInd
148             SqliteWrapper.delete(context,
149                     context.getContentResolver(),
150                     Telephony.Mms.CONTENT_URI,
151                     LOCATION_SELECTION,
152                     new String[]{
153                             Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
154                             mLocationUrl
155                     }
156             );
157         } catch (MmsException e) {
158             Log.e(MmsService.TAG, "DownloadRequest.updateStatus: can not persist message", e);
159         } catch (SQLiteException e) {
160             Log.e(MmsService.TAG, "DownloadRequest.updateStatus: can not update message", e);
161         } catch (RuntimeException e) {
162             Log.e(MmsService.TAG, "DownloadRequest.updateStatus: can not parse response", e);
163         } finally {
164             Binder.restoreCallingIdentity(identity);
165         }
166     }
167 
prepareForHttpRequest()168     protected boolean prepareForHttpRequest() {
169         return true;
170     }
171 
172     /**
173      * Try downloading via the carrier app by sending intent.
174      *
175      * @param context The context
176      */
tryDownloadingByCarrierApp(Context context)177     public void tryDownloadingByCarrierApp(Context context) {
178         TelephonyManager telephonyManager =
179                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
180         Intent intent = new Intent(Telephony.Mms.Intents.MMS_DOWNLOAD_ACTION);
181         List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
182                 intent);
183 
184         if (carrierPackages == null || carrierPackages.size() != 1) {
185             mRequestManager.addRunning(this);
186         } else {
187             intent.setPackage(carrierPackages.get(0));
188             intent.putExtra(Telephony.Mms.Intents.EXTRA_MMS_LOCATION_URL, mLocationUrl);
189             intent.putExtra(Telephony.Mms.Intents.EXTRA_MMS_CONTENT_URI, mContentUri);
190             intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
191             context.sendOrderedBroadcastAsUser(
192                     intent,
193                     UserHandle.OWNER,
194                     android.Manifest.permission.RECEIVE_MMS,
195                     AppOpsManager.OP_RECEIVE_MMS,
196                     mCarrierAppResultReceiver,
197                     null/*scheduler*/,
198                     Activity.RESULT_CANCELED,
199                     null/*initialData*/,
200                     null/*initialExtras*/);
201         }
202     }
203 
204     @Override
revokeUriPermission(Context context)205     protected void revokeUriPermission(Context context) {
206         context.revokeUriPermission(mContentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
207     }
208 }
209