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