summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/receiver
diff options
context:
space:
mode:
authorMike Dodd <mdodd@google.com>2015-08-11 11:16:59 -0700
committerMike Dodd <mdodd@google.com>2015-08-12 08:58:28 -0700
commit461a34b466cb4b13dbbc2ec6330b31e217b2ac4e (patch)
treebc4b489af52d0e2521e21167d2ad76a47256f348 /src/com/android/messaging/receiver
parent8b3e2b9c1b0a09423a7ba5d1091b9192106502f8 (diff)
downloadpackages_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')
-rw-r--r--src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java43
-rw-r--r--src/com/android/messaging/receiver/AbortSmsReceiver.java41
-rw-r--r--src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java49
-rw-r--r--src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java32
-rw-r--r--src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java43
-rw-r--r--src/com/android/messaging/receiver/MmsWapPushReceiver.java58
-rw-r--r--src/com/android/messaging/receiver/NotificationReceiver.java57
-rw-r--r--src/com/android/messaging/receiver/SendStatusReceiver.java96
-rw-r--r--src/com/android/messaging/receiver/SmsDeliverReceiver.java31
-rw-r--r--src/com/android/messaging/receiver/SmsReceiver.java375
-rw-r--r--src/com/android/messaging/receiver/StorageStatusReceiver.java38
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();
+ }
+ }
+}