1 /* 2 * Copyright (C) 2015 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.messaging.receiver; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.net.Uri; 23 import android.provider.Telephony.Sms; 24 import android.telephony.SmsMessage; 25 26 import com.android.messaging.datamodel.action.ProcessDeliveryReportAction; 27 import com.android.messaging.datamodel.action.ProcessDownloadedMmsAction; 28 import com.android.messaging.datamodel.action.ProcessSentMessageAction; 29 import com.android.messaging.datamodel.data.ParticipantData; 30 import com.android.messaging.sms.MmsUtils; 31 import com.android.messaging.sms.SmsSender; 32 import com.android.messaging.util.LogUtil; 33 34 /** 35 * The SMS sent and delivery intent receiver. 36 * 37 * This class just simply forwards the intents to proper recipients for actual handling. 38 */ 39 public class SendStatusReceiver extends BroadcastReceiver { 40 public static final String MESSAGE_SENT_ACTION = 41 "com.android.messaging.receiver.SendStatusReceiver.MESSAGE_SENT"; 42 public static final String MESSAGE_DELIVERED_ACTION = 43 "com.android.messaging.receiver.SendStatusReceiver.MESSAGE_DELIVERED"; 44 public static final String MMS_SENT_ACTION = 45 "com.android.messaging.receiver.SendStatusReceiver.MMS_SENT"; 46 public static final String MMS_DOWNLOADED_ACTION = 47 "com.android.messaging.receiver.SendStatusReceiver.MMS_DOWNLOADED"; 48 49 // Defined by platform, but no constant provided. See docs for SmsManager.sendTextMessage. 50 public static final String EXTRA_ERROR_CODE = "errorCode"; 51 52 public static final String EXTRA_PART_ID = "partId"; 53 public static final String EXTRA_SUB_ID = "subId"; 54 55 public static final int NO_ERROR_CODE = -1; 56 public static final int NO_PART_ID = -1; 57 58 @Override onReceive(final Context context, final Intent intent)59 public void onReceive(final Context context, final Intent intent) { 60 // This will be called on the main thread (so it should exit quickly) 61 final String action = intent.getAction(); 62 final int resultCode = getResultCode(); 63 if (MESSAGE_SENT_ACTION.equals(action)) { 64 final Uri requestId = intent.getData(); 65 SmsSender.setResult( 66 requestId, 67 resultCode, 68 intent.getIntExtra(EXTRA_ERROR_CODE, NO_ERROR_CODE), 69 intent.getIntExtra(EXTRA_PART_ID, NO_PART_ID), 70 intent.getIntExtra(EXTRA_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID)); 71 } else if (MMS_SENT_ACTION.equals(action)) { 72 final Uri messageUri = intent.getData(); 73 ProcessSentMessageAction.processMmsSent(resultCode, messageUri, 74 intent.getExtras()); 75 } else if (MMS_DOWNLOADED_ACTION.equals(action)) { 76 ProcessDownloadedMmsAction.processMessageDownloaded(resultCode, 77 intent.getExtras()); 78 } else if (MESSAGE_DELIVERED_ACTION.equals(action)) { 79 final SmsMessage smsMessage = MmsUtils.getSmsMessageFromDeliveryReport(intent); 80 final Uri smsMessageUri = intent.getData(); 81 if (smsMessage == null) { 82 LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: empty report message"); 83 return; 84 } 85 int status = Sms.STATUS_COMPLETE; 86 try { 87 final String format = intent.getStringExtra("format"); 88 status = smsMessage.getStatus(); 89 // Simple matching up CDMA status with GSM status. 90 if ("3gpp2".equals(format)) { 91 final int errorClass = (status >> 24) & 0x03; 92 final int statusCode = (status >> 16) & 0x3f; 93 switch (errorClass) { 94 case 0: /*ERROR_NONE*/ 95 if (statusCode == 0x02 /*STATUS_DELIVERED*/) { 96 status = Sms.STATUS_COMPLETE; 97 } else status = Sms.STATUS_PENDING; 98 break; 99 case 2: /*ERROR_TEMPORARY*/ 100 // TODO: Need to check whether SC still trying to deliver the SMS to 101 // destination and will send the report again? 102 status = Sms.STATUS_PENDING; 103 break; 104 case 3: /*ERROR_PERMANENT*/ 105 status = Sms.STATUS_FAILED; 106 break; 107 default: 108 status = Sms.STATUS_PENDING; 109 } 110 } 111 } catch (final NullPointerException e) { 112 // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access 113 // the methods on it although the SmsMessage itself is not null. 114 LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: NPE inside SmsMessage"); 115 return; 116 } 117 ProcessDeliveryReportAction.deliveryReportReceived(smsMessageUri, status); 118 } 119 } 120 } 121