1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.receiver; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.app.Notification; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.app.PendingIntent; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.BroadcastReceiver; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ComponentName; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ContentValues; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Intent; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.pm.PackageManager; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.res.Resources; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony.Sms; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.app.NotificationCompat; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.app.NotificationCompat.Builder; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.app.NotificationCompat.Style; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.app.NotificationManagerCompat; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.ArrayList; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.regex.Pattern; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.regex.PatternSyntaxException; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.R; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleNotifications; 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.MessageNotificationState; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.NoConfirmationSmsSendService; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.action.ReceiveSmsMessageAction; 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils; 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.UIIntents; 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.BugleGservices; 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.BugleGservicesKeys; 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.DebugUtils; 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.OsUtil; 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PendingIntentConstants; 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PhoneUtils; 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Class that receives incoming SMS messages through android.provider.Telephony.SMS_RECEIVED 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This class serves two purposes: 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * - Process phone verification SMS messages 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * - Handle SMS messages when the user has enabled us to be the default SMS app (Pre-KLP) 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic final class SmsReceiver extends BroadcastReceiver { 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = LogUtil.BUGLE_TAG; 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static ArrayList<Pattern> sIgnoreSmsPatterns; 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Enable or disable the SmsReceiver as appropriate. Pre-KLP we use this receiver for 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * receiving incoming SMS messages. For KLP+ this receiver is not used when running as the 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * primary user and the SmsDeliverReceiver is used for receiving incoming SMS messages. 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * When running as a secondary user, this receiver is still used to trigger the incoming 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * notification. 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void updateSmsReceiveHandler(final Context context) { 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean smsReceiverEnabled; 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean mmsWapPushReceiverEnabled; 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean respondViaMessageEnabled; 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean broadcastAbortEnabled; 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isAtLeastKLP()) { 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // When we're running as the secondary user, we don't get the new SMS_DELIVER intent, 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // only the primary user receives that. As secondary, we need to go old-school and 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // listen for the SMS_RECEIVED intent. For the secondary user, use this SmsReceiver 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // for both sms and mms notification. For the primary user on KLP (and above), we don't 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // use the SmsReceiver. 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd smsReceiverEnabled = OsUtil.isSecondaryUser(); 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On KLP use the new deliver event for mms 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mmsWapPushReceiverEnabled = false; 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On KLP we need to always enable this handler to show in the list of sms apps 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd respondViaMessageEnabled = true; 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On KLP we don't need to abort the broadcast 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd broadcastAbortEnabled = false; 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On JB we use the sms receiver for both sms/mms delivery 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean carrierSmsEnabled = PhoneUtils.getDefault().isSmsEnabled(); 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd smsReceiverEnabled = carrierSmsEnabled; 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On JB we use the mms receiver when sms/mms is enabled 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mmsWapPushReceiverEnabled = carrierSmsEnabled; 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On JB this is dynamic to make sure we don't show in dialer if sms is disabled 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd respondViaMessageEnabled = carrierSmsEnabled; 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On JB we need to abort broadcasts if SMS is enabled 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd broadcastAbortEnabled = carrierSmsEnabled; 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PackageManager packageManager = context.getPackageManager(); 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean logv = LogUtil.isLoggable(TAG, LogUtil.VERBOSE); 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (smsReceiverEnabled) { 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Enabling SMS message receiving"); 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, SmsReceiver.class), 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Disabling SMS message receiving"); 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, SmsReceiver.class), 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mmsWapPushReceiverEnabled) { 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Enabling MMS message receiving"); 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, MmsWapPushReceiver.class), 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Disabling MMS message receiving"); 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, MmsWapPushReceiver.class), 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (broadcastAbortEnabled) { 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Enabling SMS/MMS broadcast abort"); 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, AbortSmsReceiver.class), 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, AbortMmsWapPushReceiver.class), 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Disabling SMS/MMS broadcast abort"); 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, AbortSmsReceiver.class), 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, AbortMmsWapPushReceiver.class), 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (respondViaMessageEnabled) { 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Enabling respond via message intent"); 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, NoConfirmationSmsSendService.class), 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (logv) { 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Disabling respond via message intent"); 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd packageManager.setComponentEnabledSetting( 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ComponentName(context, NoConfirmationSmsSendService.class), 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String EXTRA_ERROR_CODE = "errorCode"; 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String EXTRA_SUB_ID = "subscription"; 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void deliverSmsIntent(final Context context, final Intent intent) { 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final android.telephony.SmsMessage[] messages = getMessagesFromIntent(intent); 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check messages for validity 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (messages == null || messages.length < 1) { 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(TAG, "processReceivedSms: null or zero or ignored message"); 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int errorCode = intent.getIntExtra(EXTRA_ERROR_CODE, 0); 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Always convert negative subIds into -1 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem( 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd intent, EXTRA_SUB_ID); 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd deliverSmsMessages(context, subId, errorCode, messages); 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (MmsUtils.isDumpSmsEnabled()) { 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String format = null; 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DebugUtils.dumpSms(messages[0].getTimestampMillis(), messages, format); 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void deliverSmsMessages(final Context context, final int subId, 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int errorCode, final android.telephony.SmsMessage[] messages) { 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues messageValues = 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MmsUtils.parseReceivedSmsMessage(context, messages, errorCode); 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "SmsReceiver.deliverSmsMessages"); 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long nowInMillis = System.currentTimeMillis(); 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long receivedTimestampMs = MmsUtils.getMessageDate(messages[0], nowInMillis); 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageValues.put(Sms.Inbox.DATE, receivedTimestampMs); 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Default to unread and unseen for us but ReceiveSmsMessageAction will override 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // seen for the telephony db. 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageValues.put(Sms.Inbox.READ, 0); 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageValues.put(Sms.Inbox.SEEN, 0); 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isAtLeastL_MR1()) { 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageValues.put(Sms.SUBSCRIPTION_ID, subId); 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (messages[0].getMessageClass() == android.telephony.SmsMessage.MessageClass.CLASS_0 || 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DebugUtils.debugClassZeroSmsEnabled()) { 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Factory.get().getUIIntents().launchClassZeroActivity(context, messageValues); 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(messageValues); 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd action.start(); 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onReceive(final Context context, final Intent intent) { 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "SmsReceiver.onReceive " + intent); 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // On KLP+ we only take delivery of SMS messages in SmsDeliverReceiver. 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PhoneUtils.getDefault().isSmsEnabled()) { 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String action = intent.getAction(); 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isSecondaryUser() && 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action) || 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: update this with the actual constant from Telephony 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "android.provider.Telephony.MMS_DOWNLOADED".equals(action))) { 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd postNewMessageSecondaryUserNotification(); 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (!OsUtil.isAtLeastKLP()) { 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd deliverSmsIntent(context, intent); 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static class SecondaryUserNotificationState extends MessageNotificationState { 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SecondaryUserNotificationState() { 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(null); 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Style build(Builder builder) { 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean getNotificationVibrate() { 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void postNewMessageSecondaryUserNotification() { 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Context context = Factory.get().getApplicationContext(); 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Resources resources = context.getResources(); 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PendingIntent pendingIntent = UIIntents.get() 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getPendingIntentForSecondaryUserNewMessageNotification(context); 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final NotificationCompat.Builder builder = new NotificationCompat.Builder(context); 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd builder.setContentTitle(resources.getString(R.string.secondary_user_new_message_title)) 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .setTicker(resources.getString(R.string.secondary_user_new_message_ticker)) 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .setSmallIcon(R.drawable.ic_sms_light) 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Returning PRIORITY_HIGH causes L to put up a HUD notification. Without it, the ticker 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // isn't displayed. 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .setPriority(Notification.PRIORITY_HIGH) 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .setContentIntent(pendingIntent); 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final NotificationCompat.BigTextStyle bigTextStyle = 277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new NotificationCompat.BigTextStyle(builder); 278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bigTextStyle.bigText(resources.getString(R.string.secondary_user_new_message_title)); 279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Notification notification = bigTextStyle.build(); 280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final NotificationManagerCompat notificationManager = 282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd NotificationManagerCompat.from(Factory.get().getApplicationContext()); 283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int defaults = Notification.DEFAULT_LIGHTS; 285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (BugleNotifications.shouldVibrate(new SecondaryUserNotificationState())) { 286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd defaults |= Notification.DEFAULT_VIBRATE; 287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd notification.defaults = defaults; 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd notificationManager.notify(getNotificationTag(), 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PendingIntentConstants.SMS_SECONDARY_USER_NOTIFICATION_ID, notification); 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Cancel the notification 296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void cancelSecondaryUserNotification() { 298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final NotificationManagerCompat notificationManager = 299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd NotificationManagerCompat.from(Factory.get().getApplicationContext()); 300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd notificationManager.cancel(getNotificationTag(), 301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PendingIntentConstants.SMS_SECONDARY_USER_NOTIFICATION_ID); 302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static String getNotificationTag() { 305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return Factory.get().getApplicationContext().getPackageName() + ":secondaryuser"; 306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Compile all of the patterns we check for to ignore system SMS messages. 310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void compileIgnoreSmsPatterns() { 312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Get the pattern set from GServices 313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String smsIgnoreRegex = BugleGservices.get().getString( 314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX, 315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT); 316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (smsIgnoreRegex != null) { 317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String[] ignoreSmsExpressions = smsIgnoreRegex.split("\n"); 318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ignoreSmsExpressions.length != 0) { 319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sIgnoreSmsPatterns = new ArrayList<Pattern>(); 320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < ignoreSmsExpressions.length; i++) { 321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sIgnoreSmsPatterns.add(Pattern.compile(ignoreSmsExpressions[i])); 323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (PatternSyntaxException e) { 324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(TAG, "compileIgnoreSmsPatterns: Skipping bad expression: " + 325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ignoreSmsExpressions[i]); 326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get the SMS messages from the specified SMS intent. 334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return the messages. If there is an error or the message should be ignored, return null. 335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static android.telephony.SmsMessage[] getMessagesFromIntent(Intent intent) { 337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final android.telephony.SmsMessage[] messages = Sms.Intents.getMessagesFromIntent(intent); 338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check messages for validity 340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (messages == null || messages.length < 1) { 341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access 344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the methods on it although the SmsMessage itself is not null. So do this check 345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // before we do anything on the parsed SmsMessages. 346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String messageBody = messages[0].getDisplayMessageBody(); 348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (messageBody != null) { 349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Compile patterns if necessary 350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (sIgnoreSmsPatterns == null) { 351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd compileIgnoreSmsPatterns(); 352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check against filters 354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final Pattern pattern : sIgnoreSmsPatterns) { 355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (pattern.matcher(messageBody).matches()) { 356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final NullPointerException e) { 361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(TAG, "shouldIgnoreMessage: NPE inside SmsMessage"); 362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return messages; 365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Check the specified SMS intent to see if the message should be ignored 370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return true if the message should be ignored 371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean shouldIgnoreMessage(Intent intent) { 373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return getMessagesFromIntent(intent) == null; 374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 376