MessagingNotification.java revision 674b5045f39aedf85e6a7e38237860d000f46de0
172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.transaction;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
21f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF;
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.R;
24812391ad832f3fdac054ad3a50af563da16e99b5Wei Huangimport com.android.mms.LogTag;
2533a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrickimport com.android.mms.data.Contact;
2670c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrickimport com.android.mms.data.Conversation;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.ui.ComposeMessageActivity;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.ui.ConversationList;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.ui.MessagingPreferenceActivity;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.AddressUtils;
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.DownloadManager;
32c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylorimport com.android.mms.widget.MmsWidgetProvider;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
34f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.EncodedStringValue;
35f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduHeaders;
36f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.google.android.mms.pdu.PduPersister;
37fd644551e8506266aad2b76463b51b44154ed62fTom Taylorimport android.database.sqlite.SqliteWrapper;
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Notification;
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.NotificationManager;
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.PendingIntent;
421fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylorimport android.content.ComponentName;
4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver;
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent;
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.SharedPreferences;
4770f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.BroadcastReceiver;
4870f5af8fd89d66ae246a805d10a50540746319aaWei Huangimport android.content.IntentFilter;
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.graphics.Typeface;
51006d49271549ed639ffcd70d94c7650bb3514796Jim Shumaimport android.media.AudioManager;
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
53b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylorimport android.os.AsyncTask;
545a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylorimport android.os.Handler;
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.preference.PreferenceManager;
56f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms;
57f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms;
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.Spannable;
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.SpannableString;
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils;
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.style.StyleSpan;
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
63800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERTimport android.widget.Toast;
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.Comparator;
66b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrickimport java.util.HashSet;
67b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrickimport java.util.Set;
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.SortedSet;
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.TreeSet;
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This class is used to update the notification indicator. It will check whether
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * there are unread messages. If yes, it would show the notification indicator,
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * otherwise, hide the indicator.
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class MessagingNotification {
77c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
78812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang    private static final String TAG = LogTag.APP;
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int NOTIFICATION_ID = 123;
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final int MESSAGE_FAILED_NOTIFICATION_ID = 789;
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final int DOWNLOAD_FAILED_NOTIFICATION_ID = 531;
83c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    /**
84c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * This is the volume at which to play the in-conversation notification sound,
85c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * expressed as a fraction of the system notification volume.
86c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     */
87c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    private static final float IN_CONVERSATION_NOTIFICATION_VOLUME = 0.25f;
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This must be consistent with the column constants below.
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String[] MMS_STATUS_PROJECTION = new String[] {
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Mms.THREAD_ID, Mms.DATE, Mms._ID, Mms.SUBJECT, Mms.SUBJECT_CHARSET };
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This must be consistent with the column constants below.
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String[] SMS_STATUS_PROJECTION = new String[] {
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms.THREAD_ID, Sms.DATE, Sms.ADDRESS, Sms.SUBJECT, Sms.BODY };
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // These must be consistent with MMS_STATUS_PROJECTION and
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // SMS_STATUS_PROJECTION.
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_THREAD_ID   = 0;
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_DATE        = 1;
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_MMS_ID      = 2;
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_SMS_ADDRESS = 2;
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_SUBJECT     = 3;
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_SUBJECT_CS  = 4;
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int COLUMN_SMS_BODY    = 4;
10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
107c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    private static final String[] SMS_THREAD_ID_PROJECTION = new String[] { Sms.THREAD_ID };
108c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    private static final String[] MMS_THREAD_ID_PROJECTION = new String[] { Mms.THREAD_ID };
109c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String NEW_INCOMING_SM_CONSTRAINT =
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_INBOX
112627007213deb59ef938c80353c8f3598b01478b3Wei Huang            + " AND " + Sms.SEEN + " = 0)";
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
114800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT    private static final String NEW_DELIVERY_SM_CONSTRAINT =
115c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_SENT
116c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        + " AND " + Sms.STATUS + " = "+ Sms.STATUS_COMPLETE +")";
117800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String NEW_INCOMING_MM_CONSTRAINT =
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX
120627007213deb59ef938c80353c8f3598b01478b3Wei Huang            + " AND " + Mms.SEEN + "=0"
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            + " AND (" + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_NOTIFICATION_IND
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            + " OR " + Mms.MESSAGE_TYPE + "=" + MESSAGE_TYPE_RETRIEVE_CONF + "))";
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final MmsSmsNotificationInfoComparator INFO_COMPARATOR =
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            new MmsSmsNotificationInfoComparator();
1265a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final Uri UNDELIVERED_URI = Uri.parse("content://mms-sms/undelivered");
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12970f5af8fd89d66ae246a805d10a50540746319aaWei Huang
13070f5af8fd89d66ae246a805d10a50540746319aaWei Huang    private final static String NOTIFICATION_DELETED_ACTION =
13170f5af8fd89d66ae246a805d10a50540746319aaWei Huang            "com.android.mms.NOTIFICATION_DELETED_ACTION";
13270f5af8fd89d66ae246a805d10a50540746319aaWei Huang
13370f5af8fd89d66ae246a805d10a50540746319aaWei Huang    public static class OnDeletedReceiver extends BroadcastReceiver {
134c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        @Override
13570f5af8fd89d66ae246a805d10a50540746319aaWei Huang        public void onReceive(Context context, Intent intent) {
13670f5af8fd89d66ae246a805d10a50540746319aaWei Huang            if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
13770f5af8fd89d66ae246a805d10a50540746319aaWei Huang                Log.d(TAG, "[MessagingNotification] clear notification: mark all msgs seen");
13870f5af8fd89d66ae246a805d10a50540746319aaWei Huang            }
13970f5af8fd89d66ae246a805d10a50540746319aaWei Huang
14070f5af8fd89d66ae246a805d10a50540746319aaWei Huang            Conversation.markAllConversationsAsSeen(context);
14170f5af8fd89d66ae246a805d10a50540746319aaWei Huang        }
142c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    }
143c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
144c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    public static final long THREAD_ALL = -1;
145c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    public static final long THREAD_NONE = -2;
146c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    /**
147c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * Keeps track of the thread ID of the conversation that's currently displayed to the user
148c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     */
149c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    private static long sCurrentlyDisplayedThreadId;
150c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    private static final Object sCurrentlyDisplayedThreadLock = new Object();
151c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
15270f5af8fd89d66ae246a805d10a50540746319aaWei Huang    private static OnDeletedReceiver sNotificationDeletedReceiver = new OnDeletedReceiver();
15370f5af8fd89d66ae246a805d10a50540746319aaWei Huang    private static Intent sNotificationOnDeleteIntent;
1545a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor    private static Handler mToastHandler = new Handler();
15570f5af8fd89d66ae246a805d10a50540746319aaWei Huang
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private MessagingNotification() {
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15970f5af8fd89d66ae246a805d10a50540746319aaWei Huang    public static void init(Context context) {
16070f5af8fd89d66ae246a805d10a50540746319aaWei Huang        // set up the intent filter for notification deleted action
16170f5af8fd89d66ae246a805d10a50540746319aaWei Huang        IntentFilter intentFilter = new IntentFilter();
16270f5af8fd89d66ae246a805d10a50540746319aaWei Huang        intentFilter.addAction(NOTIFICATION_DELETED_ACTION);
16370f5af8fd89d66ae246a805d10a50540746319aaWei Huang        context.registerReceiver(sNotificationDeletedReceiver, intentFilter);
16470f5af8fd89d66ae246a805d10a50540746319aaWei Huang
16570f5af8fd89d66ae246a805d10a50540746319aaWei Huang        // initialize the notification deleted action
16670f5af8fd89d66ae246a805d10a50540746319aaWei Huang        sNotificationOnDeleteIntent = new Intent(NOTIFICATION_DELETED_ACTION);
16770f5af8fd89d66ae246a805d10a50540746319aaWei Huang    }
16870f5af8fd89d66ae246a805d10a50540746319aaWei Huang
16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
170c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * Specifies which message thread is currently being viewed by the user. New messages in that
171c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * thread will not generate a notification icon and will play the notification sound at a lower
172c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * volume. Make sure you set this to THREAD_NONE when the UI component that shows the thread is
173c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * no longer visible to the user (e.g. Activity.onPause(), etc.)
174c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param threadId The ID of the thread that the user is currently viewing. Pass THREAD_NONE
175c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     *  if the user is not viewing a thread, or THREAD_ALL if the user is viewing the conversation
176c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     *  list (note: that latter one has no effect as of this implementation)
177c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     */
178c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    public static void setCurrentlyDisplayedThreadId(long threadId) {
179c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        synchronized (sCurrentlyDisplayedThreadLock) {
180c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            sCurrentlyDisplayedThreadId = threadId;
181c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
182c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    }
183c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
184c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    /**
185627007213deb59ef938c80353c8f3598b01478b3Wei Huang     * Checks to see if there are any "unseen" messages or delivery
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * reports.  Shows the most recent notification if there is one.
1873b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor     * Does its work and query in a worker thread.
18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *
18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param context the context to use
19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
1913b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor    public static void nonBlockingUpdateNewMessageIndicator(final Context context,
192c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            final long newMsgThreadId,
1933b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor            final boolean isStatusMessage) {
1943b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        new Thread(new Runnable() {
195c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            @Override
1963b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor            public void run() {
197c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                blockingUpdateNewMessageIndicator(context, newMsgThreadId, isStatusMessage);
1983b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor            }
199ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        }, "MessagingNotification.nonBlockingUpdateNewMessageIndicator").start();
20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
203627007213deb59ef938c80353c8f3598b01478b3Wei Huang     * Checks to see if there are any "unseen" messages or delivery
20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * reports.  Shows the most recent notification if there is one.
20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *
20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param context the context to use
207c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param newMsgThreadId The thread ID of a new message that we're to notify about; if there's
208c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     *  no new message, use THREAD_NONE. If we should notify about multiple or unknown thread IDs,
209c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     *  use THREAD_ALL.
210c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param isStatusMessage
21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
212c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    public static void blockingUpdateNewMessageIndicator(Context context, long newMsgThreadId,
213c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            boolean isStatusMessage) {
214c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        synchronized (sCurrentlyDisplayedThreadLock) {
215c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            if (newMsgThreadId > 0 && newMsgThreadId == sCurrentlyDisplayedThreadId) {
216c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                playInConversationNotificationSound(context);
217c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                return;
218c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            }
219c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
220c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SortedSet<MmsSmsNotificationInfo> accumulator =
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                new TreeSet<MmsSmsNotificationInfo>(INFO_COMPARATOR);
223c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        MmsSmsDeliveryInfo delivery = null;
224b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        Set<Long> threads = new HashSet<Long>(4);
2255a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int count = 0;
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        count += accumulateNotificationInfo(
228b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                accumulator, getMmsNewMessageNotificationInfo(context, threads));
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        count += accumulateNotificationInfo(
230b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                accumulator, getSmsNewMessageNotificationInfo(context, threads));
23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        cancelNotification(context, NOTIFICATION_ID);
23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!accumulator.isEmpty()) {
234e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang            if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
235e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang                Log.d(TAG, "blockingUpdateNewMessageIndicator: count=" + count +
236c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                        ", newMsgThreadId=" + newMsgThreadId);
237e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang            }
238c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            accumulator.first().deliver(context, newMsgThreadId != THREAD_NONE, count, threads.size());
23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
2405a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
2413b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // And deals with delivery reports (which use Toasts). It's safe to call in a worker
2423b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // thread because the toast will eventually get posted to a handler.
243627007213deb59ef938c80353c8f3598b01478b3Wei Huang        delivery = getSmsNewDeliveryInfo(context);
244627007213deb59ef938c80353c8f3598b01478b3Wei Huang        if (delivery != null) {
245c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            delivery.deliver(context, isStatusMessage);
246627007213deb59ef938c80353c8f3598b01478b3Wei Huang        }
24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
250c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * Play the in-conversation notification sound (it's the regular notification sound, but
251c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * played at half-volume
252c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     */
253c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    private static void playInConversationNotificationSound(Context context) {
254c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        final AudioManager audioManager =
255c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
256c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
257c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
258c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE,
259c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                null);
260c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        if (TextUtils.isEmpty(ringtoneStr)) {
261c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            // Nothing to play
262c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            return;
263c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
264c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        Uri ringtoneUri = Uri.parse(ringtoneStr);
265c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        NotificationPlayer player = new NotificationPlayer(LogTag.APP);
266c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        player.play(context, ringtoneUri, false, AudioManager.STREAM_NOTIFICATION,
267c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                IN_CONVERSATION_NOTIFICATION_VOLUME);
268c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    }
269c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
270c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    /**
27135a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick     * Updates all pending notifications, clearing or updating them as
2723b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor     * necessary.
27335a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick     */
274627007213deb59ef938c80353c8f3598b01478b3Wei Huang    public static void blockingUpdateAllNotifications(final Context context) {
275c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        nonBlockingUpdateNewMessageIndicator(context, THREAD_NONE, false);
276b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor        nonBlockingUpdateSendFailedNotification(context);
277627007213deb59ef938c80353c8f3598b01478b3Wei Huang        updateDownloadFailedNotification(context);
278c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor        MmsWidgetProvider.notifyDatasetChanged(context);
27935a74a9e0ee7c171c6e17f0eda4b0df0253f8364Ficus Kirkpatrick    }
2805a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int accumulateNotificationInfo(
282c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            SortedSet<MmsSmsNotificationInfo> set, MmsSmsNotificationInfo info) {
28372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (info != null) {
28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            set.add(info);
28572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return info.mCount;
28772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return 0;
29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
292800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT    private static final class MmsSmsDeliveryInfo {
293c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        public CharSequence mTicker;
294c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        public long mTimeMillis;
295c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor
296c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        public MmsSmsDeliveryInfo(CharSequence ticker, long timeMillis) {
297c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            mTicker = ticker;
298c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            mTimeMillis = timeMillis;
299c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        }
300c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor
301c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        public void deliver(Context context, boolean isStatusMessage) {
302c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            updateDeliveryNotification(
303c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor                    context, isStatusMessage, mTicker, mTimeMillis);
304c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        }
305800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT    }
306800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
30772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final class MmsSmsNotificationInfo {
308c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final Intent mClickIntent;
309c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final String mDescription;
310c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final int mIconResourceId;
311c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final CharSequence mTicker;
312c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final long mTimeMillis;
313c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final String mTitle;
314c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        public final int mCount;
31572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public MmsSmsNotificationInfo(
31772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Intent clickIntent, String description, int iconResourceId,
31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                CharSequence ticker, long timeMillis, String title, int count) {
31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mClickIntent = clickIntent;
32072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mDescription = description;
32172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mIconResourceId = iconResourceId;
32272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mTicker = ticker;
32372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mTimeMillis = timeMillis;
32472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mTitle = title;
32572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mCount = count;
32672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
32772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
328b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        public void deliver(Context context, boolean isNew, int count, int uniqueThreads) {
32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            updateNotification(
3303c68b6852913222dd982dddd4e39b3e57613c37eWei Huang                    context, mClickIntent, mDescription, mIconResourceId, isNew,
3313c68b6852913222dd982dddd4e39b3e57613c37eWei Huang                    (isNew? mTicker : null), // only display the ticker if the message is new
3323c68b6852913222dd982dddd4e39b3e57613c37eWei Huang                    mTimeMillis, mTitle, count, uniqueThreads);
33372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public long getTime() {
33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return mTimeMillis;
33772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
33972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
34072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final class MmsSmsNotificationInfoComparator
34172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            implements Comparator<MmsSmsNotificationInfo> {
342c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        @Override
34372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public int compare(
34472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                MmsSmsNotificationInfo info1, MmsSmsNotificationInfo info2) {
34572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return Long.signum(info2.getTime() - info1.getTime());
34672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
34772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
34872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3493b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor    private static final MmsSmsNotificationInfo getMmsNewMessageNotificationInfo(
350b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            Context context, Set<Long> threads) {
35172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentResolver resolver = context.getContentResolver();
3523b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor
3533b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // This query looks like this when logged:
3543b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // I/Database(  147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/
3553b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1
3563b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc
3573b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor
35872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor cursor = SqliteWrapper.query(context, resolver, Mms.CONTENT_URI,
35972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT,
36072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            null, Mms.DATE + " desc");
36172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
362b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        if (cursor == null) {
363b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            return null;
364b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        }
3655a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
366b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        try {
367b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            if (!cursor.moveToFirst()) {
368b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                return null;
36972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
370c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
371b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            long msgId = cursor.getLong(COLUMN_MMS_ID);
372b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath(
373b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    Long.toString(msgId)).build();
374b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            String address = AddressUtils.getFrom(context, msgUri);
3751b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor
3761b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor            Contact contact = Contact.get(address, false);
3771b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor            if (contact.getSendToVoicemail()) {
3781b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor                // don't notify
3791b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor                return null;
3801b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor            }
3811b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor
382b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            String subject = getMmsSubject(
383b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS));
384b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            long threadId = cursor.getLong(COLUMN_THREAD_ID);
385b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            long timeMillis = cursor.getLong(COLUMN_DATE) * 1000;
386b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
387e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang            if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
388e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang                Log.d(TAG, "getMmsNewMessageNotificationInfo: count=" + cursor.getCount() +
389e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang                        ", first addr = " + address + ", thread_id=" + threadId);
390e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang            }
391e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang
392b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            MmsSmsNotificationInfo info = getNewMessageNotificationInfo(
393b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    address, subject, context,
394b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    R.drawable.stat_notify_mms, null, threadId,
395b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    timeMillis, cursor.getCount());
396b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
397b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            threads.add(threadId);
398b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            while (cursor.moveToNext()) {
399b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                threads.add(cursor.getLong(COLUMN_THREAD_ID));
400b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            }
401b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
402b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            return info;
403b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        } finally {
404b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            cursor.close();
40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4083b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor    private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) {
409627007213deb59ef938c80353c8f3598b01478b3Wei Huang        ContentResolver resolver = context.getContentResolver();
410627007213deb59ef938c80353c8f3598b01478b3Wei Huang        Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI,
411627007213deb59ef938c80353c8f3598b01478b3Wei Huang                    SMS_STATUS_PROJECTION, NEW_DELIVERY_SM_CONSTRAINT,
4126a9c779f0c0dc6cf3ae942ff70fb6c806aa166dcBanavathu, Srinivas Naik                    null, Sms.DATE);
413800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
414ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom        if (cursor == null) {
415627007213deb59ef938c80353c8f3598b01478b3Wei Huang            return null;
416ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom        }
417800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
418627007213deb59ef938c80353c8f3598b01478b3Wei Huang        try {
419ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom            if (!cursor.moveToLast()) {
420ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom                return null;
421ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom            }
422800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
423627007213deb59ef938c80353c8f3598b01478b3Wei Huang            String address = cursor.getString(COLUMN_SMS_ADDRESS);
424627007213deb59ef938c80353c8f3598b01478b3Wei Huang            long timeMillis = 3000;
425800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
426ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom            Contact contact = Contact.get(address, false);
427ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom            String name = contact.getNameAndNumber();
428ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom
429ac9a5e52dc349faae2a7d8a990ff2b674c61f027Alexander Blom            return new MmsSmsDeliveryInfo(context.getString(R.string.delivery_toast_body, name),
430627007213deb59ef938c80353c8f3598b01478b3Wei Huang                timeMillis);
431800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
432627007213deb59ef938c80353c8f3598b01478b3Wei Huang        } finally {
433627007213deb59ef938c80353c8f3598b01478b3Wei Huang            cursor.close();
434627007213deb59ef938c80353c8f3598b01478b3Wei Huang        }
435800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT    }
436800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
4373b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor    private static final MmsSmsNotificationInfo getSmsNewMessageNotificationInfo(
438b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            Context context, Set<Long> threads) {
43972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentResolver resolver = context.getContentResolver();
44072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor cursor = SqliteWrapper.query(context, resolver, Sms.CONTENT_URI,
44172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            SMS_STATUS_PROJECTION, NEW_INCOMING_SM_CONSTRAINT,
44272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            null, Sms.DATE + " desc");
44372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
444b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        if (cursor == null) {
445b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            return null;
446b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        }
4475a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
448b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        try {
449b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            if (!cursor.moveToFirst()) {
450b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                return null;
451b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            }
452b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
453b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            String address = cursor.getString(COLUMN_SMS_ADDRESS);
4541b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor
4551b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor            Contact contact = Contact.get(address, false);
4561b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor            if (contact.getSendToVoicemail()) {
4571b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor                // don't notify
4581b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor                return null;
4591b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor            }
4601b8df494e49bf934fe160baea54ab5afc2ff3100Tom Taylor
461b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            String body = cursor.getString(COLUMN_SMS_BODY);
462b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            long threadId = cursor.getLong(COLUMN_THREAD_ID);
463b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            long timeMillis = cursor.getLong(COLUMN_DATE);
464b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
465d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor            if (Log.isLoggable(LogTag.APP, Log.VERBOSE))
466e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang            {
467e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang                Log.d(TAG, "getSmsNewMessageNotificationInfo: count=" + cursor.getCount() +
468e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang                        ", first addr=" + address + ", thread_id=" + threadId);
469e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang            }
470e14b79584cca1bf7ba60c53bd7e3d6386adbfc59Wei Huang
471b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            MmsSmsNotificationInfo info = getNewMessageNotificationInfo(
472b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    address, body, context, R.drawable.stat_notify_sms,
473b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    null, threadId, timeMillis, cursor.getCount());
474b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
475b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            threads.add(threadId);
476b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            while (cursor.moveToNext()) {
477b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                threads.add(cursor.getLong(COLUMN_THREAD_ID));
47872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
479b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
480b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            return info;
481b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        } finally {
482b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            cursor.close();
48372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
48472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
48572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
48672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final MmsSmsNotificationInfo getNewMessageNotificationInfo(
48772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String address,
48872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String body,
48972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Context context,
49072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int iconResourceId,
49172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String subject,
49272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            long threadId,
49372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            long timeMillis,
49472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int count) {
495812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        Intent clickIntent = ComposeMessageActivity.createIntent(context, threadId);
496812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
497812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang                | Intent.FLAG_ACTIVITY_SINGLE_TOP
498812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
49972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
50072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String senderInfo = buildTickerMessage(
50172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                context, address, null, null).toString();
50272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String senderInfoName = senderInfo.substring(
50372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                0, senderInfo.length() - 2);
50472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        CharSequence ticker = buildTickerMessage(
50572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                context, address, subject, body);
50672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
50772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return new MmsSmsNotificationInfo(
50872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                clickIntent, body, iconResourceId, ticker, timeMillis,
50972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                senderInfoName, count);
51072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
51172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
51272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void cancelNotification(Context context, int notificationId) {
51372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        NotificationManager nm = (NotificationManager) context.getSystemService(
51472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Context.NOTIFICATION_SERVICE);
51572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
51672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        nm.cancel(notificationId);
51772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
51872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5195a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor    private static void updateDeliveryNotification(final Context context,
520c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor                                                   boolean isStatusMessage,
5215a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor                                                   final CharSequence message,
5225a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor                                                   final long timeMillis) {
523c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        if (!isStatusMessage) {
524c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            return;
525c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        }
526c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor
527800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
528d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor        if (!MessagingPreferenceActivity.getNotificationEnabled(context)) {
52970f5af8fd89d66ae246a805d10a50540746319aaWei Huang            return;
53070f5af8fd89d66ae246a805d10a50540746319aaWei Huang        }
531800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
532c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        mToastHandler.post(new Runnable() {
533c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            @Override
534c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            public void run() {
535c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor                Toast.makeText(context, message, (int)timeMillis).show();
536c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor            }
537c36deab7d27940a07554cc424114d9c9ddd36552Tom Taylor        });
538800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT    }
539800f2ac17e15b24e93158574649e821a334c491eAlexis ROBERT
54072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static void updateNotification(
54172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Context context,
54272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Intent clickIntent,
54372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String description,
54472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int iconRes,
54572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            boolean isNew,
54672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            CharSequence ticker,
54772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            long timeMillis,
54872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String title,
549b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            int messageCount,
550b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            int uniqueThreadCount) {
551d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor        if (!MessagingPreferenceActivity.getNotificationEnabled(context)) {
55272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return;
55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
55472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
555674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        final Notification.Builder noti = new Notification.Builder(context)
556674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                .setSmallIcon(iconRes)
557674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                .setTicker(ticker)
558674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                .setWhen(timeMillis);
559674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler
5601fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor        Intent[] intents;
561b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick
562b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // If we have more than one unique thread, change the title (which would
563b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // normally be the contact who sent the message) to a generic one that
564b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // makes sense for multiple senders, and change the Intent to take the
565b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // user to the conversation list instead of the specific thread.
566674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler
567674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        // TODO: use forthcoming notification templates to either:
568674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        //  - hoist one message out and show an overflow summary, or
569674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        //  - show a digest of the last N threads
570b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        if (uniqueThreadCount > 1) {
571b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            title = context.getString(R.string.notification_multiple_title);
5721fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            Intent mainActivityIntent = new Intent(Intent.ACTION_MAIN);
573812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
5741fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
575812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
576812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
577812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
5781fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            mainActivityIntent.setType("vnd.android-dir/mms-sms");
5791fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            intents = new Intent[1];
5801fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            intents[0] = mainActivityIntent;
5811fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor        } else {
5821fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            // Build a stack of intents so when the user hits back from the ComposeMessageActivity
5831fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            // we're sending them to, they'll up on ConversationList.
5841fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            intents = new Intent[2];
5851fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor
5861fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            // First: root activity of the MessagingApp: ConversationList.
5871fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            // This is a convenient way to make the proper Intent to launch and
5881fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            // reset an application's task.
5891fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            intents[0] = Intent.makeRestartActivityTask(new ComponentName(context,
5901fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor                    ConversationList.class));
5911fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor            intents[1] = clickIntent;
592b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        }
5935a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
594b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // If there is more than one message, change the description (which
595b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // would normally be a snippet of the individual message text) to
596627007213deb59ef938c80353c8f3598b01478b3Wei Huang        // a string indicating how many "unseen" messages there are.
597674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler
598674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        // TODO: show the most recent message in full plus some indication of older messages in the thread
599b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        if (messageCount > 1) {
600b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick            description = context.getString(R.string.notification_multiple,
601b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick                    Integer.toString(messageCount));
602b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        }
60372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
604b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // Make a startActivity() PendingIntent for the notification.
6051fdc24a996e1c2d6a1add1f40260c5e0380f3112Tom Taylor        PendingIntent pendingIntent = PendingIntent.getActivities(context, 0, intents,
606810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor                PendingIntent.FLAG_UPDATE_CURRENT);
60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
608b11a5086727c4b67c72ca605771fb37e12dcf803Ficus Kirkpatrick        // Update the notification.
609674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        noti.setContentTitle(title)
610674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler            .setContentText(description)
611674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler            .setContentIntent(pendingIntent);
612674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler
613674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        int defaults = 0;
61472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
61572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (isNew) {
616d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
617006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            String vibrateWhen;
618006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN)) {
619006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                vibrateWhen =
620006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                    sp.getString(MessagingPreferenceActivity.NOTIFICATION_VIBRATE_WHEN, null);
621006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            } else if (sp.contains(MessagingPreferenceActivity.NOTIFICATION_VIBRATE)) {
622006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                vibrateWhen = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE, false) ?
623006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                    context.getString(R.string.prefDefault_vibrate_true) :
624006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                    context.getString(R.string.prefDefault_vibrate_false);
625006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            } else {
626006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                vibrateWhen = context.getString(R.string.prefDefault_vibrateWhen);
627006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            }
628006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma
629006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            boolean vibrateAlways = vibrateWhen.equals("always");
630006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            boolean vibrateSilent = vibrateWhen.equals("silent");
631006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            AudioManager audioManager =
632006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
633006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            boolean nowSilent =
634006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma                audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE;
635006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma
636006d49271549ed639ffcd70d94c7650bb3514796Jim Shuma            if (vibrateAlways || vibrateSilent && nowSilent) {
637674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                defaults |= Notification.DEFAULT_VIBRATE;
63872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
63972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
640627007213deb59ef938c80353c8f3598b01478b3Wei Huang            String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE,
641627007213deb59ef938c80353c8f3598b01478b3Wei Huang                    null);
642674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler            noti.setSound(TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr));
64372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
64472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
645674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        defaults |= Notification.DEFAULT_LIGHTS;
646674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler
647674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        noti.setDefaults(defaults);
64872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
64970f5af8fd89d66ae246a805d10a50540746319aaWei Huang        // set up delete intent
650674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        noti.setDeleteIntent(PendingIntent.getBroadcast(context, 0,
651674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                sNotificationOnDeleteIntent, 0));
65270f5af8fd89d66ae246a805d10a50540746319aaWei Huang
65372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        NotificationManager nm = (NotificationManager)
65472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            context.getSystemService(Context.NOTIFICATION_SERVICE);
65572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
656674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        final Notification notification;
657674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        if (messageCount == 1) {
658674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler            notification = new Notification.BigTextStyle(noti)
659674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                .bigText(description)
660674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler                .build();
661674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        } else {
662674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler            notification = noti.getNotification();
663674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler        }
664674b5045f39aedf85e6a7e38237860d000f46de0Daniel Sandler
66572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        nm.notify(NOTIFICATION_ID, notification);
66672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
66772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
66872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected static CharSequence buildTickerMessage(
66972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Context context, String address, String subject, String body) {
67033a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick        String displayAddress = Contact.get(address, true).getName();
6715a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
67272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        StringBuilder buf = new StringBuilder(
67372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                displayAddress == null
67472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ? ""
67572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                : displayAddress.replace('\n', ' ').replace('\r', ' '));
67672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        buf.append(':').append(' ');
67772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
67872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int offset = buf.length();
67972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!TextUtils.isEmpty(subject)) {
68072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            subject = subject.replace('\n', ' ').replace('\r', ' ');
68172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            buf.append(subject);
68272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            buf.append(' ');
68372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
68472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
68572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!TextUtils.isEmpty(body)) {
68672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            body = body.replace('\n', ' ').replace('\r', ' ');
68772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            buf.append(body);
68872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
68972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
69072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SpannableString spanText = new SpannableString(buf.toString());
69172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        spanText.setSpan(new StyleSpan(Typeface.BOLD), 0, offset,
69272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
69372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
69472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return spanText;
69572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
69672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
69772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static String getMmsSubject(String sub, int charset) {
69872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return TextUtils.isEmpty(sub) ? ""
69972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                : new EncodedStringValue(charset, PduPersister.getBytes(sub)).getString();
70072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
70172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
70272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void notifyDownloadFailed(Context context, long threadId) {
703b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick        notifyFailed(context, true, threadId, false);
70472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
70572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7065d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project    public static void notifySendFailed(Context context) {
707b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick        notifyFailed(context, false, 0, false);
70872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
70972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
710b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick    public static void notifySendFailed(Context context, boolean noisy) {
711b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick        notifyFailed(context, false, 0, noisy);
712b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick    }
7135a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
714b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick    private static void notifyFailed(Context context, boolean isDownload, long threadId,
715b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick                                     boolean noisy) {
71672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // TODO factor out common code for creating notifications
717d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor        boolean enabled = MessagingPreferenceActivity.getNotificationEnabled(context);
71872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!enabled) {
71972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return;
72072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
72172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
72272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        NotificationManager nm = (NotificationManager)
72372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                context.getSystemService(Context.NOTIFICATION_SERVICE);
7245a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
72572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Strategy:
72672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // a. If there is a single failure notification, tapping on the notification goes
72772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        //    to the compose view.
7285a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor        // b. If there are two failure it stays in the thread view. Selecting one undelivered
72972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        //    thread will dismiss one undelivered notification but will still display the
73072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        //    notification.If you select the 2nd undelivered one it will dismiss the notification.
7315a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
7327015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        long[] msgThreadId = {0, 1};    // Dummy initial values, just to initialize the memory
73372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int totalFailedCount = getUndeliveredMessageCount(context, msgThreadId);
7347015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        if (totalFailedCount == 0 && !isDownload) {
7357015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev            return;
7367015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        }
7377015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // The getUndeliveredMessageCount method puts a non-zero value in msgThreadId[1] if all
7387015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // failures are from the same thread.
7397015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // If isDownload is true, we're dealing with 1 specific failure; therefore "all failed" are
7407015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // indeed in the same thread since there's only 1.
7417015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        boolean allFailedInSameThread = (msgThreadId[1] != 0) || isDownload;
7425a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
74372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Intent failedIntent;
74472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Notification notification = new Notification();
74572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String title;
74672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String description;
74772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (totalFailedCount > 1) {
74872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            description = context.getString(R.string.notification_failed_multiple,
74972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Integer.toString(totalFailedCount));
75072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            title = context.getString(R.string.notification_failed_multiple_title);
75172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
75272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            title = isDownload ?
75372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        context.getString(R.string.message_download_failed_title) :
75472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        context.getString(R.string.message_send_failed_title);
7555a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
75672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            description = context.getString(R.string.message_failed_body);
7577015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        }
7587015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev
7597015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        if (allFailedInSameThread) {
760836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project            failedIntent = new Intent(context, ComposeMessageActivity.class);
76195817b166d415114bac89ca0946c3717ae229526Tom Taylor            if (isDownload) {
76295817b166d415114bac89ca0946c3717ae229526Tom Taylor                // When isDownload is true, the valid threadId is passed into this function.
76395817b166d415114bac89ca0946c3717ae229526Tom Taylor                failedIntent.putExtra("failed_download_flag", true);
76495817b166d415114bac89ca0946c3717ae229526Tom Taylor            } else {
7657015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev                threadId = msgThreadId[0];
76695817b166d415114bac89ca0946c3717ae229526Tom Taylor                failedIntent.putExtra("undelivered_flag", true);
7675a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor            }
7685a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor            failedIntent.putExtra("thread_id", threadId);
7697015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        } else {
7707015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev            failedIntent = new Intent(context, ConversationList.class);
77172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
77272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
773b92b26763e49fd9cc34d382dee4d764ef163bde5Ficus Kirkpatrick        failedIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
77472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        PendingIntent pendingIntent = PendingIntent.getActivity(
775810fae756f4d2db00b35d7c9dfead252737abdacTom Taylor                context, 0, failedIntent, PendingIntent.FLAG_UPDATE_CURRENT);
77672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
77772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        notification.icon = R.drawable.stat_notify_sms_failed;
77872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
77972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        notification.tickerText = title;
78072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
78172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        notification.setLatestEventInfo(context, title, description, pendingIntent);
78272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
783b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick        if (noisy) {
784d83675687b1ef742c33bffe8195d7b1852c2c01dTom Taylor            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
785e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang            boolean vibrate = sp.getBoolean(MessagingPreferenceActivity.NOTIFICATION_VIBRATE,
786e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang                    false /* don't vibrate by default */);
787b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick            if (vibrate) {
788b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick                notification.defaults |= Notification.DEFAULT_VIBRATE;
789b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick            }
79072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
791e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang            String ringtoneStr = sp.getString(MessagingPreferenceActivity.NOTIFICATION_RINGTONE,
792e3baaa51cd25b52c7a24e381319926b9da00abdfWei Huang                    null);
793b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick            notification.sound = TextUtils.isEmpty(ringtoneStr) ? null : Uri.parse(ringtoneStr);
794b3cb9bbf929f70cb4855f03e4bfbed749022cf1bFicus Kirkpatrick        }
7955a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
79672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (isDownload) {
79772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            nm.notify(DOWNLOAD_FAILED_NOTIFICATION_ID, notification);
79872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
79972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            nm.notify(MESSAGE_FAILED_NOTIFICATION_ID, notification);
80072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
80172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
8025a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
8037015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev    /**
8047015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     * Query the DB and return the number of undelivered messages (total for both SMS and MMS)
8057015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     * @param context The context
8067015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     * @param threadIdResult A container to put the result in, according to the following rules:
8077015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     *  threadIdResult[0] contains the thread id of the first message.
8087015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     *  threadIdResult[1] is nonzero if the thread ids of all the messages are the same.
8097015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     *  You can pass in null for threadIdResult.
8107015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     *  You can pass in a threadIdResult of size 1 to avoid the comparison of each thread id.
8117015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     */
81272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static int getUndeliveredMessageCount(Context context, long[] threadIdResult) {
81372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor undeliveredCursor = SqliteWrapper.query(context, context.getContentResolver(),
814c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                UNDELIVERED_URI, MMS_THREAD_ID_PROJECTION, "read=0", null, null);
81572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (undeliveredCursor == null) {
81672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return 0;
81772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
81872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int count = undeliveredCursor.getCount();
81972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
82072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (threadIdResult != null && undeliveredCursor.moveToFirst()) {
82172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                threadIdResult[0] = undeliveredCursor.getLong(0);
8225a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
8232f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                if (threadIdResult.length >= 2) {
8242f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                    // Test to see if all the undelivered messages belong to the same thread.
8252f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                    long firstId = threadIdResult[0];
8262f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                    while (undeliveredCursor.moveToNext()) {
8272f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                        if (undeliveredCursor.getLong(0) != firstId) {
8282f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                            firstId = 0;
8292f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                            break;
8302f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                        }
8312f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                    }
8322f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                    threadIdResult[1] = firstId;    // non-zero if all ids are the same
8332f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                }
83472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
83572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } finally {
83672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            undeliveredCursor.close();
83772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
83872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return count;
83972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
84072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
841b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor    public static void nonBlockingUpdateSendFailedNotification(final Context context) {
842b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor        new AsyncTask<Void, Void, Integer>() {
843b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor            protected Integer doInBackground(Void... none) {
844b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                return getUndeliveredMessageCount(context, null);
845b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor            }
846b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor
847b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor            protected void onPostExecute(Integer result) {
848b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                if (result < 1) {
849b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                    cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID);
850b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                } else {
851b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                    // rebuild and adjust the message count if necessary.
852b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                    notifySendFailed(context);
853b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                }
854b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor            }
855b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor        }.execute();
85672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
8575a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
8585a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor    /**
8592f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project     *  If all the undelivered messages belong to "threadId", cancel the notification.
8602f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project     */
8612f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project    public static void updateSendFailedNotificationForThread(Context context, long threadId) {
8622f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project        long[] msgThreadId = {0, 0};
8635a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor        if (getUndeliveredMessageCount(context, msgThreadId) > 0
8642f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                && msgThreadId[0] == threadId
8652f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project                && msgThreadId[1] != 0) {
8662f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project            cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID);
8672f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project        }
8682f56791329cefc49ce79663b8d3aff50594cc1f3The Android Open Source Project    }
8695a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
87072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static int getDownloadFailedMessageCount(Context context) {
87172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Look for any messages in the MMS Inbox that are of the type
87272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // NOTIFICATION_IND (i.e. not already downloaded) and in the
87372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // permanent failure state.  If there are none, cancel any
87472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // failed download notification.
87572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor c = SqliteWrapper.query(context, context.getContentResolver(),
87672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Mms.Inbox.CONTENT_URI, null,
87772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Mms.MESSAGE_TYPE + "=" +
87872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    String.valueOf(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) +
87972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                " AND " + Mms.STATUS + "=" +
88072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    String.valueOf(DownloadManager.STATE_PERMANENT_FAILURE),
88172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                null, null);
88272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (c == null) {
88372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return 0;
88472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
88572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int count = c.getCount();
88672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        c.close();
88772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return count;
88872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
88972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
89072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void updateDownloadFailedNotification(Context context) {
89172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (getDownloadFailedMessageCount(context) < 1) {
89272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            cancelNotification(context, DOWNLOAD_FAILED_NOTIFICATION_ID);
89372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
89472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
8955a73318ac906b37eb5634a6975a8a26ef5ed36efTom Taylor
89695817b166d415114bac89ca0946c3717ae229526Tom Taylor    public static boolean isFailedToDeliver(Intent intent) {
89795817b166d415114bac89ca0946c3717ae229526Tom Taylor        return (intent != null) && intent.getBooleanExtra("undelivered_flag", false);
89895817b166d415114bac89ca0946c3717ae229526Tom Taylor    }
89995817b166d415114bac89ca0946c3717ae229526Tom Taylor
90095817b166d415114bac89ca0946c3717ae229526Tom Taylor    public static boolean isFailedToDownload(Intent intent) {
90195817b166d415114bac89ca0946c3717ae229526Tom Taylor        return (intent != null) && intent.getBooleanExtra("failed_download_flag", false);
90295817b166d415114bac89ca0946c3717ae229526Tom Taylor    }
903c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
904c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    /**
905c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * Get the thread ID of the SMS message with the given URI
906c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param context The context
907c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param uri The URI of the SMS message
908c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @return The thread ID, or THREAD_NONE if the URI contains no entries
909c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     */
910c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    public static long getSmsThreadId(Context context, Uri uri) {
911c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        Cursor cursor = SqliteWrapper.query(
912c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            context,
913c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            context.getContentResolver(),
914c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            uri,
915c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            SMS_THREAD_ID_PROJECTION,
916c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            null,
917c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            null,
918c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            null);
919c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
920c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        if (cursor == null) {
921c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            return THREAD_NONE;
922c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
923c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
924c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        try {
925c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            if (cursor.moveToFirst()) {
926c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                return cursor.getLong(cursor.getColumnIndex(Sms.THREAD_ID));
927c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            } else {
928c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                return THREAD_NONE;
929c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            }
930c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        } finally {
931c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            cursor.close();
932c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
933c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    }
934c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
935c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    /**
936c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * Get the thread ID of the MMS message with the given URI
937c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param context The context
938c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @param uri The URI of the SMS message
939c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     * @return The thread ID, or THREAD_NONE if the URI contains no entries
940c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev     */
941c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    public static long getThreadId(Context context, Uri uri) {
942c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        Cursor cursor = SqliteWrapper.query(
943c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                context,
944c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                context.getContentResolver(),
945c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                uri,
946c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                MMS_THREAD_ID_PROJECTION,
947c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                null,
948c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                null,
949c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                null);
950c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
951c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        if (cursor == null) {
952c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            return THREAD_NONE;
953c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
954c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev
955c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        try {
956c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            if (cursor.moveToFirst()) {
957c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                return cursor.getLong(cursor.getColumnIndex(Mms.THREAD_ID));
958c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            } else {
959c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                return THREAD_NONE;
960c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            }
961c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        } finally {
962c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            cursor.close();
963c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        }
964c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev    }
96572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
966