diff options
author | Mike Dodd <mdodd@google.com> | 2015-08-11 11:16:59 -0700 |
---|---|---|
committer | Mike Dodd <mdodd@google.com> | 2015-08-12 08:58:28 -0700 |
commit | 461a34b466cb4b13dbbc2ec6330b31e217b2ac4e (patch) | |
tree | bc4b489af52d0e2521e21167d2ad76a47256f348 /src/com/android/messaging/receiver | |
parent | 8b3e2b9c1b0a09423a7ba5d1091b9192106502f8 (diff) | |
download | packages_apps_Messaging-461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.tar.gz packages_apps_Messaging-461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.tar.bz2 packages_apps_Messaging-461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.zip |
Initial checkin of AOSP Messaging app.
b/23110861
Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
Diffstat (limited to 'src/com/android/messaging/receiver')
11 files changed, 863 insertions, 0 deletions
diff --git a/src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java b/src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java new file mode 100644 index 0000000..9e09a2a --- /dev/null +++ b/src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.provider.Telephony; + +import com.android.messaging.util.ContentType; +import com.android.messaging.util.OsUtil; +import com.android.messaging.util.PhoneUtils; + +/** + * This receiver is used to abort MMS WAP broadcasts pre-KLP when SMS is enabled. + */ +public class AbortMmsWapPushReceiver extends BroadcastReceiver { + @Override + public void onReceive(final Context context, final Intent intent) { + if (Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction()) + && ContentType.MMS_MESSAGE.equals(intent.getType())) { + // If we are enabled, it's our job to stop the broadcast from continuing. This + // receiver is not used on KLP but we do an extra check here just to make sure. + if (!OsUtil.isAtLeastKLP() && PhoneUtils.getDefault().isSmsEnabled()) { + abortBroadcast(); + } + } + } +} diff --git a/src/com/android/messaging/receiver/AbortSmsReceiver.java b/src/com/android/messaging/receiver/AbortSmsReceiver.java new file mode 100644 index 0000000..f4491d8 --- /dev/null +++ b/src/com/android/messaging/receiver/AbortSmsReceiver.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.android.messaging.util.OsUtil; +import com.android.messaging.util.PhoneUtils; + +/** + * This receiver is used to abort SMS broadcasts pre-KLP when SMS is enabled. + */ +public final class AbortSmsReceiver extends BroadcastReceiver { + + @Override + public void onReceive(final Context context, final Intent intent) { + // If we are enabled, it's our job to stop the broadcast from continuing. This + // receiver is not used on KLP but we do an extra check here just to make sure. + if (!OsUtil.isAtLeastKLP() && PhoneUtils.getDefault().isSmsEnabled()) { + if (!SmsReceiver.shouldIgnoreMessage(intent)) { + abortBroadcast(); + } + } + } +} diff --git a/src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java b/src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java new file mode 100644 index 0000000..be0d296 --- /dev/null +++ b/src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.android.messaging.BugleApplication; +import com.android.messaging.Factory; +import com.android.messaging.datamodel.action.UpdateMessageNotificationAction; +import com.android.messaging.util.BuglePrefsKeys; +import com.android.messaging.util.LogUtil; + +/** + * Receives notification of boot completion and package replacement + */ +public class BootAndPackageReplacedReceiver extends BroadcastReceiver { + @Override + public void onReceive(final Context context, final Intent intent) { + if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) + || Intent.ACTION_MY_PACKAGE_REPLACED.equals(intent.getAction())) { + // Repost unseen notifications + Factory.get().getApplicationPrefs().putLong( + BuglePrefsKeys.LATEST_NOTIFICATION_MESSAGE_TIMESTAMP, Long.MIN_VALUE); + UpdateMessageNotificationAction.updateMessageNotification(); + + BugleApplication.updateAppConfig(context); + } else { + LogUtil.i(LogUtil.BUGLE_TAG, "BootAndPackageReplacedReceiver got unexpected action: " + + intent.getAction()); + } + } +} + diff --git a/src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java b/src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java new file mode 100644 index 0000000..d5153a0 --- /dev/null +++ b/src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.android.messaging.datamodel.ParticipantRefresh; + +/** + * Responds to default SMS subscription selection changes from system Settings. + */ +public class DefaultSmsSubscriptionChangeReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + ParticipantRefresh.refreshSelfParticipants(); + } +} diff --git a/src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java b/src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java new file mode 100644 index 0000000..a5c247c --- /dev/null +++ b/src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.provider.Telephony; + +import com.android.messaging.util.ContentType; +import com.android.messaging.util.PhoneUtils; + +/** + * Class that handles MMS WAP push intent from telephony on KLP+ Devices. + */ +public class MmsWapPushDeliverReceiver extends BroadcastReceiver { + + @Override + public void onReceive(final Context context, final Intent intent) { + if (Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION.equals(intent.getAction()) + && ContentType.MMS_MESSAGE.equals(intent.getType())) { + // Always convert negative subIds into -1 + int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem( + intent, MmsWapPushReceiver.EXTRA_SUBSCRIPTION); + byte[] data = intent.getByteArrayExtra(MmsWapPushReceiver.EXTRA_DATA); + MmsWapPushReceiver.mmsReceived(subId, data); + } + } +} diff --git a/src/com/android/messaging/receiver/MmsWapPushReceiver.java b/src/com/android/messaging/receiver/MmsWapPushReceiver.java new file mode 100644 index 0000000..29cf0db --- /dev/null +++ b/src/com/android/messaging/receiver/MmsWapPushReceiver.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.provider.Telephony; + +import com.android.messaging.datamodel.action.ReceiveMmsMessageAction; +import com.android.messaging.util.ContentType; +import com.android.messaging.util.PhoneUtils; + +/** + * Class that handles MMS WAP push intent from telephony on pre-KLP Devices. + */ +public class MmsWapPushReceiver extends BroadcastReceiver { + static final String EXTRA_SUBSCRIPTION = "subscription"; + static final String EXTRA_DATA = "data"; + + @Override + public void onReceive(final Context context, final Intent intent) { + if (Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction()) + && ContentType.MMS_MESSAGE.equals(intent.getType())) { + if (PhoneUtils.getDefault().isSmsEnabled()) { + // Always convert negative subIds into -1 + final int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem( + intent, MmsWapPushReceiver.EXTRA_SUBSCRIPTION); + final byte[] data = intent.getByteArrayExtra(MmsWapPushReceiver.EXTRA_DATA); + mmsReceived(subId, data); + } + } + } + + static void mmsReceived(final int subId, final byte[] data) { + if (!PhoneUtils.getDefault().isSmsEnabled()) { + return; + } + + final ReceiveMmsMessageAction action = new ReceiveMmsMessageAction(subId, data); + action.start(); + } +} + diff --git a/src/com/android/messaging/receiver/NotificationReceiver.java b/src/com/android/messaging/receiver/NotificationReceiver.java new file mode 100644 index 0000000..bbb847d --- /dev/null +++ b/src/com/android/messaging/receiver/NotificationReceiver.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.android.messaging.datamodel.BugleNotifications; +import com.android.messaging.datamodel.action.MarkAsSeenAction; +import com.android.messaging.ui.UIIntents; +import com.android.messaging.util.ConversationIdSet; +import com.android.messaging.util.LogUtil; + +// NotificationReceiver is used to handle delete intents from notifications. When a user +// clears all notifications or swipes a bugle notification away, the intent we pass in as +// the delete intent will get handled here. +public class NotificationReceiver extends BroadcastReceiver { + // Logging + public static final String TAG = LogUtil.BUGLE_TAG; + public static final boolean VERBOSE = false; + + @Override + public void onReceive(final Context context, final Intent intent) { + if (VERBOSE) { + LogUtil.v(TAG, "NotificationReceiver.onReceive: intent " + intent); + } + if (intent.getAction().equals(UIIntents.ACTION_RESET_NOTIFICATIONS)) { + final String conversationIdSetString = + intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID_SET); + final int notificationTargets = intent.getIntExtra( + UIIntents.UI_INTENT_EXTRA_NOTIFICATIONS_UPDATE, BugleNotifications.UPDATE_ALL); + if (conversationIdSetString == null) { + BugleNotifications.markAllMessagesAsSeen(); + } else { + for (final String conversationId : + ConversationIdSet.createSet(conversationIdSetString)) { + MarkAsSeenAction.markAsSeen(conversationId); + BugleNotifications.resetLastMessageDing(conversationId); + } + } + } + } +}
\ No newline at end of file diff --git a/src/com/android/messaging/receiver/SendStatusReceiver.java b/src/com/android/messaging/receiver/SendStatusReceiver.java new file mode 100644 index 0000000..fc0e8c9 --- /dev/null +++ b/src/com/android/messaging/receiver/SendStatusReceiver.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.telephony.SmsMessage; + +import com.android.messaging.datamodel.action.ProcessDeliveryReportAction; +import com.android.messaging.datamodel.action.ProcessDownloadedMmsAction; +import com.android.messaging.datamodel.action.ProcessSentMessageAction; +import com.android.messaging.datamodel.data.ParticipantData; +import com.android.messaging.sms.MmsUtils; +import com.android.messaging.sms.SmsSender; +import com.android.messaging.util.LogUtil; + +/** + * The SMS sent and delivery intent receiver. + * + * This class just simply forwards the intents to proper recipients for actual handling. + */ +public class SendStatusReceiver extends BroadcastReceiver { + public static final String MESSAGE_SENT_ACTION = + "com.android.messaging.receiver.SendStatusReceiver.MESSAGE_SENT"; + public static final String MESSAGE_DELIVERED_ACTION = + "com.android.messaging.receiver.SendStatusReceiver.MESSAGE_DELIVERED"; + public static final String MMS_SENT_ACTION = + "com.android.messaging.receiver.SendStatusReceiver.MMS_SENT"; + public static final String MMS_DOWNLOADED_ACTION = + "com.android.messaging.receiver.SendStatusReceiver.MMS_DOWNLOADED"; + + // Defined by platform, but no constant provided. See docs for SmsManager.sendTextMessage. + public static final String EXTRA_ERROR_CODE = "errorCode"; + + public static final String EXTRA_PART_ID = "partId"; + public static final String EXTRA_SUB_ID = "subId"; + + public static final int NO_ERROR_CODE = 0; + public static final int NO_PART_ID = -1; + + @Override + public void onReceive(final Context context, final Intent intent) { + // This will be called on the main thread (so it should exit quickly) + final String action = intent.getAction(); + final int resultCode = getResultCode(); + if (MESSAGE_SENT_ACTION.equals(action)) { + final Uri requestId = intent.getData(); + SmsSender.setResult( + requestId, + resultCode, + intent.getIntExtra(EXTRA_ERROR_CODE, NO_ERROR_CODE), + intent.getIntExtra(EXTRA_PART_ID, NO_PART_ID), + intent.getIntExtra(EXTRA_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID)); + } else if (MMS_SENT_ACTION.equals(action)) { + final Uri messageUri = intent.getData(); + ProcessSentMessageAction.processMmsSent(resultCode, messageUri, + intent.getExtras()); + } else if (MMS_DOWNLOADED_ACTION.equals(action)) { + ProcessDownloadedMmsAction.processMessageDownloaded(resultCode, + intent.getExtras()); + } else if (MESSAGE_DELIVERED_ACTION.equals(action)) { + final SmsMessage smsMessage = MmsUtils.getSmsMessageFromDeliveryReport(intent); + final Uri smsMessageUri = intent.getData(); + if (smsMessage == null) { + LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: empty report message"); + return; + } + int status = 0; + try { + status = smsMessage.getStatus(); + } catch (final NullPointerException e) { + // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access + // the methods on it although the SmsMessage itself is not null. + LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: NPE inside SmsMessage"); + return; + } + ProcessDeliveryReportAction.deliveryReportReceived(smsMessageUri, status); + } + } +} diff --git a/src/com/android/messaging/receiver/SmsDeliverReceiver.java b/src/com/android/messaging/receiver/SmsDeliverReceiver.java new file mode 100644 index 0000000..6a9b66c --- /dev/null +++ b/src/com/android/messaging/receiver/SmsDeliverReceiver.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +/** + * Class that receives incoming SMS messages on KLP+ Devices. + */ +public final class SmsDeliverReceiver extends BroadcastReceiver { + @Override + public void onReceive(final Context context, final Intent intent) { + SmsReceiver.deliverSmsIntent(context, intent); + } +} diff --git a/src/com/android/messaging/receiver/SmsReceiver.java b/src/com/android/messaging/receiver/SmsReceiver.java new file mode 100644 index 0000000..db9b4bb --- /dev/null +++ b/src/com/android/messaging/receiver/SmsReceiver.java @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.app.Notification; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.provider.Telephony; +import android.provider.Telephony.Sms; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationCompat.Builder; +import android.support.v4.app.NotificationCompat.Style; +import android.support.v4.app.NotificationManagerCompat; + +import java.util.ArrayList; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import com.android.messaging.Factory; +import com.android.messaging.R; +import com.android.messaging.datamodel.BugleNotifications; +import com.android.messaging.datamodel.MessageNotificationState; +import com.android.messaging.datamodel.NoConfirmationSmsSendService; +import com.android.messaging.datamodel.action.ReceiveSmsMessageAction; +import com.android.messaging.sms.MmsUtils; +import com.android.messaging.ui.UIIntents; +import com.android.messaging.util.BugleGservices; +import com.android.messaging.util.BugleGservicesKeys; +import com.android.messaging.util.DebugUtils; +import com.android.messaging.util.LogUtil; +import com.android.messaging.util.OsUtil; +import com.android.messaging.util.PendingIntentConstants; +import com.android.messaging.util.PhoneUtils; + +/** + * Class that receives incoming SMS messages through android.provider.Telephony.SMS_RECEIVED + * + * This class serves two purposes: + * - Process phone verification SMS messages + * - Handle SMS messages when the user has enabled us to be the default SMS app (Pre-KLP) + */ +public final class SmsReceiver extends BroadcastReceiver { + private static final String TAG = LogUtil.BUGLE_TAG; + + private static ArrayList<Pattern> sIgnoreSmsPatterns; + + /** + * Enable or disable the SmsReceiver as appropriate. Pre-KLP we use this receiver for + * receiving incoming SMS messages. For KLP+ this receiver is not used when running as the + * primary user and the SmsDeliverReceiver is used for receiving incoming SMS messages. + * When running as a secondary user, this receiver is still used to trigger the incoming + * notification. + */ + public static void updateSmsReceiveHandler(final Context context) { + boolean smsReceiverEnabled; + boolean mmsWapPushReceiverEnabled; + boolean respondViaMessageEnabled; + boolean broadcastAbortEnabled; + + if (OsUtil.isAtLeastKLP()) { + // When we're running as the secondary user, we don't get the new SMS_DELIVER intent, + // only the primary user receives that. As secondary, we need to go old-school and + // listen for the SMS_RECEIVED intent. For the secondary user, use this SmsReceiver + // for both sms and mms notification. For the primary user on KLP (and above), we don't + // use the SmsReceiver. + smsReceiverEnabled = OsUtil.isSecondaryUser(); + // On KLP use the new deliver event for mms + mmsWapPushReceiverEnabled = false; + // On KLP we need to always enable this handler to show in the list of sms apps + respondViaMessageEnabled = true; + // On KLP we don't need to abort the broadcast + broadcastAbortEnabled = false; + } else { + // On JB we use the sms receiver for both sms/mms delivery + final boolean carrierSmsEnabled = PhoneUtils.getDefault().isSmsEnabled(); + smsReceiverEnabled = carrierSmsEnabled; + + // On JB we use the mms receiver when sms/mms is enabled + mmsWapPushReceiverEnabled = carrierSmsEnabled; + // On JB this is dynamic to make sure we don't show in dialer if sms is disabled + respondViaMessageEnabled = carrierSmsEnabled; + // On JB we need to abort broadcasts if SMS is enabled + broadcastAbortEnabled = carrierSmsEnabled; + } + + final PackageManager packageManager = context.getPackageManager(); + final boolean logv = LogUtil.isLoggable(TAG, LogUtil.VERBOSE); + if (smsReceiverEnabled) { + if (logv) { + LogUtil.v(TAG, "Enabling SMS message receiving"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, SmsReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + + } else { + if (logv) { + LogUtil.v(TAG, "Disabling SMS message receiving"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, SmsReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + } + if (mmsWapPushReceiverEnabled) { + if (logv) { + LogUtil.v(TAG, "Enabling MMS message receiving"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, MmsWapPushReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + } else { + if (logv) { + LogUtil.v(TAG, "Disabling MMS message receiving"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, MmsWapPushReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + } + if (broadcastAbortEnabled) { + if (logv) { + LogUtil.v(TAG, "Enabling SMS/MMS broadcast abort"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, AbortSmsReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + packageManager.setComponentEnabledSetting( + new ComponentName(context, AbortMmsWapPushReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + } else { + if (logv) { + LogUtil.v(TAG, "Disabling SMS/MMS broadcast abort"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, AbortSmsReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + packageManager.setComponentEnabledSetting( + new ComponentName(context, AbortMmsWapPushReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + } + if (respondViaMessageEnabled) { + if (logv) { + LogUtil.v(TAG, "Enabling respond via message intent"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, NoConfirmationSmsSendService.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + } else { + if (logv) { + LogUtil.v(TAG, "Disabling respond via message intent"); + } + packageManager.setComponentEnabledSetting( + new ComponentName(context, NoConfirmationSmsSendService.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + } + } + + private static final String EXTRA_ERROR_CODE = "errorCode"; + private static final String EXTRA_SUB_ID = "subscription"; + + public static void deliverSmsIntent(final Context context, final Intent intent) { + final android.telephony.SmsMessage[] messages = getMessagesFromIntent(intent); + + // Check messages for validity + if (messages == null || messages.length < 1) { + LogUtil.e(TAG, "processReceivedSms: null or zero or ignored message"); + return; + } + + final int errorCode = intent.getIntExtra(EXTRA_ERROR_CODE, 0); + // Always convert negative subIds into -1 + int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem( + intent, EXTRA_SUB_ID); + deliverSmsMessages(context, subId, errorCode, messages); + if (MmsUtils.isDumpSmsEnabled()) { + final String format = null; + DebugUtils.dumpSms(messages[0].getTimestampMillis(), messages, format); + } + } + + public static void deliverSmsMessages(final Context context, final int subId, + final int errorCode, final android.telephony.SmsMessage[] messages) { + final ContentValues messageValues = + MmsUtils.parseReceivedSmsMessage(context, messages, errorCode); + + LogUtil.v(TAG, "SmsReceiver.deliverSmsMessages"); + + final long nowInMillis = System.currentTimeMillis(); + final long receivedTimestampMs = MmsUtils.getMessageDate(messages[0], nowInMillis); + + messageValues.put(Sms.Inbox.DATE, receivedTimestampMs); + // Default to unread and unseen for us but ReceiveSmsMessageAction will override + // seen for the telephony db. + messageValues.put(Sms.Inbox.READ, 0); + messageValues.put(Sms.Inbox.SEEN, 0); + if (OsUtil.isAtLeastL_MR1()) { + messageValues.put(Sms.SUBSCRIPTION_ID, subId); + } + + if (messages[0].getMessageClass() == android.telephony.SmsMessage.MessageClass.CLASS_0 || + DebugUtils.debugClassZeroSmsEnabled()) { + Factory.get().getUIIntents().launchClassZeroActivity(context, messageValues); + } else { + final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(messageValues); + action.start(); + } + } + + @Override + public void onReceive(final Context context, final Intent intent) { + LogUtil.v(TAG, "SmsReceiver.onReceive " + intent); + // On KLP+ we only take delivery of SMS messages in SmsDeliverReceiver. + if (PhoneUtils.getDefault().isSmsEnabled()) { + final String action = intent.getAction(); + if (OsUtil.isSecondaryUser() && + (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action) || + // TODO: update this with the actual constant from Telephony + "android.provider.Telephony.MMS_DOWNLOADED".equals(action))) { + postNewMessageSecondaryUserNotification(); + } else if (!OsUtil.isAtLeastKLP()) { + deliverSmsIntent(context, intent); + } + } + } + + private static class SecondaryUserNotificationState extends MessageNotificationState { + SecondaryUserNotificationState() { + super(null); + } + + @Override + protected Style build(Builder builder) { + return null; + } + + @Override + public boolean getNotificationVibrate() { + return true; + } + } + + public static void postNewMessageSecondaryUserNotification() { + final Context context = Factory.get().getApplicationContext(); + final Resources resources = context.getResources(); + final PendingIntent pendingIntent = UIIntents.get() + .getPendingIntentForSecondaryUserNewMessageNotification(context); + + final NotificationCompat.Builder builder = new NotificationCompat.Builder(context); + builder.setContentTitle(resources.getString(R.string.secondary_user_new_message_title)) + .setTicker(resources.getString(R.string.secondary_user_new_message_ticker)) + .setSmallIcon(R.drawable.ic_sms_light) + // Returning PRIORITY_HIGH causes L to put up a HUD notification. Without it, the ticker + // isn't displayed. + .setPriority(Notification.PRIORITY_HIGH) + .setContentIntent(pendingIntent); + + final NotificationCompat.BigTextStyle bigTextStyle = + new NotificationCompat.BigTextStyle(builder); + bigTextStyle.bigText(resources.getString(R.string.secondary_user_new_message_title)); + final Notification notification = bigTextStyle.build(); + + final NotificationManagerCompat notificationManager = + NotificationManagerCompat.from(Factory.get().getApplicationContext()); + + int defaults = Notification.DEFAULT_LIGHTS; + if (BugleNotifications.shouldVibrate(new SecondaryUserNotificationState())) { + defaults |= Notification.DEFAULT_VIBRATE; + } + notification.defaults = defaults; + + notificationManager.notify(getNotificationTag(), + PendingIntentConstants.SMS_SECONDARY_USER_NOTIFICATION_ID, notification); + } + + /** + * Cancel the notification + */ + public static void cancelSecondaryUserNotification() { + final NotificationManagerCompat notificationManager = + NotificationManagerCompat.from(Factory.get().getApplicationContext()); + notificationManager.cancel(getNotificationTag(), + PendingIntentConstants.SMS_SECONDARY_USER_NOTIFICATION_ID); + } + + private static String getNotificationTag() { + return Factory.get().getApplicationContext().getPackageName() + ":secondaryuser"; + } + + /** + * Compile all of the patterns we check for to ignore system SMS messages. + */ + private static void compileIgnoreSmsPatterns() { + // Get the pattern set from GServices + final String smsIgnoreRegex = BugleGservices.get().getString( + BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX, + BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT); + if (smsIgnoreRegex != null) { + final String[] ignoreSmsExpressions = smsIgnoreRegex.split("\n"); + if (ignoreSmsExpressions.length != 0) { + sIgnoreSmsPatterns = new ArrayList<Pattern>(); + for (int i = 0; i < ignoreSmsExpressions.length; i++) { + try { + sIgnoreSmsPatterns.add(Pattern.compile(ignoreSmsExpressions[i])); + } catch (PatternSyntaxException e) { + LogUtil.e(TAG, "compileIgnoreSmsPatterns: Skipping bad expression: " + + ignoreSmsExpressions[i]); + } + } + } + } + } + + /** + * Get the SMS messages from the specified SMS intent. + * @return the messages. If there is an error or the message should be ignored, return null. + */ + public static android.telephony.SmsMessage[] getMessagesFromIntent(Intent intent) { + final android.telephony.SmsMessage[] messages = Sms.Intents.getMessagesFromIntent(intent); + + // Check messages for validity + if (messages == null || messages.length < 1) { + return null; + } + // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access + // the methods on it although the SmsMessage itself is not null. So do this check + // before we do anything on the parsed SmsMessages. + try { + final String messageBody = messages[0].getDisplayMessageBody(); + if (messageBody != null) { + // Compile patterns if necessary + if (sIgnoreSmsPatterns == null) { + compileIgnoreSmsPatterns(); + } + // Check against filters + for (final Pattern pattern : sIgnoreSmsPatterns) { + if (pattern.matcher(messageBody).matches()) { + return null; + } + } + } + } catch (final NullPointerException e) { + LogUtil.e(TAG, "shouldIgnoreMessage: NPE inside SmsMessage"); + return null; + } + return messages; + } + + + /** + * Check the specified SMS intent to see if the message should be ignored + * @return true if the message should be ignored + */ + public static boolean shouldIgnoreMessage(Intent intent) { + return getMessagesFromIntent(intent) == null; + } +} diff --git a/src/com/android/messaging/receiver/StorageStatusReceiver.java b/src/com/android/messaging/receiver/StorageStatusReceiver.java new file mode 100644 index 0000000..bee899c --- /dev/null +++ b/src/com/android/messaging/receiver/StorageStatusReceiver.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.messaging.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.android.messaging.sms.SmsStorageStatusManager; + +/** + * Receiver that listens on storage status changes + */ +public class StorageStatusReceiver extends BroadcastReceiver { + + @Override + public void onReceive(final Context context, final Intent intent) { + if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction())) { + SmsStorageStatusManager.handleStorageLow(); + } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction())) { + SmsStorageStatusManager.handleStorageOk(); + } + } +} |